DanSaratov
Новичок
- Сообщения
- 112
- Репутация
- 1
В вин7 делается так : Панель управления-->Оборудование и звук-->Управление звуковыми устройствами-->Пкм по нужному устройству-->Использовать по умолчанию. Как можно реализовать это на autoit?
#NoTrayIcon
Opt("TrayMenuMode", 1)
#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 $S_OK = 0
;Global Const $E_INVALIDARG = 0x80070057
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
;==========================================================
; First generae array filled wih devices data
Global $aArray = _EnumerateDevices()
; Then create UI
For $i = 0 To UBound($aArray, 2) - 2
$aArray[2][$i] = TrayCreateItem($aArray[1][$i])
Next
TrayCreateItem("")
Global $iExit = TrayCreateItem("Exit")
TrayItemSetState($iExit, $TRAY_DEFAULT)
TraySetState()
Global $iMsg
While 1
$iMsg = TrayGetMsg()
Switch $iMsg
Case $iExit
Exit
Case Else
If $iMsg > 0 Then
For $i = 0 To UBound($aArray, 2) - 1
TrayItemSetState($aArray[2][$i], $TRAY_UNCHECKED)
If $iMsg = $aArray[2][$i] Then
ConsoleWrite("Switching to: " & $aArray[1][$i] & @CRLF)
_SwitchToDevice($aArray[0][$i])
TrayItemSetState($iMsg, $TRAY_CHECKED)
EndIf
Next
EndIf
EndSwitch
WEnd
; THE END
Func _EnumerateDevices()
; Error monitoring
Local $oErrorHandler = ObjEvent("AutoIt.Error", "_ErrFunc")
#forceref $oErrorHandler
; Creae MMDeviceEnumerator object
Local $oEnumerator = ObjCreateInterface($sCLSID_MMDeviceEnumerator, $sIID_IMMDeviceEnumerator, $tagIMMDeviceEnumerator)
; Get collection out of it
Local $pCollection
$oEnumerator.EnumAudioEndpoints($eRender, $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[3][$iCount + 1]
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[0][$i] = $sId
; 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[1][$i] = $sName
Next
Return $aArray
EndFunc ;==>_EnumerateDevices
Func _SwitchToDevice($sId)
Local $oPolicyConfig = ObjCreateInterface($sCLSID_CPolicyConfigClient, $sIID_IPolicyConfig, $tagIPolicyConfig)
Local $hResult
$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