Change audio output with #If WinActive? Topic is solved

Ask gaming related questions (AHK v1.1 and older)
Dahu
Posts: 3
Joined: 21 Jun 2022, 14:14

Change audio output with #If WinActive?

Post by Dahu » 30 Jun 2022, 15:13

I found this code to change the audio output with hotkeys, but I'm also trying to know how to automate the change when starting specific games. I tried #If WinActive on line number 45 but it doesn't work. Any ideas?

Code: Select all

{
; Original FORUM : https://www.autohotkey.com/boards/viewtopic.php?f=76&t=49980
; http www.daveamenta.com /2011-05/programmatically-or-command-line-change-the-default-sound-playback-device-in-windows-7/  Broken Link for safety

Devices := {}
IMMDeviceEnumerator := ComObjCreate("{BCDE0395-E52F-467C-8E3D-C4579291692E}", "{A95664D2-9614-4F35-A746-DE8DB63617E6}")

; IMMDeviceEnumerator::EnumAudioEndpoints
; eRender = 0, eCapture, eAll
; 0x1 = DEVICE_STATE_ACTIVE
DllCall(NumGet(NumGet(IMMDeviceEnumerator+0)+3*A_PtrSize), "UPtr", IMMDeviceEnumerator, "UInt", 0, "UInt", 0x1, "UPtrP", IMMDeviceCollection, "UInt")
ObjRelease(IMMDeviceEnumerator)

; IMMDeviceCollection::GetCount
DllCall(NumGet(NumGet(IMMDeviceCollection+0)+3*A_PtrSize), "UPtr", IMMDeviceCollection, "UIntP", Count, "UInt")
Loop % (Count)
{
    ; IMMDeviceCollection::Item
    DllCall(NumGet(NumGet(IMMDeviceCollection+0)+4*A_PtrSize), "UPtr", IMMDeviceCollection, "UInt", A_Index-1, "UPtrP", IMMDevice, "UInt")

    ; IMMDevice::GetId
    DllCall(NumGet(NumGet(IMMDevice+0)+5*A_PtrSize), "UPtr", IMMDevice, "UPtrP", pBuffer, "UInt")
    DeviceID := StrGet(pBuffer, "UTF-16"), DllCall("Ole32.dll\CoTaskMemFree", "UPtr", pBuffer)

    ; IMMDevice::OpenPropertyStore
    ; 0x0 = STGM_READ
    DllCall(NumGet(NumGet(IMMDevice+0)+4*A_PtrSize), "UPtr", IMMDevice, "UInt", 0x0, "UPtrP", IPropertyStore, "UInt")
    ObjRelease(IMMDevice)

    ; IPropertyStore::GetValue
    VarSetCapacity(PROPVARIANT, A_PtrSize == 4 ? 16 : 24)
    VarSetCapacity(PROPERTYKEY, 20)
    DllCall("Ole32.dll\CLSIDFromString", "Str", "{A45C254E-DF1C-4EFD-8020-67D146A850E0}", "UPtr", &PROPERTYKEY)
    NumPut(14, &PROPERTYKEY + 16, "UInt")
    DllCall(NumGet(NumGet(IPropertyStore+0)+5*A_PtrSize), "UPtr", IPropertyStore, "UPtr", &PROPERTYKEY, "UPtr", &PROPVARIANT, "UInt")
    DeviceName := StrGet(NumGet(&PROPVARIANT + 8), "UTF-16")    ; LPWSTR PROPVARIANT.pwszVal
    DllCall("Ole32.dll\CoTaskMemFree", "UPtr", NumGet(&PROPVARIANT + 8))    ; LPWSTR PROPVARIANT.pwszVal
    ObjRelease(IPropertyStore)

    ObjRawSet(Devices, DeviceName, DeviceID)
}
ObjRelease(IMMDeviceCollection)
Return

#If WinActive("Arma 3") OR WinActive("Apex Legends")  ;;;;;; It doesn’t work ¿Is it wrong?
{
SetDefaultEndpoint( GetDeviceID(Devices, "Redragon Zeus X H510 (USB Audio Device)") )   ; Update second device name
}
Return
#If

^F4::                                                                                   ; Update Hotkey
t := !t  ; Toggle Var (0 or 1)
If (t = "1")
{
SetDefaultEndpoint( GetDeviceID(Devices, "Altavoces (Realtek(R) Audio)") )              ; Update first device name
}
If (t = "0")
{
SetDefaultEndpoint( GetDeviceID(Devices, "Redragon Zeus X H510 (USB Audio Device)") )   ; Update second device name
}
Return

SetDefaultEndpoint(DeviceID)
{
    IPolicyConfig := ComObjCreate("{870af99c-171d-4f9e-af0d-e63df40c2bc9}", "{F8679F50-850A-41CF-9C72-430F290290C8}")
    DllCall(NumGet(NumGet(IPolicyConfig+0)+13*A_PtrSize), "UPtr", IPolicyConfig, "UPtr", &DeviceID, "UInt", 0, "UInt")          ;number 0 for "Default Device"
    DllCall(NumGet(NumGet(IPolicyConfig+0)+13*A_PtrSize), "UPtr", IPolicyConfig, "UPtr", &DeviceID, "UInt", 2, "UInt")          ;number 2 for "Default Communication Device" (optional line)
    ObjRelease(IPolicyConfig)
}

GetDeviceID(Devices, Name)
{
    For DeviceName, DeviceID in Devices
        If (InStr(DeviceName, Name))
            Return DeviceID
}
Return
}

User avatar
boiler
Posts: 16771
Joined: 21 Dec 2014, 02:44

Re: Change audio output with #If WinActive?  Topic is solved

Post by boiler » 30 Jun 2022, 17:31

Line 45 does nothing because directives only apply to hotkeys, hotstrings, and key remaps. Line 47 doesn’t do anything either because it’s never executed. It’s buried below a Return so the code never flows to that line.

I suppose you want your #If line to cause that script to trigger that line to run whenever either of those windows is active. That’s not how it works. They don’t cause code to execute by an event occurring like a window becoming active. You could do something like use SetTimer to regularly check whether one of those windows becomes active at some point and run a subroutine or function when it is found to occur.

Post Reply

Return to “Gaming Help (v1)”