Jump to content
Sign in to follow this  
Subz

Get Audio/Microphone Devices [Solved]

Recommended Posts

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

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

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

Share this post


Link to post
Share on other sites

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
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By ripdad
      This is a project that I have been working on for several months off and on.
      It's a simple "What You Hear" MP3 @ 320Kbps and WAV audio recorder.
      Features:
      - LoudMax, a Gain Controller and Look-Ahead Limiter
      - Auto Shut-Off after one minute of silence
      - Side-by-Side Simulated LED Meter
      - Running Time Counter
      It started off being a large project, but I eventually stripped it down to its
      bare essentials because I came to realize that it would be very difficult to
      deal with every sound card and every way a PC is set up for audio. It would
      have been a nightmare that I was not willing to go through.
      This project contains the most up-to-date BASS.dll v.2.4.15.0 - December 17, 2019.
      All BASS Dll's are 32bit. Those and the needed UDF's are included in the zip file.
      I will try to explain how it works in the next post.

      Download:
      BASS VST Recorder v1.1.zip
       
    • By nacerbaaziz
      good morning autoit team
      please i need your help
      am trying to make an program that work with hotkeys
      it function is to change the volume to the current application
      e.g when i select the vlc window by using this hotkey i will be able to change the vlc volume with out changing the system volume.
       am able to get the process handle and the process name of the window
      but when am trying to get or set the volume i does not succeded
      i tried to search in this forums but no result.
      can you please guide me to do that.
      am waiting for your answers
      thanks in advanced
    • By ripdad
      This is an example script of how to load and use a VST using BASS in AutoIt.
      It is NOT immediately Plug and Play. You will need to download 2 VST's to run it.
      They are free for personal use.
      All information is in the header of the script.

      Download:
      BASS VST HOST v0.4.zip
       
    • By CYCho
      This file includes all the source codes and a compiled .exe version of zPlayer, which is a stand-alone, simple, intuitive and easy-to-use, yet fully functional audio player.  I made this to suit my purpose and you can tweak it to your taste as the source code is only about 1000 lines which are very much readable.  This player has the following functions:
      - Play back all formats of audio files which can be palyed back by the Windows Media Player in your computer
      - Graphical player similar to embedded Windows Media Player
      - Forward, backward, pause, repeat, shuffle funtions
      - Increase/decrease/mute sound volume
      - Change folders and create playlist for all audio files in that folder and its subfolders, and support for manually-made playlists
      - Save play-back environment when terminating and resume that environment when restarting
      - With one click, you can see DuckDuckGo search results for the file being played back
      - With a double-click, you can play back an item in the playlist
      - Search strings in the playlist
      - Option to see long file names including folder names
      - Resize the playlist window, and restore it to its default position
      - Very small footprint: very low CPU and memory usage, with only about 1MB when compiled
      - You can even hide all the windows and manipulate the player with hotkeys only
      Note: zPlayer is the name I used when I introduced the early version of this palyer in my blog back in early 2009 and, therefore, has nothing to do with the mobile media player of the same name which started marketing in 2015.
    • By PeterVerbeek
      In this post I take the opportunity to show the awesome capabilities of AutoIt and its libraries. My open source project Peace is a long running AutoIt based app located on SourceForge. It provides users with a system-wide equalizer and effects machine. It's an interface using the power of Equalizer APO, an audio processing object software. Peace has been download over 1,100,000 times by various kind of users. Amongst others it gives them possibilities like these:
      Hearing impaired - Amplify the gain of frequencies which are impaired. Home Theatre - Create Equalizer presets for watching movies and listening to music. Music lovers & audiophiles - Create presets for listening to music on their high quality speakers and headphones. Gamers - Enhance frequencies to get an edge over other gamers. Headphones - Improve the sound quality of cheap headphones and get the max out of expensive ones. Bass lovers - Boost low frequencies for extra bass. Voice - Make a microphone sound better and improve the voice, for instance for YouTube usage. Low audio - Boost low audio of an input source to a comfortable level. This list covers the main needs of the Peace user. Many people have contacted me over the years asking for new features and telling me how they use Peace for their (sometimes specific) needs.  I was able to use AutoIt and its libraries for all of their needs. So what are the main features of Peace?
      Equalize your computer audio by using up to 31 sliders. Support of equalizing 9 speakers : left/right, center, subwoofer, left/right rear, left/right side. Per slider a filter can be chosen such as peak, low/high pass, shelving. The graph windows shows your equalization so you see exactly what you're doing. Apply an effect such as crossfeed simple/Jan Meier/Chu Moy, stereo balance, bass/treble, upmix/downmix, channel routing. Save presets (called configurations) and activate by mouse click, hotkey, desktop shortcut or Peace system tray. Select a target device to equalize, microphone as input can also be equalized. Automate: you can let Peace automatically activate presets on a switch to another device and another process. Peace is available in these languages: English, Czech, Deutsch, Français, Italiano, Nederlands, Pусский, Українська So who am I? I'm a Dutch programmer who happens the stumble upon AutoIt 5 years ago and created a small Equalizer interface app of less than 400 program lines with it. Nowadays Peace has grown to more than 17,000 lines as many features were added. Although Peace is open source, the program code isn't of the best possible quality. The reason being that I didn't expect it to become so popular. It caught me by supprise. I've created a Library of functions called Pal (link to forum post) which quality is up to the AutoIt community standard as counterpart to the Peace program code.
      I want to state here that AutoIt is a mature program language as Peace obviously shows. I wish it to be used more extensively for professional or semi-professional apps. In my view AutoIt deserves a place amongst the major programming languages for Windows computers.
      Regards,
      Peter Verbeek







×
×
  • Create New...