Jump to content
Subz

Get Audio/Microphone Devices [Solved]

Recommended Posts

Subz

Hello all.

in the process of packaging an application (Voip) and looking at trying to automate capturing the following information to add to a config.xml file:

Default: Playback Device Name and Guid
Example:
Name: Speakers (Realtek High Definition Audio)
Guid: {0.0.0.00000000}.{a46ce930-4dd3-49b5-8e8e-7c8a2fdc3925}

Default Microphone Device Name and Guid
Example:
Name: Microphone (Realtek High Definition Audio)
Guid: {0.0.1.00000000}.{cff6f838-33ce-4c2d-9f77-98f4e19e4a75}

I've seen the following post by @trancexx, which gives me the Default Audit Device Name, but unsure how to get the Guid or the Microphone Name and Guid.  I believe to get the Guid, I would need to use PKEY_AudioEndpoint_GUID but unsure how to code this.  If anyone can assist or point me in the right direction it would be much appreciated.

Cheers Subz

 

Edited by Subz

Share this post


Link to post
Share on other sites
Bilgus

Thats a nice example from Trancexx there

I believe you just need to pass the Correct Property Key

Global Const $sPKEY_Device_FriendlyName = "{a45c254e-df1c-4efd-8020-67d146a850e0}, 14"
Global Const $sPKEY_Audio_Endpoint_GUID = "{1DA5D803-D492-4EDD-8C23-E0C0FFEE7F0E}, 4"

like literally use $sPKEY_Audio_Endpoint_GUID instead of $sPKEY_Device_FriendlyName

Share this post


Link to post
Share on other sites
Bilgus

sorry I missed the part about you wanting the microphone as well

#include <WinAPICOM.au3>


Global Const $sCLSID_MMDeviceEnumerator = "{BCDE0395-E52F-467C-8E3D-C4579291692E}"
Global Const $sIID_IMMDeviceEnumerator = "{A95664D2-9614-4F35-A746-DE8DB63617E6}"
Global Const $tagIMMDeviceEnumerator = "EnumAudioEndpoints hresult(int;int;ptr*);" & _
        "GetDefaultAudioEndpoint hresult(int;int;ptr*);" & _
        "GetDevice hresult(wstr;ptr*);" & _
        "RegisterEndpointNotificationCallback hresult(ptr);" & _
        "UnregisterEndpointNotificationCallback hresult(ptr);"

Global Const $IID_IMMDevice = "{D666063F-1587-4E43-81F1-B948E807363F}"
Global Const $tagIMMDevice = "Activate hresult(ptr;dword;variant*;ptr*);" & _
        "OpenPropertyStore hresult(dword;ptr*);" & _
        "GetId hresult(ptr*);" & _
        "GetState hresult(dword*);"

Global Const $IID_IPropertyStore = "{886d8eeb-8cf2-4446-8d02-cdba1dbdcf99}"
Global Const $tagIPropertyStore = "GetCount hresult(dword*);" & _
        "GetAt hresult(dword;ptr*);" & _
        "GetValue hresult(struct*;variant*);" & _
        "SetValue hresult(struct*;variant);" & _
        "Commit hresult();"

Global Const $sPKEY_Device_FriendlyName = "{a45c254e-df1c-4efd-8020-67d146a850e0}, 14"
Global Const $sPKEY_Audio_Endpoint_GUID = "{1DA5D803-D492-4EDD-8C23-E0C0FFEE7F0E}, 4"

Global Const $STGM_READ = 0
Global Const $DEVICE_STATE_ACTIVE = 0x00000001

Global Const $eRender = 0
Global Const $eCapture = 1
Global Const $eAll = 2
Global Const $EDataFlow_enum_count = 3

Global Const $eConsole = 0
Global Const $eMultimedia = 1
Global Const $eCommunications = 2
Global Const $ERole_enum_count = 3

Func _WinAPI_PKEYFromString($sPKEY, $pID = Default)
    Local $tPKEY = DllStructCreate("byte GUID[16]; dword PID;")
    DllCall("propsys.dll", "long", "PSPropertyKeyFromString", "wstr", $sPKEY, "struct*", $tPKEY)
    If $pID <> Default Then DllStructSetData($tPKEY, "PID", $pID)
    Return $tPKEY
EndFunc
;==========================================================

Local $oEnumerator = ObjCreateInterface($sCLSID_MMDeviceEnumerator, $sIID_IMMDeviceEnumerator, $tagIMMDeviceEnumerator)

Local $pDefaultEndpoint
$oEnumerator.GetDefaultAudioEndpoint($eRender, $DEVICE_STATE_ACTIVE, $pDefaultEndpoint)

Local $oEndpoint = ObjCreateInterface($pDefaultEndpoint, $IID_IMMDevice, $tagIMMDevice)

; PropertyStore stores properties
Local $pProps
$oEndpoint.OpenPropertyStore($STGM_READ, $pProps)
$oProps = ObjCreateInterface($pProps, $IID_IPropertyStore, $tagIPropertyStore)

; Collect FriendlyName property
Local $tPKEY_Device_FriendlyName = _WinAPI_PKEYFromString($sPKEY_Device_FriendlyName)
Local $sName
$oProps.GetValue($tPKEY_Device_FriendlyName, $sName)

ConsoleWrite($sName & @CRLF)

Local $tPKEY_Audio_Endpoint_GUID = _WinAPI_PKEYFromString($sPKEY_Audio_Endpoint_GUID)
Local $sGuid
$oProps.GetValue($tPKEY_Audio_Endpoint_GUID, $sGuid)

ConsoleWrite($sGuid & @CRLF)

;------------MICROPHONE
$oEnumerator.GetDefaultAudioEndpoint($eCapture, $DEVICE_STATE_ACTIVE, $pDefaultEndpoint)

$oEndpoint = ObjCreateInterface($pDefaultEndpoint, $IID_IMMDevice, $tagIMMDevice)

; PropertyStore stores properties
$oEndpoint.OpenPropertyStore($STGM_READ, $pProps)

$oProps = ObjCreateInterface($pProps, $IID_IPropertyStore, $tagIPropertyStore)

; Collect FriendlyName property
$tPKEY_Device_FriendlyName = _WinAPI_PKEYFromString($sPKEY_Device_FriendlyName)

$oProps.GetValue($tPKEY_Device_FriendlyName, $sName)

ConsoleWrite($sName & @CRLF)

$tPKEY_Audio_Endpoint_GUID = _WinAPI_PKEYFromString($sPKEY_Audio_Endpoint_GUID)

$oProps.GetValue($tPKEY_Audio_Endpoint_GUID, $sGuid)

ConsoleWrite($sGuid & @CRLF)

 

Edited by Bilgus
  • Like 1

Share this post


Link to post
Share on other sites
Subz

Thanks Bilgus

Sorry for the delay, it turned out I required the Instance ID rather than the Guid, was attempting to get this when I found another post by Trancexx which included the instance id and I was able to make a few adjustments to return the instance Id, Type (Microphone or Playback) and the name. (see code below)

nb: I tried to figure out how to use the ERoles to determine the type but reverted to using the registry as not very familiar with converting C++ into AutoIt code.

Thanks again.

#include <Array.au3>
#include <WinAPI.au3>
#include <Constants.au3>

Global Const $sCLSID_MMDeviceEnumerator = "{BCDE0395-E52F-467C-8E3D-C4579291692E}"
Global Const $sIID_IMMDeviceEnumerator = "{A95664D2-9614-4F35-A746-DE8DB63617E6}"

Global Const $tagIMMDeviceEnumerator = "EnumAudioEndpoints hresult(dword;dword;ptr*);" & _
    "GetDefaultAudioEndpoint hresult(dword;dword;ptr*);" & _
    "GetDevice hresult(wstr;ptr*);" & _
    "RegisterEndpointNotificationCallback hresult(ptr);" & _
    "UnregisterEndpointNotificationCallback hresult(ptr);"

Global Const $sCLSID_CPolicyConfigClient = "{870af99c-171d-4f9e-af0d-e63df40c2bc9}"
Global Const $sIID_IPolicyConfig = "{f8679f50-850a-41cf-9c72-430f290290c8}"

Global Const $tagIPolicyConfig = "GetMixFormat hresult(wstr;ptr*);" & _
    "GetDeviceFormat hresult(wstr;int;ptr*);" & _
    "ResetDeviceFormat hresult(wstr);" & _
    "SetDeviceFormat hresult(wstr;ptr;ptr);" & _
    "GetProcessingPeriod hresult(wstr;int;int64*;int64*);" & _
    "SetProcessingPeriod hresult(wstr;int64*);" & _
    "GetShareMode hresult(wstr;ptr);" & _
    "SetShareMode hresult(wstr;ptr);" & _
    "GetPropertyValue hresult(wstr;struct;variant*);" & _
    "SetPropertyValue hresult(wstr;struct;variant*);" & _
    "SetDefaultEndpoint hresult(wstr;int);" & _
    "SetEndpointVisibility hresult(wstr;int);"

Global Const $IID_IMMDevice = "{D666063F-1587-4E43-81F1-B948E807363F}"
Global Const $tagIMMDevice = "Activate hresult(ptr;dword;variant*;ptr*);" & _
    "OpenPropertyStore hresult(dword;ptr*);" & _
    "GetId hresult(ptr*);" & _
    "GetState hresult(dword*);"

Global Const $IID_IMMDeviceCollection = "{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}"
Global Const $tagIMMDeviceCollection = "GetCount hresult(uint*);" & _
    "Item hresult(uint;ptr*)"

Global Const $IID_IPropertyStore = "{886d8eeb-8cf2-4446-8d02-cdba1dbdcf99}"
Global Const $tagIPropertyStore = "GetCount hresult(dword*);" & _
    "GetAt hresult(dword;ptr*);" & _
    "GetValue hresult(ptr;variant*);" & _
    "SetValue hresult(ptr;variant);" & _
    "Commit hresult();"

Global Const $sPKEY_Device_FriendlyName = "{a45c254e-df1c-4efd-8020-67d146a850e0} 14"

Global Const $STGM_READ = 0
Global Const $DEVICE_STATE_ACTIVE = 0x00000001

Global Const $eRender = 0
Global Const $eCapture = 1
Global Const $eAll = 2
Global Const $EDataFlow_enum_count = 3

Global Const $eConsole = 0
Global Const $eMultimedia = 1
Global Const $eCommunications = 2
Global Const $ERole_enum_count = 3
;==========================================================
Global $aArray = _EnumerateDevices()
_ArrayDisplay($aArray)


Func _EnumerateDevices()
    ;~ Error monitoring
    Local $oErrorHandler = ObjEvent("AutoIt.Error", "_ErrFunc")
        #forceref $oErrorHandler

;~ Registry Key for Audio Devices
    Local $sRegAudio = @OSArch = "x64" ? "HKLM64\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio" : "HKLM64\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio"

    ;~ Create MMDeviceEnumerator object
    Local $oEnumerator = ObjCreateInterface($sCLSID_MMDeviceEnumerator, $sIID_IMMDeviceEnumerator, $tagIMMDeviceEnumerator)

    ;~ Get collection out of it
    Local $pCollection
    $oEnumerator.EnumAudioEndpoints($eAll, $DEVICE_STATE_ACTIVE, $pCollection)
    ;~ Turn it into object
    Local $oCollection = ObjCreateInterface($pCollection, $IID_IMMDeviceCollection, $tagIMMDeviceCollection)

    ;~ Check the number of devices in collection
    Local $iCount
    $oCollection.GetCount($iCount)

    ;~ Array for out
    Local $aArray[$iCount][4]
    Local $pEndpoint, $oEndpoint
    Local $pID, $sId, $pProps, $oProps
    Local $sName
    Local $tPKEY_Device_FriendlyName = _WinAPI_PKEYFromString($sPKEY_Device_FriendlyName)

    ;~ Actual enumeration
    For $i = 0 To $iCount - 1
    ;~ Item at "i" index is audio endpoint device
        $oCollection.Item($i, $pEndpoint)
        $oEndpoint = ObjCreateInterface($pEndpoint, $IID_IMMDevice, $tagIMMDevice)

    ;~ Collect ID
        $oEndpoint.GetId($pID)
        $sId = DllStructGetData(DllStructCreate("wchar ID[" & _WinAPI_PtrStringLenW($pID) & "]", $pID), "ID")
        _WinAPI_CoTaskMemFree($pID)
        $aArray[$i][2] = $sId

    ;~ Detect Instance ID is Microphone(capture) or Playback(render)
        $aGuid = StringSplit($sId, ".")
        $aArray[$i][1] = $aGuid[$aGuid[0]]
        $aArray[$i][0] = RegRead($sRegAudio & "\Capture\" & $aGuid[$aGuid[0]], "DeviceState") >= 1 ? "Microphone" : ""
        If $aArray[$i][0] = "" Then $aArray[$i][0] = RegRead($sRegAudio & "\Render\" & $aGuid[$aGuid[0]], "DeviceState") >= 1 ? "Playback" : ""

    ;~ PropertyStore stores properties, lol
        $oEndpoint.OpenPropertyStore($STGM_READ, $pProps)
        $oProps = ObjCreateInterface($pProps, $IID_IPropertyStore, $tagIPropertyStore)

    ;~ Collect FriendlyName property
        $sName = 0
        $oProps.GetValue(DllStructGetPtr($tPKEY_Device_FriendlyName), $sName)
        $aArray[$i][3] = $sName
    Next
    Return $aArray
EndFunc ;==>_EnumerateDevices

Func _SwitchToDevice($sId)
    Local $oPolicyConfig = ObjCreateInterface($sCLSID_CPolicyConfigClient, $sIID_IPolicyConfig, $tagIPolicyConfig)
    Local $hResult = $oPolicyConfig.SetDefaultEndpoint($sId, $eConsole)
    If $hResult = $S_OK Then $hResult = $oPolicyConfig.SetDefaultEndpoint($sId, $eCommunications)
    Return $hResult = $S_OK
EndFunc ;==>_SwitchToDevice


Func _WinAPI_PKEYFromString($sPKEY, $pID = Default)
    Local $tPKEY = DllStructCreate("byte GUID[16]; dword PID;")
    DllCall("propsys.dll", "long", "PSPropertyKeyFromString", "wstr", $sPKEY, "ptr", DllStructGetPtr($tPKEY))
    If @error Then ; alternative for unsupported systems
        Local $tGUID = _WinAPI_GUIDFromString($sPKEY)
        If Not @error Then
            DllStructSetData($tPKEY, "GUID", DllStructGetData(DllStructCreate("byte Data[16]", DllStructGetPtr($tGUID)), 1))
        EndIf
        DllStructSetData($tPKEY, "PID", Number(StringRegExpReplace($sPKEY, ".*?}", "")))
    EndIf
    If $pID <> Default Then DllStructSetData($tPKEY, "PID", $pID)
    Return $tPKEY
EndFunc ;==>_WinAPI_PKEYFromString

Func _WinAPI_PtrStringLenW($pString)
    Local $aCall = DllCall("kernel32.dll", "dword", "lstrlenW", "ptr", $pString)
        If @error Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc ;==>_WinAPI_PtrStringLenW

Func _WinAPI_CoTaskMemFree($pMem)
    DllCall("ole32.dll", "none", "CoTaskMemFree", "ptr", $pMem)
    If @error Then Return SetError(1, 0, False)
    Return True
EndFunc ;==>_WinAPI_CoTaskMemFree

Func _ErrFunc($oError)
    ConsoleWrite("COM Error, ScriptLine(" & $oError.scriptline & ") : Number 0x" & Hex($oError.number, 8) & " - " & $oError.windescription & @CRLF)
EndFunc ;==>_ErrFunc

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • nacerbaaziz
      By nacerbaaziz
      Hi guys
      I'm looking for how to detect if the default audio output has changed
      During my research I found this file
      I did not know how to use it
      can  anyone guide me how  it works please.
      Thanks in advance
      audioOutputIsChanged.au3
    • nss
      By nss
      Hi all,
       
      I am making a program in which I use Bass audio library (with the wrapper for autoit that I found here on forums I think) because of its support for dx effects.
      My problem, though, is that when effects as reverb or echo/delay are added, the channel length is not extended as to fit the tail of the effect, so if the file was really short, you wouldn't even hear the reverb at all.
      I've tried setting the  buffer parameter even to 60k ms, updating the channel length to 60k ms, but nothing makes it so that the effects aren't being cut off.
      I've heard that I could add silence manually to wave files by adding the chr(0) characters, but haven't had any luck doing that, either.
      What I'm doing:
      initialize bass use streamCreateFile to load the wave file with the fx flag and length parameter set to 60000 set the config buffer to 60000 use channel set fx to add dx8 reverb use channel play to play the sound use bass update to update the length to 60000  
      I even tried having only silence in one wave file and tried joining two wave files together, but that didn't work either.
       
      Any help would be very much appreciated.
    • nacerbaaziz
      By nacerbaaziz
      Hello my friends
      I have an urgent problem and we hope you can help me
      I want to detect if the audio output of the device has changed
      Such as the headset is connected or disConnected.
      or change the default audio output
      Is this possible?
      I really searched a lot and found suggestions but unfortunately I did not understand them
      Please explain to me
      Greetings
    • nacerbaaziz
      By nacerbaaziz
      Hello my friends
      I am a totally blind young man
      for easier to read books and articles Among the blind
      i has programmed a tool
      This tool converts text to audio with the possibility to save it into a wav or mp3 file
      It is also compatible with all persons, whether blind or ordinary
      I have completed the work of this tool and want to take your opinion
      i Especially published here for anyone looking about how to convert text to speech, I will put this tool open source for you
      I want to know what your think about it
      and if it need any other additions?
      Note :
      This tool converts texts to audio using sapi 5 voices
      so i was also puted a hot keys to control the tool
      Now I put this project to you for public benefit and I am ready to answer any question.
      Apology :
      I am an Arab youth from Algeria
      I do not mastered English very well
      So I apologize to you if there are written mistakes
      With my greetings and best wishes
      My texts to audio converter.zip
    • nacerbaaziz
      By nacerbaaziz
      hellow guys
      I am a blind young man
      I started a project to make an audio player
      with recorder
      I ended the player and i did not know how to recorder
      This player is Compatible with the blind and visually impaired and ordinary users
      Unfortunately I do not see so I could not merge images and icons
      So I hope you will be able to help me in this matter
      I will bring you the open source project and please help me to add images, icons and recorder, the project is requires easy access in order to be compatible with the screen readers, Please take this into account.
      the software is organized so the recorder is In a special  menu that Contains stop and start and pause and save.
      The same is true for player
      Please help
      And greetings to all
      easy player.zip
×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.