none
Change audio input RRS feed

  • Question

  • There is some way to change the audio input of my sistem ??

    I lista the audio with :

    Function GetAudioCardList() As List(Of String)
            'Add a reference to System.Management dll
            'Return audio list
            Dim Questions As New List(Of String)()
            Dim objSearcher As New ManagementObjectSearcher("SELECT * FROM Win32_SoundDevice")
            Dim objCollection As ManagementObjectCollection = objSearcher.Get()
    
            For Each obj As ManagementObject In objCollection
                Questions.Add(obj.GetPropertyValue("Caption").ToString())
            Next
    
            Return Questions
        End Function

    A want to change with my code.

    Thursday, December 21, 2017 10:02 PM

Answers

  • Ran-jj,  If your question has been answered,  then please do not forget to mark the post or posts that have answered your question as the answer(s).  Thanks.  8)

    Also,  here is a slightly upgraded version of my prior example.  The first example i posted would only set the selected device as the (default device).  This new example allows you to set the selected device as the (default communications device) and/or the (default device).

     This is the updated AudioEndPoints class code.  I explained in the last example how to add the class to your project.

    Imports System.Runtime.InteropServices
    
    Public Class AudioEndPoints
        ''' <summary>Sets the specified device as the default device and/or the default communications device.</summary>
        ''' <param name="devId">The string Id for the input or output device to set.</param>
        ''' <param name="SetAsDefaultDevice">Set to True to set this device as the default device.</param>
        ''' <param name="SetAsDefaultCommunicationDevice">Set to True to set this device as the default communications device.</param>
        Public Shared Sub SetDefaultEndPoint(devId As String, SetAsDefaultDevice As Boolean, SetAsDefaultCommunicationDevice As Boolean)
            Dim IPCV As IPolicyConfigVista = Nothing
            Dim oIPCV As Object = Nothing
            Try
                Dim IID_IPolicyConfigVista As Guid = New Guid("568b9108-44bf-40b4-9006-86afe5b5a620")
                Dim CLSID_CPolicyConfigVistaClient As Guid = New Guid("294935CE-F637-4E7C-A41B-AB255460B862")
                If CoCreateInstance(CLSID_CPolicyConfigVistaClient, Nothing, CLSCTX.CLSCTX_INPROC_SERVER, IID_IPolicyConfigVista, oIPCV) <> 0 Then
                    Throw New Exception("Failed:  CoCreateInstance")
                Else
                    IPCV = CType(oIPCV, IPolicyConfigVista)
                    If IPCV Is Nothing Then Throw New Exception("Failed: COM cast to IPolicyConfigVista")
                End If
                If SetAsDefaultDevice Then
                    IPCV.SetDefaultEndpoint(devId, ERole.eConsole)
                End If
                If SetAsDefaultCommunicationDevice Then
                    IPCV.SetDefaultEndpoint(devId, ERole.eCommunications)
                End If
            Finally
                If (IPCV IsNot Nothing) Then
                    While Marshal.ReleaseComObject(IPCV) > 0
                    End While
                    IPCV = Nothing
                End If
                If (oIPCV IsNot Nothing) Then
                    While Marshal.ReleaseComObject(oIPCV) > 0
                    End While
                    oIPCV = Nothing
                End If
            End Try
        End Sub
    
        ''' <summary>Returns an array of EndPointDeviceInfo classes which contain the information for each device found for the specified types.</summary>
        ''' <param name="DevType">Can be (eRender) to get only output devices, (eCapture) to get only the input devices, or (eAll) to get all input and output devices.</param>
        Public Shared Function GetEndPointNames(ByVal DevType As EDataFlow) As EndPointDeviceInfo()
            Dim immdevcolptr As IntPtr = IntPtr.Zero
            Dim devcnt As UInteger = 0
            Dim immdevcol As IMMDeviceCollection = Nothing
            Dim dvInfo As New List(Of EndPointDeviceInfo)
            Dim IMMDE As IMMDeviceEnumerator = Nothing
            Dim oIMMDE As Object = Nothing
            Try
                Dim IID_IUnknown As Guid = New Guid("00000000-0000-0000-C000-000000000046")
                Dim IMMDE_clsid As Guid = New Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")
                If CoCreateInstance(IMMDE_clsid, Nothing, CLSCTX.CLSCTX_INPROC_SERVER, IID_IUnknown, oIMMDE) <> 0 Then
                    Throw New Exception("Failed:  CoCreateInstance")
                Else
                    IMMDE = CType(oIMMDE, IMMDeviceEnumerator)
                    If IMMDE Is Nothing Then Throw New Exception("Failed: COM cast to IMMDeviceEnumerator")
                End If
    
                Dim res As Integer = IMMDE.EnumAudioEndpoints(DevType, IMMDeviceStatesFlags.DEVICE_STATE_ACTIVE, immdevcolptr)
                If res <> 0 Then
                    Throw New Exception("EnumAudioEndpoints Failed with error: 0x" & res.ToString("X"))
                End If
    
                immdevcol = CType(Marshal.GetObjectForIUnknown(immdevcolptr), IMMDeviceCollection)
    
                res = immdevcol.GetCount(devcnt)
                If res <> 0 Then
                    Throw New Exception("GetCount Failed with error: 0x" & res.ToString("X"))
                End If
    
                If devcnt > 0 Then
                    For i As UInteger = 0 To devcnt - 1UI
                        Dim immdevptr As IntPtr = IntPtr.Zero
                        res = immdevcol.Item(i, immdevptr)
                        If res = 0 Then
                            Dim immdev As IMMDevice = CType(Marshal.GetObjectForIUnknown(immdevptr), IMMDevice)
                            If immdev IsNot Nothing Then
                                Dim propstrptr As IntPtr = IntPtr.Zero
                                res = immdev.OpenPropertyStore(STGM_READ, propstrptr)
                                If res = 0 Then
                                    Dim propstor As IPropertyStore = CType(Marshal.GetObjectForIUnknown(propstrptr), IPropertyStore)
                                    If propstor IsNot Nothing Then
                                        Dim FriendlyName As String = ""
                                        Using varnt As New PropVariant
                                            propstor.GetValue(Device_FriendlyName, varnt)
                                            FriendlyName = varnt.Value
                                        End Using
    
                                        Dim Description As String = ""
                                        Using vrnt As New PropVariant
                                            propstor.GetValue(Device_DeviceDesc, vrnt)
                                            Description = vrnt.Value
                                        End Using
    
                                        Dim idString As String = ""
                                        immdev.GetId(idString)
    
                                        dvInfo.Add(New EndPointDeviceInfo(FriendlyName, idString, Description))
    
                                        Marshal.ReleaseComObject(propstor)
                                        propstor = Nothing
                                    End If
                                End If
                                Marshal.ReleaseComObject(immdev)
                                immdev = Nothing
                            End If
                        End If
                    Next
                End If
            Finally
                If immdevcol IsNot Nothing Then
                    Marshal.ReleaseComObject(immdevcol)
                    immdevcol = Nothing
                End If
                If (IMMDE IsNot Nothing) Then
                    While Marshal.ReleaseComObject(IMMDE) > 0
                    End While
                    IMMDE = Nothing
                End If
                If (oIMMDE IsNot Nothing) Then
                    While Marshal.ReleaseComObject(oIMMDE) > 0
                    End While
                    oIMMDE = Nothing
                End If
            End Try
            Return dvInfo.ToArray
        End Function
    
    
        Private Shared SPDRP_Guid As New Guid(&HA45C254EUI, &HDF1C, &H4EFD, &H80, &H20, &H67, &HD1, &H46, &HA8, &H50, &HE0)
        Private Shared ReadOnly Property Device_Manufacturer As PropertyKey
            Get
                Return New PropertyKey(SPDRP_Guid, 13)
            End Get
        End Property
        Private Shared ReadOnly Property Device_DeviceDesc As PropertyKey
            Get
                Return New PropertyKey(SPDRP_Guid, 2)
            End Get
        End Property
        Private Shared ReadOnly Property Device_FriendlyName As PropertyKey
            Get
                Return New PropertyKey(SPDRP_Guid, 14)
            End Get
        End Property
    
        Private Const STGM_READ As Integer = &H0 'used for the (stgmAccess) parameter of the (OpenPropertyStore) function in the (IMMDevice) interface.
    
        <ComImport(), Guid("0BD7A1BE-7A1A-44DB-8397-CC5392387B5E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IMMDeviceCollection
            Function GetCount(ByRef pcDevices As UInteger) As Integer
            Function Item(ByVal nDevice As UInteger, ByRef ppDevice As IntPtr) As Integer
        End Interface
    
        <ComImport(), Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IMMDeviceEnumerator
            Function EnumAudioEndpoints(<ComAliasName("MMDeviceAPILib.EDataFlow")> ByVal dataFlow As EDataFlow, ByVal dwStateMask As Integer, ByRef ppDevices As IntPtr) As Integer
            Function GetDefaultAudioEndpoint(<ComAliasName("MMDeviceAPILib.EDataFlow")> ByVal dataFlow As EDataFlow, <ComAliasName("MMDeviceAPILib.ERole")> ByVal role As ERole, ByRef ppEndpoint As IntPtr) As Boolean
            Function GetDevice(ByVal pwstrId As String, ByRef ppDevice As IntPtr) As Integer
            Function RegisterEndpointNotificationCallback(ByVal pClient As IMMNotificationClient) As Integer
            Function UnregisterEndpointNotificationCallback(ByVal pClient As IMMNotificationClient) As Integer
        End Interface
    
        <ComImport(), Guid("7991EEC9-7E89-4D85-8390-6C703CEC60C0"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IMMNotificationClient
            Sub OnDeviceStateChanged(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDeviceId As String, ByVal dwNewState As UInteger)
            Sub OnDeviceAdded(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDeviceId As String)
            Sub OnDeviceRemoved(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDeviceId As String)
            Sub OnDefaultDeviceChanged(<ComAliasName("MMDeviceAPILib.EDataFlow")> ByVal flow As EDataFlow, <ComAliasName("MMDeviceAPILib.ERole")> ByVal role As ERole, <MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDefaultDeviceId As String)
            Sub OnPropertyValueChanged(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDeviceId As String, ByVal key As PropertyKey)
        End Interface
    
        <ComImport(), Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IMMDevice
            Function Activate(ByRef iid As Guid, ByVal dwClsCtx As Integer, ByVal pActivationParams As IntPtr, ByRef ppInterface As IntPtr) As Boolean
            Function OpenPropertyStore(ByVal stgmAccess As Integer, ByRef ppProperties As IntPtr) As Integer
            Function GetId(<MarshalAs(UnmanagedType.LPWStr)> ByRef ppstrId As String) As Integer
            Function GetState(ByRef pdwState As IMMDeviceStatesFlags) As Integer
        End Interface
    
        <ComImport(), Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IPropertyStore
            Function GetCount(ByRef cProps As UInteger) As UInteger
            Function GetAt(ByVal iProp As UInteger, ByRef pkey As PropertyKey) As UInteger
            Function GetValue(ByRef key As PropertyKey, ByVal pv As PropVariant) As UInteger
            Function SetValue(ByRef key As PropertyKey, ByVal pv As PropVariant) As UInteger
            Function Commit() As UInteger
        End Interface
    
        <ComImport(), Guid("568b9108-44bf-40b4-9006-86afe5b5a620"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IPolicyConfigVista
            Function GetMixFormat(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByRef param1 As IntPtr) As Integer 'not available on Windows 7, use method from IPolicyConfig
            Function GetDeviceFormat(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByVal param1 As Integer, ByRef wfx As tWAVEFORMATEX) As Integer
            Function SetDeviceFormat(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByRef wfx1 As tWAVEFORMATEX, ByRef wfx2 As tWAVEFORMATEX) As Integer
            Function GetProcessingPeriod(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByVal param1 As Integer, ByRef param2 As Long, ByRef param3 As Long) As Integer 'not available on Windows 7, use method from IPolicyConfig
            Function SetProcessingPeriod(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByRef param1 As Long) As Integer 'not available on Windows 7, use method from IPolicyConfig
            Function GetShareMode(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByRef DeviceShareMode As IntPtr) As Integer 'not available on Windows 7, use method from IPolicyConfig
            Function SetShareMode(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByRef DeviceShareMode As IntPtr) As Integer 'not available on Windows 7, use method from IPolicyConfig
            Function GetPropertyValue(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByRef propKey As PropertyKey, ByRef propVar As PropVariant) As Integer
            Function SetPropertyValue(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByRef propKey As PropertyKey, ByRef propVar As PropVariant) As Integer
            Function SetDefaultEndpoint(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByVal eRole As ERole) As Integer
            Function SetEndpointVisibility(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByVal param1 As Integer) As Integer 'not available on Windows 7, use method from IPolicyConfig
        End Interface
    
        <Flags()>
        Private Enum IMMDeviceStatesFlags As Integer
            DEVICE_STATE_ACTIVE = &H1
            DEVICE_STATE_DISABLED = &H2
            DEVICE_STATE_NOTPRESENT = &H4
            DEVICE_STATE_UNPLUGGED = &H8
            DEVICE_STATE_ALL = &HF
        End Enum
    
        Public Enum EDataFlow As Integer
            eRender = &H0
            eCapture = &H1
            eAll = &H2
            EDataFlow_enum_count = &H3
        End Enum
    
        Private Enum ERole As Integer
            eConsole = &H0
            eMultimedia = &H1
            eCommunications = &H2
            ERole_enum_count = &H3
        End Enum
    
        <Flags()>
        Private Enum CLSCTX
            CLSCTX_INPROC_SERVER = &H1
            CLSCTX_INPROC_HANDLER = &H2
            CLSCTX_LOCAL_SERVER = &H4
            CLSCTX_INPROC_SERVER16 = &H8
            CLSCTX_REMOTE_SERVER = &H10
            CLSCTX_INPROC_HANDLER16 = &H20
            CLSCTX_RESERVED1 = &H40
            CLSCTX_RESERVED2 = &H80
            CLSCTX_RESERVED3 = &H100
            CLSCTX_RESERVED4 = &H200
            CLSCTX_NO_CODE_DOWNLOAD = &H400
            CLSCTX_RESERVED5 = &H800
            CLSCTX_NO_CUSTOM_MARSHAL = &H1000
            CLSCTX_ENABLE_CODE_DOWNLOAD = &H2000
            CLSCTX_NO_FAILURE_LOG = &H4000
            CLSCTX_DISABLE_AAA = &H8000
            CLSCTX_ENABLE_AAA = &H10000
            CLSCTX_FROM_DEFAULT_CONTEXT = &H20000
            CLSCTX_INPROC = CLSCTX_INPROC_SERVER Or CLSCTX_INPROC_HANDLER
            CLSCTX_SERVER = CLSCTX_INPROC_SERVER Or CLSCTX_LOCAL_SERVER Or CLSCTX_REMOTE_SERVER
            CLSCTX_ALL = CLSCTX_SERVER Or CLSCTX_INPROC_HANDLER
        End Enum
    
        <StructLayout(LayoutKind.Sequential, Pack:=4)>
        Private Structure PropertyKey
            Private m_formatId As Guid
            Private m_propertyId As Integer
            Public ReadOnly Property FormatId() As Guid
                Get
                    Return Me.m_formatId
                End Get
            End Property
            Public ReadOnly Property PropertyId() As Integer
                Get
                    Return Me.m_propertyId
                End Get
            End Property
            Public Sub New(ByVal formatId As Guid, ByVal propertyId As Integer)
                Me.m_formatId = formatId
                Me.m_propertyId = propertyId
            End Sub
        End Structure
    
        <StructLayout(LayoutKind.Sequential)>
        Private Structure tWAVEFORMATEX
            Public wFormatTag As UShort
            Public nChannels As UShort
            Public nSamplesPerSec As UInteger
            Public nAvgBytesPerSec As UInteger
            Public nBlockAlign As UShort
            Public wBitsPerSample As UShort
            Public cbSize As UShort
        End Structure
    
        <StructLayout(LayoutKind.Explicit)>
        Private NotInheritable Class PropVariant
            Implements IDisposable
    
            <FieldOffset(0)> Private valueType As UShort
            <FieldOffset(8)> Private ptr As IntPtr
    
            Public Property VarType() As VarEnum
                Get
                    Return DirectCast(CInt(Me.valueType), VarEnum)
                End Get
                Set(ByVal value As VarEnum)
                    Me.valueType = CUShort(value)
                End Set
            End Property
    
            Public ReadOnly Property IsNullOrEmpty() As Boolean
                Get
                    Return (Me.valueType = CUShort(VarEnum.VT_EMPTY) OrElse Me.valueType = CUShort(VarEnum.VT_NULL))
                End Get
            End Property
    
            Public ReadOnly Property Value() As String
                Get
                    Return Marshal.PtrToStringUni(Me.ptr)
                End Get
            End Property
    
            Public Sub New()
            End Sub
    
            Public Sub New(ByVal value As String)
                If value Is Nothing Then
                    Throw New ArgumentNullException("value")
                End If
    
                Me.valueType = CUShort(VarEnum.VT_LPWSTR)
                Me.ptr = Marshal.StringToCoTaskMemUni(value)
            End Sub
    
            Protected Overrides Sub Finalize()
                Try
                    Dispose()
                Finally
                    MyBase.Finalize()
                End Try
            End Sub
    
            Public Sub Dispose() Implements IDisposable.Dispose
                PropVariantClear(Me)
                GC.SuppressFinalize(Me)
            End Sub
        End Class
    
        <DllImport("Ole32.dll", PreserveSig:=False)> Private Shared Sub PropVariantClear(<[In](), Out()> ByVal pvar As PropVariant)
        End Sub
    
        <DllImport("ole32.Dll")>
        Private Shared Function CoCreateInstance(ByRef clsid As Guid, <MarshalAs(UnmanagedType.IUnknown)> ByVal inner As Object, ByVal context As Integer, ByRef uuid As Guid, <MarshalAs(UnmanagedType.IUnknown)> ByRef rReturnedComObject As Object) As Integer
        End Function
    End Class
    
    
    Public Class EndPointDeviceInfo
        Public ReadOnly Property FriendlyName As String
        Public ReadOnly Property Description As String
        Public ReadOnly Property Id As String
    
        Public Sub New(devName As String, devId As String, devDescription As String)
            _FriendlyName = devName
            _Id = devId
            _Description = devDescription
        End Sub
    
        Public Overrides Function ToString() As String
            Return FriendlyName
        End Function
    End Class
    
     

     I have also set up the example form differently too.  So,  these are the controls and the names of them that are required to replicate my example form as seen in the animated gif at the bottom of this post.

     Add 2 RadioButton controls and name them (RadioButton_OutputDevices) and (RadioButton_InputDevices).

     Add 2 CheckBox controls and name them (CheckBox_DefaultDevice) and (CheckBox_DefaultCommunicationsDevice).

     Add 1 ComboBox control and name it (ComboBox_EndPointDevices).

     Add 1 Button control and name it (Button_SetDefault).

     Now you can add this code to the form class....

    Public Class Form1
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            RadioButton_OutputDevices.Checked = True
            ComboBox_EndPointDevices.DropDownStyle = ComboBoxStyle.DropDownList
        End Sub
    
        Private Sub Button_SetDefault_Click(sender As Object, e As EventArgs) Handles Button_SetDefault.Click
            If ComboBox_EndPointDevices.SelectedItem IsNot Nothing AndAlso (CheckBox_DefaultDevice.Checked OrElse CheckBox_DefaultCommunicationsDevice.Checked) Then
                Dim epdi As EndPointDeviceInfo = CType(ComboBox_EndPointDevices.SelectedItem, EndPointDeviceInfo)
                AudioEndPoints.SetDefaultEndPoint(epdi.Id, CheckBox_DefaultDevice.Checked, CheckBox_DefaultCommunicationsDevice.Checked)
            End If
        End Sub
    
        Private Sub RadioButton_OutputDevices_CheckedChanged(sender As Object, e As EventArgs) Handles RadioButton_OutputDevices.CheckedChanged
            If RadioButton_OutputDevices.Checked Then
                ComboBox_EndPointDevices.DataSource = AudioEndPoints.GetEndPointNames(AudioEndPoints.EDataFlow.eRender)
            Else
                ComboBox_EndPointDevices.DataSource = AudioEndPoints.GetEndPointNames(AudioEndPoints.EDataFlow.eCapture)
            End If
        End Sub
    End Class
    
     

     This shows it setting the the Venus microphone as the default device and the default communications device.  Then setting the SigmaTel microphone as the default communications device.  Lastly, i set the SigmaTel microphone as the default device.  This can be done for the Input or Output devices.


    If you say it can`t be done then i`ll try it

    • Marked as answer by Ran-jj Tuesday, January 23, 2018 2:14 AM
    Tuesday, January 9, 2018 9:49 PM

All replies

  • Hi Ran-jj,

    I test your code and get list.count=0, so I think there is some error in your code, I use the flowing code to get audio devices.

    <DllImport("winmm.dll", SetLastError:=True)>
        Private Shared Function waveOutGetNumDevs() As UInteger
        End Function
    
        <DllImport("winmm.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
        Public Shared Function waveOutGetDevCaps(ByVal hwo As UInteger, ByRef pwoc As WAVEOUTCAPS, ByVal cbwoc As UInteger) As UInteger
        End Function
    
        <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)>
        Public Structure WAVEOUTCAPS
    
            Public wMid As UShort
    
            Public wPid As UShort
    
            Public vDriverVersion As UInteger
    
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=32)>
            Public szPname As String
    
            Public dwFormats As UInteger
    
            Public wChannels As UShort
    
            Public wReserved1 As UShort
    
            Public dwSupport As UInteger
        End Structure
    
    
     Public Shared Function GetSoundDevices() As String()
            Dim devices As UInteger = waveOutGetNumDevs()
            Dim result As String() = New String(devices - 1) {}
            Dim caps As WAVEOUTCAPS = New WAVEOUTCAPS()
            For i As UInteger = 0 To devices - 1
                waveOutGetDevCaps(i, caps, CUInt(Marshal.SizeOf(caps)))
                result(i) = caps.szPname
            Next
    
            Return result
        End Function

    And you said that you wan to change audio input of the system, your mean that you want to change the audio devices in the system?

    Best Regards,

    Cherry


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Friday, December 22, 2017 5:25 AM
    Moderator
  • So i want to switch the audio card default.

    The default Playback divice

    Thursday, January 4, 2018 1:37 AM
  • So i want to switch the audio card default.

    The default Playback divice

    This is actually a lot more complicated than it should be, due to the lack of API function calls, but the project below should help:

    https://sdae.codeplex.com/


    Paul ~~~~ Microsoft MVP (Visual Basic)

    Thursday, January 4, 2018 2:41 PM
  • Windows uses IPolicyConfig.SetDefaultEndpoint

    Not officially documented but you can find samples on Google...


    Thursday, January 4, 2018 2:50 PM
  •  As Paul said,  it is much more complex than it should be since they started using Core Audio APIs.  They started using these in windows Vista and any newer OS's.  Using them in managed code like Vb.Net adds even more complexity to it because you need to create all the signatures for the Interfaces,  Enumerations,  Structures,  and Functions in your code.

     As Castorix31 said,  you can use the IPolicyConfig interface which MS seems to have mysteriously forgotten to document.  However,  you need to use much more than that interface just to get the device names and most important,  the device Id.  This specific Id is needed in order to call the SetDefaultEndpoint function of the IPolicyConfig interface.

     Here is an example that has basically only what you need to get a list of the audio Capture and/or Render devices and allow you to set the Default devices.  Capture devices are the input devices and Render devices are the output devices.

     You can test this by creating a new Form project with 2 ComboBoxes and 2 Buttons added to the form.  Name the ComboBoxes as "ComboBox_RendererEndPoints" and "ComboBox_CaptureEndPoints".  Name the two buttons as "Button_SetDefaultRenderer" and "Button_SetDefaultCapture".

     I would set the Text of the buttons and there locations so you know which button is for setting the default Capture devices and which is for Renderer devices.

     Now add a Class to your project by clicking (Project) on the VS menu and selecting (Add Class).  Change it's name from "Class1.vb" to "AudioEndPoints.vb" and click the (Add) button.  Then copy this code into it...

    Imports System.Runtime.InteropServices
    
    Public Class AudioEndPoints
        Public Shared Sub SetDefaultEndPoint(devId As String)
            Dim IPCV As IPolicyConfigVista = Nothing
            Dim oIPCV As Object = Nothing
            Try
                Dim IID_IPolicyConfigVista As Guid = New Guid("568b9108-44bf-40b4-9006-86afe5b5a620")
                Dim CLSID_CPolicyConfigVistaClient As Guid = New Guid("294935CE-F637-4E7C-A41B-AB255460B862")
                If CoCreateInstance(CLSID_CPolicyConfigVistaClient, Nothing, CLSCTX.CLSCTX_INPROC_SERVER, IID_IPolicyConfigVista, oIPCV) <> 0 Then
                    Throw New Exception("Failed:  CoCreateInstance")
                Else
                    IPCV = CType(oIPCV, IPolicyConfigVista)
                    If IPCV Is Nothing Then Throw New Exception("Failed: COM cast to IPolicyConfigVista")
                End If
                IPCV.SetDefaultEndpoint(devId, ERole.eConsole)
            Finally
                If (IPCV IsNot Nothing) Then
                    While Marshal.ReleaseComObject(IPCV) > 0
                    End While
                    IPCV = Nothing
                End If
                If (oIPCV IsNot Nothing) Then
                    While Marshal.ReleaseComObject(oIPCV) > 0
                    End While
                    oIPCV = Nothing
                End If
            End Try
        End Sub
    
        Public Shared Function GetEndPointNames(ByVal DevType As EDataFlow) As EndPointDeviceInfo()
            Dim immdevcolptr As IntPtr = IntPtr.Zero
            Dim devcnt As UInteger = 0
            Dim immdevcol As IMMDeviceCollection = Nothing
            Dim dvInfo As New List(Of EndPointDeviceInfo)
            Dim IMMDE As IMMDeviceEnumerator = Nothing
            Dim oIMMDE As Object = Nothing
            Try
                Dim IID_IUnknown As Guid = New Guid("00000000-0000-0000-C000-000000000046")
                Dim IMMDE_clsid As Guid = New Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")
                If CoCreateInstance(IMMDE_clsid, Nothing, CLSCTX.CLSCTX_INPROC_SERVER, IID_IUnknown, oIMMDE) <> 0 Then
                    Throw New Exception("Failed:  CoCreateInstance")
                Else
                    IMMDE = CType(oIMMDE, IMMDeviceEnumerator)
                    If IMMDE Is Nothing Then Throw New Exception("Failed: COM cast to IMMDeviceEnumerator")
                End If
    
                Dim res As Integer = IMMDE.EnumAudioEndpoints(DevType, IMMDeviceStatesFlags.DEVICE_STATE_ACTIVE, immdevcolptr)
                If res <> 0 Then
                    Throw New Exception("EnumAudioEndpoints Failed with error: " & res.ToString)
                End If
    
                immdevcol = CType(Marshal.GetObjectForIUnknown(immdevcolptr), IMMDeviceCollection)
    
                res = immdevcol.GetCount(devcnt)
                If res <> 0 Then
                    Throw New Exception("GetCount Failed with error: " & res.ToString)
                End If
    
                If devcnt > 0 Then
                    For i As UInteger = 0 To devcnt - 1UI
    
                        Dim immdevptr As IntPtr = IntPtr.Zero
                        res = immdevcol.Item(i, immdevptr)
                        If res = 0 Then
    
                            Dim immdev As IMMDevice = CType(Marshal.GetObjectForIUnknown(immdevptr), IMMDevice)
                            If immdev IsNot Nothing Then
    
                                Dim propstrptr As IntPtr = IntPtr.Zero
                                res = immdev.OpenPropertyStore(STGM_READ, propstrptr)
                                If res = 0 Then
    
                                    Dim propstor As IPropertyStore = CType(Marshal.GetObjectForIUnknown(propstrptr), IPropertyStore)
                                    If propstor IsNot Nothing Then
    
                                        Dim FriendlyName As String = ""
                                        Using varnt As New PropVariant
                                            propstor.GetValue(Device_FriendlyName, varnt)
                                            FriendlyName = varnt.Value
                                        End Using
    
                                        Dim Description As String = ""
                                        Using vrnt As New PropVariant
                                            propstor.GetValue(Device_DeviceDesc, vrnt)
                                            Description = vrnt.Value
                                        End Using
    
                                        Dim idString As String = ""
                                        immdev.GetId(idString)
    
                                        dvInfo.Add(New EndPointDeviceInfo(FriendlyName, idString, Description))
    
                                        Marshal.ReleaseComObject(propstor)
                                        propstor = Nothing
                                    End If
    
                                End If
    
                                Marshal.ReleaseComObject(immdev)
                                immdev = Nothing
                            End If
    
                        End If
                    Next
    
                End If
            Finally
                If immdevcol IsNot Nothing Then
                    Marshal.ReleaseComObject(immdevcol)
                    immdevcol = Nothing
                End If
                If (IMMDE IsNot Nothing) Then
                    While Marshal.ReleaseComObject(IMMDE) > 0
                    End While
                    IMMDE = Nothing
                End If
                If (oIMMDE IsNot Nothing) Then
                    While Marshal.ReleaseComObject(oIMMDE) > 0
                    End While
                    oIMMDE = Nothing
                End If
            End Try
            Return dvInfo.ToArray
        End Function
    
    
        Private Shared SPDRP_Guid As New Guid(&HA45C254EUI, &HDF1C, &H4EFD, &H80, &H20, &H67, &HD1, &H46, &HA8, &H50, &HE0)
        Private Shared ReadOnly Property Device_Manufacturer As PropertyKey
            Get
                Return New PropertyKey(SPDRP_Guid, 13)
            End Get
        End Property
        Private Shared ReadOnly Property Device_DeviceDesc As PropertyKey
            Get
                Return New PropertyKey(SPDRP_Guid, 2)
            End Get
        End Property
        Private Shared ReadOnly Property Device_FriendlyName As PropertyKey
            Get
                Return New PropertyKey(SPDRP_Guid, 14)
            End Get
        End Property
    
        Private Const STGM_READ As Integer = &H0
    
        <Guid("0BD7A1BE-7A1A-44DB-8397-CC5392387B5E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IMMDeviceCollection
            Function GetCount(ByRef pcDevices As UInteger) As Integer
            Function Item(ByVal nDevice As UInteger, ByRef ppDevice As IntPtr) As Integer
        End Interface
    
        <Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IMMDeviceEnumerator
            Function EnumAudioEndpoints(<ComAliasName("MMDeviceAPILib.EDataFlow")> ByVal dataFlow As EDataFlow, ByVal dwStateMask As Integer, ByRef ppDevices As IntPtr) As Integer
            Function GetDefaultAudioEndpoint(<ComAliasName("MMDeviceAPILib.EDataFlow")> ByVal dataFlow As EDataFlow, <ComAliasName("MMDeviceAPILib.ERole")> ByVal role As ERole, ByRef ppEndpoint As IntPtr) As Boolean
            Function GetDevice(ByVal pwstrId As String, ByRef ppDevice As IntPtr) As Integer
            Function RegisterEndpointNotificationCallback(ByVal pClient As IMMNotificationClient) As Integer
            Function UnregisterEndpointNotificationCallback(ByVal pClient As IMMNotificationClient) As Integer
        End Interface
    
        <Guid("7991EEC9-7E89-4D85-8390-6C703CEC60C0"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IMMNotificationClient
            Sub OnDeviceStateChanged(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDeviceId As String, ByVal dwNewState As UInteger)
            Sub OnDeviceAdded(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDeviceId As String)
            Sub OnDeviceRemoved(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDeviceId As String)
            Sub OnDefaultDeviceChanged(<ComAliasName("MMDeviceAPILib.EDataFlow")> ByVal flow As EDataFlow, <ComAliasName("MMDeviceAPILib.ERole")> ByVal role As ERole, <MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDefaultDeviceId As String)
            Sub OnPropertyValueChanged(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDeviceId As String, ByVal key As PropertyKey)
        End Interface
    
        <Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IMMDevice
            Function Activate(ByRef iid As Guid, ByVal dwClsCtx As Integer, ByVal pActivationParams As IntPtr, ByRef ppInterface As IntPtr) As Boolean
            Function OpenPropertyStore(ByVal stgmAccess As Integer, ByRef ppProperties As IntPtr) As Integer
            Function GetId(<MarshalAs(UnmanagedType.LPWStr)> ByRef ppstrId As String) As Integer
            Function GetState(ByRef pdwState As IMMDeviceStatesFlags) As Integer
        End Interface
    
        <ComImport(), Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IPropertyStore
            Function GetCount(ByRef cProps As UInteger) As UInteger
            Function GetAt(ByVal iProp As UInteger, ByRef pkey As PropertyKey) As UInteger
            Function GetValue(ByRef key As PropertyKey, ByVal pv As PropVariant) As UInteger
            Function SetValue(ByRef key As PropertyKey, ByVal pv As PropVariant) As UInteger
            Function Commit() As UInteger
        End Interface
    
        <ComImport(), Guid("568b9108-44bf-40b4-9006-86afe5b5a620"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IPolicyConfigVista
            Function GetMixFormat(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByRef param1 As IntPtr) As Integer 'not available on Windows 7, use method from IPolicyConfig
            Function GetDeviceFormat(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByVal param1 As Integer, ByRef wfx As tWAVEFORMATEX) As Integer
            Function SetDeviceFormat(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByRef wfx1 As tWAVEFORMATEX, ByRef wfx2 As tWAVEFORMATEX) As Integer
            Function GetProcessingPeriod(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByVal param1 As Integer, ByRef param2 As Long, ByRef param3 As Long) As Integer 'not available on Windows 7, use method from IPolicyConfig
            Function SetProcessingPeriod(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByRef param1 As Long) As Integer 'not available on Windows 7, use method from IPolicyConfig
            Function GetShareMode(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByRef DeviceShareMode As IntPtr) As Integer 'not available on Windows 7, use method from IPolicyConfig
            Function SetShareMode(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByRef DeviceShareMode As IntPtr) As Integer 'not available on Windows 7, use method from IPolicyConfig
            Function GetPropertyValue(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByRef propKey As PropertyKey, ByRef propVar As PropVariant) As Integer
            Function SetPropertyValue(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByRef propKey As PropertyKey, ByRef propVar As PropVariant) As Integer
            Function SetDefaultEndpoint(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByVal eRole As ERole) As Integer
            Function SetEndpointVisibility(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByVal param1 As Integer) As Integer 'not available on Windows 7, use method from IPolicyConfig
        End Interface
    
        <Flags()>
        Private Enum IMMDeviceStatesFlags As Integer
            DEVICE_STATE_ACTIVE = &H1
            DEVICE_STATE_DISABLED = &H2
            DEVICE_STATE_NOTPRESENT = &H4
            DEVICE_STATE_UNPLUGGED = &H8
            DEVICE_STATE_ALL = &HF
        End Enum
    
        Public Enum EDataFlow As Integer
            eRender = &H0
            eCapture = &H1
            eAll = &H2
            EDataFlow_enum_count = &H3
        End Enum
    
        Private Enum ERole As Integer
            eConsole = &H0
            eMultimedia = &H1
            eCommunications = &H2
            ERole_enum_count = &H3
        End Enum
    
        <Flags()>
        Private Enum CLSCTX
            CLSCTX_INPROC_SERVER = &H1
            CLSCTX_INPROC_HANDLER = &H2
            CLSCTX_LOCAL_SERVER = &H4
            CLSCTX_INPROC_SERVER16 = &H8
            CLSCTX_REMOTE_SERVER = &H10
            CLSCTX_INPROC_HANDLER16 = &H20
            CLSCTX_RESERVED1 = &H40
            CLSCTX_RESERVED2 = &H80
            CLSCTX_RESERVED3 = &H100
            CLSCTX_RESERVED4 = &H200
            CLSCTX_NO_CODE_DOWNLOAD = &H400
            CLSCTX_RESERVED5 = &H800
            CLSCTX_NO_CUSTOM_MARSHAL = &H1000
            CLSCTX_ENABLE_CODE_DOWNLOAD = &H2000
            CLSCTX_NO_FAILURE_LOG = &H4000
            CLSCTX_DISABLE_AAA = &H8000
            CLSCTX_ENABLE_AAA = &H10000
            CLSCTX_FROM_DEFAULT_CONTEXT = &H20000
            CLSCTX_INPROC = CLSCTX_INPROC_SERVER Or CLSCTX_INPROC_HANDLER
            CLSCTX_SERVER = CLSCTX_INPROC_SERVER Or CLSCTX_LOCAL_SERVER Or CLSCTX_REMOTE_SERVER
            CLSCTX_ALL = CLSCTX_SERVER Or CLSCTX_INPROC_HANDLER
        End Enum
    
    
        <StructLayout(LayoutKind.Sequential, Pack:=4)>
        Private Structure PropertyKey
            Private m_formatId As Guid
            Private m_propertyId As Integer
    
            Public ReadOnly Property FormatId() As Guid
                Get
                    Return Me.m_formatId
                End Get
            End Property
    
            Public ReadOnly Property PropertyId() As Integer
                Get
                    Return Me.m_propertyId
                End Get
            End Property
    
            Public Sub New(ByVal formatId As Guid, ByVal propertyId As Integer)
                Me.m_formatId = formatId
                Me.m_propertyId = propertyId
            End Sub
        End Structure
    
        <StructLayout(LayoutKind.Sequential)>
        Private Structure tWAVEFORMATEX
            Public wFormatTag As UShort
            Public nChannels As UShort
            Public nSamplesPerSec As UInteger
            Public nAvgBytesPerSec As UInteger
            Public nBlockAlign As UShort
            Public wBitsPerSample As UShort
            Public cbSize As UShort
        End Structure
    
    
        <StructLayout(LayoutKind.Explicit)>
        Private NotInheritable Class PropVariant
            Implements IDisposable
    
            <FieldOffset(0)> Private valueType As UShort
            <FieldOffset(8)> Private ptr As IntPtr
    
            Public Property VarType() As VarEnum
                Get
                    Return DirectCast(CInt(Me.valueType), VarEnum)
                End Get
                Set(ByVal value As VarEnum)
                    Me.valueType = CUShort(value)
                End Set
            End Property
    
            Public ReadOnly Property IsNullOrEmpty() As Boolean
                Get
                    Return (Me.valueType = CUShort(VarEnum.VT_EMPTY) OrElse Me.valueType = CUShort(VarEnum.VT_NULL))
                End Get
            End Property
    
            Public ReadOnly Property Value() As String
                Get
                    Return Marshal.PtrToStringUni(Me.ptr)
                End Get
            End Property
    
            Public Sub New()
            End Sub
    
            Public Sub New(ByVal value As String)
                If value Is Nothing Then
                    Throw New ArgumentNullException("value")
                End If
    
                Me.valueType = CUShort(VarEnum.VT_LPWSTR)
                Me.ptr = Marshal.StringToCoTaskMemUni(value)
            End Sub
    
            Protected Overrides Sub Finalize()
                Try
                    Dispose()
                Finally
                    MyBase.Finalize()
                End Try
            End Sub
    
            Public Sub Dispose() Implements IDisposable.Dispose
                PropVariantClear(Me)
                GC.SuppressFinalize(Me)
            End Sub
        End Class
    
        <DllImport("Ole32.dll", PreserveSig:=False)> Private Shared Sub PropVariantClear(<[In](), Out()> ByVal pvar As PropVariant)
        End Sub
    
        <DllImport("ole32.Dll")>
        Private Shared Function CoCreateInstance(ByRef clsid As Guid, <MarshalAs(UnmanagedType.IUnknown)> ByVal inner As Object, ByVal context As Integer, ByRef uuid As Guid, <MarshalAs(UnmanagedType.IUnknown)> ByRef rReturnedComObject As Object) As Integer
        End Function
    End Class
    
    
    Public Class EndPointDeviceInfo
        Public ReadOnly Property FriendlyName As String
        Public ReadOnly Property Description As String
        Public ReadOnly Property Id As String
    
        Public Sub New(devName As String, devId As String, devDescription As String)
            _FriendlyName = devName
            _Id = devId
            _Description = devDescription
        End Sub
    
        Public Overrides Function ToString() As String
            Return FriendlyName
        End Function
    End Class
     

     Now go back to your Form's code and add the following code.  Then you can run/debug the application and test it.

    Public Class Form1
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            ComboBox_RendererEndPoints.DataSource = AudioEndPoints.GetEndPointNames(AudioEndPoints.EDataFlow.eRender)
            ComboBox_CaptureEndPoints.DataSource = AudioEndPoints.GetEndPointNames(AudioEndPoints.EDataFlow.eCapture)
        End Sub
    
        Private Sub Button_SetDefaultRenderer_Click(sender As Object, e As EventArgs) Handles Button_SetDefaultRenderer.Click
            Dim epdi As EndPointDeviceInfo = CType(ComboBox_RendererEndPoints.SelectedItem, EndPointDeviceInfo)
            AudioEndPoints.SetDefaultEndPoint(epdi.Id)
        End Sub
    
        Private Sub Button_SetDefaultCapture_Click(sender As Object, e As EventArgs) Handles Button_SetDefaultCapture.Click
            Dim epdi As EndPointDeviceInfo = CType(ComboBox_CaptureEndPoints.SelectedItem, EndPointDeviceInfo)
            AudioEndPoints.SetDefaultEndPoint(epdi.Id)
        End Sub
    End Class

     

     Here you can see it sets the device as the "Default Device".   However,  it does not set the device as the "Default Communications Device".


    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Saturday, January 6, 2018 3:03 AM
    Friday, January 5, 2018 2:48 PM

  • Thanks, I will study this code :)
    Tuesday, January 9, 2018 4:06 PM
  • Ran-jj,  If your question has been answered,  then please do not forget to mark the post or posts that have answered your question as the answer(s).  Thanks.  8)

    Also,  here is a slightly upgraded version of my prior example.  The first example i posted would only set the selected device as the (default device).  This new example allows you to set the selected device as the (default communications device) and/or the (default device).

     This is the updated AudioEndPoints class code.  I explained in the last example how to add the class to your project.

    Imports System.Runtime.InteropServices
    
    Public Class AudioEndPoints
        ''' <summary>Sets the specified device as the default device and/or the default communications device.</summary>
        ''' <param name="devId">The string Id for the input or output device to set.</param>
        ''' <param name="SetAsDefaultDevice">Set to True to set this device as the default device.</param>
        ''' <param name="SetAsDefaultCommunicationDevice">Set to True to set this device as the default communications device.</param>
        Public Shared Sub SetDefaultEndPoint(devId As String, SetAsDefaultDevice As Boolean, SetAsDefaultCommunicationDevice As Boolean)
            Dim IPCV As IPolicyConfigVista = Nothing
            Dim oIPCV As Object = Nothing
            Try
                Dim IID_IPolicyConfigVista As Guid = New Guid("568b9108-44bf-40b4-9006-86afe5b5a620")
                Dim CLSID_CPolicyConfigVistaClient As Guid = New Guid("294935CE-F637-4E7C-A41B-AB255460B862")
                If CoCreateInstance(CLSID_CPolicyConfigVistaClient, Nothing, CLSCTX.CLSCTX_INPROC_SERVER, IID_IPolicyConfigVista, oIPCV) <> 0 Then
                    Throw New Exception("Failed:  CoCreateInstance")
                Else
                    IPCV = CType(oIPCV, IPolicyConfigVista)
                    If IPCV Is Nothing Then Throw New Exception("Failed: COM cast to IPolicyConfigVista")
                End If
                If SetAsDefaultDevice Then
                    IPCV.SetDefaultEndpoint(devId, ERole.eConsole)
                End If
                If SetAsDefaultCommunicationDevice Then
                    IPCV.SetDefaultEndpoint(devId, ERole.eCommunications)
                End If
            Finally
                If (IPCV IsNot Nothing) Then
                    While Marshal.ReleaseComObject(IPCV) > 0
                    End While
                    IPCV = Nothing
                End If
                If (oIPCV IsNot Nothing) Then
                    While Marshal.ReleaseComObject(oIPCV) > 0
                    End While
                    oIPCV = Nothing
                End If
            End Try
        End Sub
    
        ''' <summary>Returns an array of EndPointDeviceInfo classes which contain the information for each device found for the specified types.</summary>
        ''' <param name="DevType">Can be (eRender) to get only output devices, (eCapture) to get only the input devices, or (eAll) to get all input and output devices.</param>
        Public Shared Function GetEndPointNames(ByVal DevType As EDataFlow) As EndPointDeviceInfo()
            Dim immdevcolptr As IntPtr = IntPtr.Zero
            Dim devcnt As UInteger = 0
            Dim immdevcol As IMMDeviceCollection = Nothing
            Dim dvInfo As New List(Of EndPointDeviceInfo)
            Dim IMMDE As IMMDeviceEnumerator = Nothing
            Dim oIMMDE As Object = Nothing
            Try
                Dim IID_IUnknown As Guid = New Guid("00000000-0000-0000-C000-000000000046")
                Dim IMMDE_clsid As Guid = New Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")
                If CoCreateInstance(IMMDE_clsid, Nothing, CLSCTX.CLSCTX_INPROC_SERVER, IID_IUnknown, oIMMDE) <> 0 Then
                    Throw New Exception("Failed:  CoCreateInstance")
                Else
                    IMMDE = CType(oIMMDE, IMMDeviceEnumerator)
                    If IMMDE Is Nothing Then Throw New Exception("Failed: COM cast to IMMDeviceEnumerator")
                End If
    
                Dim res As Integer = IMMDE.EnumAudioEndpoints(DevType, IMMDeviceStatesFlags.DEVICE_STATE_ACTIVE, immdevcolptr)
                If res <> 0 Then
                    Throw New Exception("EnumAudioEndpoints Failed with error: 0x" & res.ToString("X"))
                End If
    
                immdevcol = CType(Marshal.GetObjectForIUnknown(immdevcolptr), IMMDeviceCollection)
    
                res = immdevcol.GetCount(devcnt)
                If res <> 0 Then
                    Throw New Exception("GetCount Failed with error: 0x" & res.ToString("X"))
                End If
    
                If devcnt > 0 Then
                    For i As UInteger = 0 To devcnt - 1UI
                        Dim immdevptr As IntPtr = IntPtr.Zero
                        res = immdevcol.Item(i, immdevptr)
                        If res = 0 Then
                            Dim immdev As IMMDevice = CType(Marshal.GetObjectForIUnknown(immdevptr), IMMDevice)
                            If immdev IsNot Nothing Then
                                Dim propstrptr As IntPtr = IntPtr.Zero
                                res = immdev.OpenPropertyStore(STGM_READ, propstrptr)
                                If res = 0 Then
                                    Dim propstor As IPropertyStore = CType(Marshal.GetObjectForIUnknown(propstrptr), IPropertyStore)
                                    If propstor IsNot Nothing Then
                                        Dim FriendlyName As String = ""
                                        Using varnt As New PropVariant
                                            propstor.GetValue(Device_FriendlyName, varnt)
                                            FriendlyName = varnt.Value
                                        End Using
    
                                        Dim Description As String = ""
                                        Using vrnt As New PropVariant
                                            propstor.GetValue(Device_DeviceDesc, vrnt)
                                            Description = vrnt.Value
                                        End Using
    
                                        Dim idString As String = ""
                                        immdev.GetId(idString)
    
                                        dvInfo.Add(New EndPointDeviceInfo(FriendlyName, idString, Description))
    
                                        Marshal.ReleaseComObject(propstor)
                                        propstor = Nothing
                                    End If
                                End If
                                Marshal.ReleaseComObject(immdev)
                                immdev = Nothing
                            End If
                        End If
                    Next
                End If
            Finally
                If immdevcol IsNot Nothing Then
                    Marshal.ReleaseComObject(immdevcol)
                    immdevcol = Nothing
                End If
                If (IMMDE IsNot Nothing) Then
                    While Marshal.ReleaseComObject(IMMDE) > 0
                    End While
                    IMMDE = Nothing
                End If
                If (oIMMDE IsNot Nothing) Then
                    While Marshal.ReleaseComObject(oIMMDE) > 0
                    End While
                    oIMMDE = Nothing
                End If
            End Try
            Return dvInfo.ToArray
        End Function
    
    
        Private Shared SPDRP_Guid As New Guid(&HA45C254EUI, &HDF1C, &H4EFD, &H80, &H20, &H67, &HD1, &H46, &HA8, &H50, &HE0)
        Private Shared ReadOnly Property Device_Manufacturer As PropertyKey
            Get
                Return New PropertyKey(SPDRP_Guid, 13)
            End Get
        End Property
        Private Shared ReadOnly Property Device_DeviceDesc As PropertyKey
            Get
                Return New PropertyKey(SPDRP_Guid, 2)
            End Get
        End Property
        Private Shared ReadOnly Property Device_FriendlyName As PropertyKey
            Get
                Return New PropertyKey(SPDRP_Guid, 14)
            End Get
        End Property
    
        Private Const STGM_READ As Integer = &H0 'used for the (stgmAccess) parameter of the (OpenPropertyStore) function in the (IMMDevice) interface.
    
        <ComImport(), Guid("0BD7A1BE-7A1A-44DB-8397-CC5392387B5E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IMMDeviceCollection
            Function GetCount(ByRef pcDevices As UInteger) As Integer
            Function Item(ByVal nDevice As UInteger, ByRef ppDevice As IntPtr) As Integer
        End Interface
    
        <ComImport(), Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IMMDeviceEnumerator
            Function EnumAudioEndpoints(<ComAliasName("MMDeviceAPILib.EDataFlow")> ByVal dataFlow As EDataFlow, ByVal dwStateMask As Integer, ByRef ppDevices As IntPtr) As Integer
            Function GetDefaultAudioEndpoint(<ComAliasName("MMDeviceAPILib.EDataFlow")> ByVal dataFlow As EDataFlow, <ComAliasName("MMDeviceAPILib.ERole")> ByVal role As ERole, ByRef ppEndpoint As IntPtr) As Boolean
            Function GetDevice(ByVal pwstrId As String, ByRef ppDevice As IntPtr) As Integer
            Function RegisterEndpointNotificationCallback(ByVal pClient As IMMNotificationClient) As Integer
            Function UnregisterEndpointNotificationCallback(ByVal pClient As IMMNotificationClient) As Integer
        End Interface
    
        <ComImport(), Guid("7991EEC9-7E89-4D85-8390-6C703CEC60C0"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IMMNotificationClient
            Sub OnDeviceStateChanged(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDeviceId As String, ByVal dwNewState As UInteger)
            Sub OnDeviceAdded(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDeviceId As String)
            Sub OnDeviceRemoved(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDeviceId As String)
            Sub OnDefaultDeviceChanged(<ComAliasName("MMDeviceAPILib.EDataFlow")> ByVal flow As EDataFlow, <ComAliasName("MMDeviceAPILib.ERole")> ByVal role As ERole, <MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDefaultDeviceId As String)
            Sub OnPropertyValueChanged(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDeviceId As String, ByVal key As PropertyKey)
        End Interface
    
        <ComImport(), Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IMMDevice
            Function Activate(ByRef iid As Guid, ByVal dwClsCtx As Integer, ByVal pActivationParams As IntPtr, ByRef ppInterface As IntPtr) As Boolean
            Function OpenPropertyStore(ByVal stgmAccess As Integer, ByRef ppProperties As IntPtr) As Integer
            Function GetId(<MarshalAs(UnmanagedType.LPWStr)> ByRef ppstrId As String) As Integer
            Function GetState(ByRef pdwState As IMMDeviceStatesFlags) As Integer
        End Interface
    
        <ComImport(), Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IPropertyStore
            Function GetCount(ByRef cProps As UInteger) As UInteger
            Function GetAt(ByVal iProp As UInteger, ByRef pkey As PropertyKey) As UInteger
            Function GetValue(ByRef key As PropertyKey, ByVal pv As PropVariant) As UInteger
            Function SetValue(ByRef key As PropertyKey, ByVal pv As PropVariant) As UInteger
            Function Commit() As UInteger
        End Interface
    
        <ComImport(), Guid("568b9108-44bf-40b4-9006-86afe5b5a620"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IPolicyConfigVista
            Function GetMixFormat(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByRef param1 As IntPtr) As Integer 'not available on Windows 7, use method from IPolicyConfig
            Function GetDeviceFormat(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByVal param1 As Integer, ByRef wfx As tWAVEFORMATEX) As Integer
            Function SetDeviceFormat(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByRef wfx1 As tWAVEFORMATEX, ByRef wfx2 As tWAVEFORMATEX) As Integer
            Function GetProcessingPeriod(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByVal param1 As Integer, ByRef param2 As Long, ByRef param3 As Long) As Integer 'not available on Windows 7, use method from IPolicyConfig
            Function SetProcessingPeriod(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByRef param1 As Long) As Integer 'not available on Windows 7, use method from IPolicyConfig
            Function GetShareMode(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByRef DeviceShareMode As IntPtr) As Integer 'not available on Windows 7, use method from IPolicyConfig
            Function SetShareMode(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByRef DeviceShareMode As IntPtr) As Integer 'not available on Windows 7, use method from IPolicyConfig
            Function GetPropertyValue(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByRef propKey As PropertyKey, ByRef propVar As PropVariant) As Integer
            Function SetPropertyValue(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByRef propKey As PropertyKey, ByRef propVar As PropVariant) As Integer
            Function SetDefaultEndpoint(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByVal eRole As ERole) As Integer
            Function SetEndpointVisibility(<MarshalAs(UnmanagedType.LPWStr)> ByVal wszDeviceId As String, ByVal param1 As Integer) As Integer 'not available on Windows 7, use method from IPolicyConfig
        End Interface
    
        <Flags()>
        Private Enum IMMDeviceStatesFlags As Integer
            DEVICE_STATE_ACTIVE = &H1
            DEVICE_STATE_DISABLED = &H2
            DEVICE_STATE_NOTPRESENT = &H4
            DEVICE_STATE_UNPLUGGED = &H8
            DEVICE_STATE_ALL = &HF
        End Enum
    
        Public Enum EDataFlow As Integer
            eRender = &H0
            eCapture = &H1
            eAll = &H2
            EDataFlow_enum_count = &H3
        End Enum
    
        Private Enum ERole As Integer
            eConsole = &H0
            eMultimedia = &H1
            eCommunications = &H2
            ERole_enum_count = &H3
        End Enum
    
        <Flags()>
        Private Enum CLSCTX
            CLSCTX_INPROC_SERVER = &H1
            CLSCTX_INPROC_HANDLER = &H2
            CLSCTX_LOCAL_SERVER = &H4
            CLSCTX_INPROC_SERVER16 = &H8
            CLSCTX_REMOTE_SERVER = &H10
            CLSCTX_INPROC_HANDLER16 = &H20
            CLSCTX_RESERVED1 = &H40
            CLSCTX_RESERVED2 = &H80
            CLSCTX_RESERVED3 = &H100
            CLSCTX_RESERVED4 = &H200
            CLSCTX_NO_CODE_DOWNLOAD = &H400
            CLSCTX_RESERVED5 = &H800
            CLSCTX_NO_CUSTOM_MARSHAL = &H1000
            CLSCTX_ENABLE_CODE_DOWNLOAD = &H2000
            CLSCTX_NO_FAILURE_LOG = &H4000
            CLSCTX_DISABLE_AAA = &H8000
            CLSCTX_ENABLE_AAA = &H10000
            CLSCTX_FROM_DEFAULT_CONTEXT = &H20000
            CLSCTX_INPROC = CLSCTX_INPROC_SERVER Or CLSCTX_INPROC_HANDLER
            CLSCTX_SERVER = CLSCTX_INPROC_SERVER Or CLSCTX_LOCAL_SERVER Or CLSCTX_REMOTE_SERVER
            CLSCTX_ALL = CLSCTX_SERVER Or CLSCTX_INPROC_HANDLER
        End Enum
    
        <StructLayout(LayoutKind.Sequential, Pack:=4)>
        Private Structure PropertyKey
            Private m_formatId As Guid
            Private m_propertyId As Integer
            Public ReadOnly Property FormatId() As Guid
                Get
                    Return Me.m_formatId
                End Get
            End Property
            Public ReadOnly Property PropertyId() As Integer
                Get
                    Return Me.m_propertyId
                End Get
            End Property
            Public Sub New(ByVal formatId As Guid, ByVal propertyId As Integer)
                Me.m_formatId = formatId
                Me.m_propertyId = propertyId
            End Sub
        End Structure
    
        <StructLayout(LayoutKind.Sequential)>
        Private Structure tWAVEFORMATEX
            Public wFormatTag As UShort
            Public nChannels As UShort
            Public nSamplesPerSec As UInteger
            Public nAvgBytesPerSec As UInteger
            Public nBlockAlign As UShort
            Public wBitsPerSample As UShort
            Public cbSize As UShort
        End Structure
    
        <StructLayout(LayoutKind.Explicit)>
        Private NotInheritable Class PropVariant
            Implements IDisposable
    
            <FieldOffset(0)> Private valueType As UShort
            <FieldOffset(8)> Private ptr As IntPtr
    
            Public Property VarType() As VarEnum
                Get
                    Return DirectCast(CInt(Me.valueType), VarEnum)
                End Get
                Set(ByVal value As VarEnum)
                    Me.valueType = CUShort(value)
                End Set
            End Property
    
            Public ReadOnly Property IsNullOrEmpty() As Boolean
                Get
                    Return (Me.valueType = CUShort(VarEnum.VT_EMPTY) OrElse Me.valueType = CUShort(VarEnum.VT_NULL))
                End Get
            End Property
    
            Public ReadOnly Property Value() As String
                Get
                    Return Marshal.PtrToStringUni(Me.ptr)
                End Get
            End Property
    
            Public Sub New()
            End Sub
    
            Public Sub New(ByVal value As String)
                If value Is Nothing Then
                    Throw New ArgumentNullException("value")
                End If
    
                Me.valueType = CUShort(VarEnum.VT_LPWSTR)
                Me.ptr = Marshal.StringToCoTaskMemUni(value)
            End Sub
    
            Protected Overrides Sub Finalize()
                Try
                    Dispose()
                Finally
                    MyBase.Finalize()
                End Try
            End Sub
    
            Public Sub Dispose() Implements IDisposable.Dispose
                PropVariantClear(Me)
                GC.SuppressFinalize(Me)
            End Sub
        End Class
    
        <DllImport("Ole32.dll", PreserveSig:=False)> Private Shared Sub PropVariantClear(<[In](), Out()> ByVal pvar As PropVariant)
        End Sub
    
        <DllImport("ole32.Dll")>
        Private Shared Function CoCreateInstance(ByRef clsid As Guid, <MarshalAs(UnmanagedType.IUnknown)> ByVal inner As Object, ByVal context As Integer, ByRef uuid As Guid, <MarshalAs(UnmanagedType.IUnknown)> ByRef rReturnedComObject As Object) As Integer
        End Function
    End Class
    
    
    Public Class EndPointDeviceInfo
        Public ReadOnly Property FriendlyName As String
        Public ReadOnly Property Description As String
        Public ReadOnly Property Id As String
    
        Public Sub New(devName As String, devId As String, devDescription As String)
            _FriendlyName = devName
            _Id = devId
            _Description = devDescription
        End Sub
    
        Public Overrides Function ToString() As String
            Return FriendlyName
        End Function
    End Class
    
     

     I have also set up the example form differently too.  So,  these are the controls and the names of them that are required to replicate my example form as seen in the animated gif at the bottom of this post.

     Add 2 RadioButton controls and name them (RadioButton_OutputDevices) and (RadioButton_InputDevices).

     Add 2 CheckBox controls and name them (CheckBox_DefaultDevice) and (CheckBox_DefaultCommunicationsDevice).

     Add 1 ComboBox control and name it (ComboBox_EndPointDevices).

     Add 1 Button control and name it (Button_SetDefault).

     Now you can add this code to the form class....

    Public Class Form1
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            RadioButton_OutputDevices.Checked = True
            ComboBox_EndPointDevices.DropDownStyle = ComboBoxStyle.DropDownList
        End Sub
    
        Private Sub Button_SetDefault_Click(sender As Object, e As EventArgs) Handles Button_SetDefault.Click
            If ComboBox_EndPointDevices.SelectedItem IsNot Nothing AndAlso (CheckBox_DefaultDevice.Checked OrElse CheckBox_DefaultCommunicationsDevice.Checked) Then
                Dim epdi As EndPointDeviceInfo = CType(ComboBox_EndPointDevices.SelectedItem, EndPointDeviceInfo)
                AudioEndPoints.SetDefaultEndPoint(epdi.Id, CheckBox_DefaultDevice.Checked, CheckBox_DefaultCommunicationsDevice.Checked)
            End If
        End Sub
    
        Private Sub RadioButton_OutputDevices_CheckedChanged(sender As Object, e As EventArgs) Handles RadioButton_OutputDevices.CheckedChanged
            If RadioButton_OutputDevices.Checked Then
                ComboBox_EndPointDevices.DataSource = AudioEndPoints.GetEndPointNames(AudioEndPoints.EDataFlow.eRender)
            Else
                ComboBox_EndPointDevices.DataSource = AudioEndPoints.GetEndPointNames(AudioEndPoints.EDataFlow.eCapture)
            End If
        End Sub
    End Class
    
     

     This shows it setting the the Venus microphone as the default device and the default communications device.  Then setting the SigmaTel microphone as the default communications device.  Lastly, i set the SigmaTel microphone as the default device.  This can be done for the Input or Output devices.


    If you say it can`t be done then i`ll try it

    • Marked as answer by Ran-jj Tuesday, January 23, 2018 2:14 AM
    Tuesday, January 9, 2018 9:49 PM
  • IronRazerz, I stumbled across this class and it is working beautifully. One question I have is in regards to implementing the "GetDefaultAudioEndpoint". I'm attempting to access the existing default audio endpoint on form load, but not sure how to go about that.

    Any further help would be greatly appreciated, thanks!

    Monday, May 27, 2019 9:16 PM
  • Thank you for the code, it also work perfectly for me but I am also wondering how to display the default audio device in the combo box upon form load.  Any help would be appreciated.

    Thank you!

    Thursday, November 14, 2019 8:37 PM
  • Thank you for the code, it also work perfectly for me but I am also wondering how to display the default audio device in the combo box upon form load.  Any help would be appreciated.

    Compare GetDefaultAudioEndpoint with GetId
    Friday, November 15, 2019 12:34 PM