1

Тема: AHK: Управление микшером в контексте приложений

Приветствую.

И так сабж.
Управлять колонками/наушниками/микрофоном и т.д. , т.е. микшером на уровне устройств - проблемы нет.

А вот как отрегулировать уровень звука приложения... не получается.

Я посмотрел Серый форум ветку и не только  AutoHotkey, весь Интернет перерыл - пусто.

В реестре ничего похожего нет или я не знаю, что искать.


P.S. Windows 7 SP1 x64 Ultimate Edition

"На каждое действие есть равная ему противодействующая критика." Постулат Харриссона
OS Windows 7 x64
AutoHotkey v1.1.32.00 - November 24, 2019
Click to Download

2

Re: AHK: Управление микшером в контексте приложений

https://autohotkey.com/board/topic/7822 … pp-volume/

3 (изменено: Indomito, 2016-06-04 12:22:06)

Re: AHK: Управление микшером в контексте приложений

Спасибо, но возникла проблема с VA.ahk.

; Requirements:
;   VA 2.1 - http://www.autohotkey.com/forum/topic23792.html
;   Windows 7
;   AutoHotkey_L
;   Luck?

Ссылка битая.

"На каждое действие есть равная ему противодействующая критика." Постулат Харриссона
OS Windows 7 x64
AutoHotkey v1.1.32.00 - November 24, 2019
Click to Download

4

Re: AHK: Управление микшером в контексте приложений

Почему битая?
https://autohotkey.com/board/topic/2198 … functions/

Download v2.3 for AutoHotkey 1.1

5 (изменено: serzh82saratov, 2016-06-04 17:04:33)

Re: AHK: Управление микшером в контексте приложений

Была такая тема, но иногда не срабатывает. Например у скайпа находит 3 процесса, если на первом убавляешь громкость то де-факто ничего не происходит. У firefox вообще 2 разных процесса. По каким признакам отобрать нужный, не ясно.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

6

Re: AHK: Управление микшером в контексте приложений

По ссылке из 2 поста у меня всё вроде определяет правильно.

7

Re: AHK: Управление микшером в контексте приложений

Malcev пишет:

определяет правильно

Так у тебя определяет правильно, или всё таки в скайпе и лисе всегда правильно регулирует громкость, mute?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

8 (изменено: Malcev, 2016-06-04 18:15:44)

Re: AHK: Управление микшером в контексте приложений

И определяет и регулирует.
Вот так у меня перечисляются все программы для которых можно регулировать звук и лиса идёт в состояние mute:

WinGet, WinPid, pid, ahk_exe firefox.exe
; Requirements:
;   VA 2.1 - http://www.autohotkey.com/forum/topic23792.html
;   Windows 7
;   AutoHotkey_L
;   Luck?

IID_IAudioSessionManager2 := "{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}"
IID_ISimpleAudioVolume := "{87CE5498-68D6-44E5-9215-6DA47EF883D8}"

dev := VA_GetDevice()
if !dev
    throw "Can't get device"
if VA_IMMDevice_Activate(dev, IID_IAudioSessionManager2, 7, 0, mgr) != 0
    throw "Can't get session manager"
ObjRelease(dev)
if VA_IAudioSessionManager2_GetSessionEnumerator(mgr, enm) != 0
    throw "Can't get session enumerator"
ObjRelease(mgr)
VA_IAudioSessionEnumerator_GetCount(enm, count)
Loop % count
{
    ; IAudioSessionControl *session;
    VA_IAudioSessionEnumerator_GetSession(enm, A_Index-1, ssn)
    VA_IAudioSessionControl_GetDisplayName(ssn, name)
    VA_IAudioSessionControl2_GetProcessId(ssn, pid)
    sav := ComObjQuery(ssn, IID_ISimpleAudioVolume)
    ObjRelease(ssn)
    if !sav ; Unlikely?
        throw "Can't get volume control"
    if (WinPid = pid)
       VA_ISimpleAudioVolume_SetMute(sav, 1)
    VA_ISimpleAudioVolume_GetMasterVolume(sav, volume)
    MsgBox %name%`nPID: %pid%`nVolume: %volume%
    ObjRelease(sav)
}
ObjRelease(enm)


;
; ISimpleAudioVolume -- currently not included in VA.ahk
;
VA_ISimpleAudioVolume_SetMasterVolume(this, Level, EventContext="") {
    return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "uint", this, "float", Level, "uint", VA_GUID(EventContext))
}
VA_ISimpleAudioVolume_GetMasterVolume(this, ByRef Level) {
    return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "uint", this, "float*", Level)
}
VA_ISimpleAudioVolume_SetMute(this, Mute, EventContext="") {
    return DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "uint", this, "int", Mute, "uint", VA_GUID(EventContext))
}
VA_ISimpleAudioVolume_GetMute(this, ByRef Mute) {
    return DllCall(NumGet(NumGet(this+0)+6*A_PtrSize), "uint", this, "int*", Mute)
}






; VA v2.3

;
; MASTER CONTROLS
;

VA_GetMasterVolume(channel="", device_desc="playback")
{
    if ! aev := VA_GetAudioEndpointVolume(device_desc)
        return
    if channel =
        VA_IAudioEndpointVolume_GetMasterVolumeLevelScalar(aev, vol)
    else
        VA_IAudioEndpointVolume_GetChannelVolumeLevelScalar(aev, channel-1, vol)
    ObjRelease(aev)
    return Round(vol*100,3)
}

VA_SetMasterVolume(vol, channel="", device_desc="playback")
{
    vol := vol>100 ? 100 : vol<0 ? 0 : vol
    if ! aev := VA_GetAudioEndpointVolume(device_desc)
        return
    if channel =
        VA_IAudioEndpointVolume_SetMasterVolumeLevelScalar(aev, vol/100)
    else
        VA_IAudioEndpointVolume_SetChannelVolumeLevelScalar(aev, channel-1, vol/100)
    ObjRelease(aev)
}

VA_GetMasterChannelCount(device_desc="playback")
{
    if ! aev := VA_GetAudioEndpointVolume(device_desc)
        return
    VA_IAudioEndpointVolume_GetChannelCount(aev, count)
    ObjRelease(aev)
    return count
}

VA_SetMasterMute(mute, device_desc="playback")
{
    if ! aev := VA_GetAudioEndpointVolume(device_desc)
        return
    VA_IAudioEndpointVolume_SetMute(aev, mute)
    ObjRelease(aev)
}

VA_GetMasterMute(device_desc="playback")
{
    if ! aev := VA_GetAudioEndpointVolume(device_desc)
        return
    VA_IAudioEndpointVolume_GetMute(aev, mute)
    ObjRelease(aev)
    return mute
}

;
; SUBUNIT CONTROLS
;

VA_GetVolume(subunit_desc="1", channel="", device_desc="playback")
{
    if ! avl := VA_GetDeviceSubunit(device_desc, subunit_desc, "{7FB7B48F-531D-44A2-BCB3-5AD5A134B3DC}")
        return
    VA_IPerChannelDbLevel_GetChannelCount(avl, channel_count)
    if channel =
    {
        vol = 0
        
        Loop, %channel_count%
        {
            VA_IPerChannelDbLevel_GetLevelRange(avl, A_Index-1, min_dB, max_dB, step_dB)
            VA_IPerChannelDbLevel_GetLevel(avl, A_Index-1, this_vol)
            this_vol := VA_dB2Scalar(this_vol, min_dB, max_dB)
            
            ; "Speakers Properties" reports the highest channel as the volume.
            if (this_vol > vol)
                vol := this_vol
        }
    }
    else if channel between 1 and channel_count
    {
        channel -= 1
        VA_IPerChannelDbLevel_GetLevelRange(avl, channel, min_dB, max_dB, step_dB)
        VA_IPerChannelDbLevel_GetLevel(avl, channel, vol)
        vol := VA_dB2Scalar(vol, min_dB, max_dB)
    }
    ObjRelease(avl)
    return vol
}

VA_SetVolume(vol, subunit_desc="1", channel="", device_desc="playback")
{
    if ! avl := VA_GetDeviceSubunit(device_desc, subunit_desc, "{7FB7B48F-531D-44A2-BCB3-5AD5A134B3DC}")
        return
    
    vol := vol<0 ? 0 : vol>100 ? 100 : vol
    
    VA_IPerChannelDbLevel_GetChannelCount(avl, channel_count)
    
    if channel =
    {
        ; Simple method -- resets balance to "center":
        ;VA_IPerChannelDbLevel_SetLevelUniform(avl, vol)
        
        vol_max = 0
        
        Loop, %channel_count%
        {
            VA_IPerChannelDbLevel_GetLevelRange(avl, A_Index-1, min_dB, max_dB, step_dB)
            VA_IPerChannelDbLevel_GetLevel(avl, A_Index-1, this_vol)
            this_vol := VA_dB2Scalar(this_vol, min_dB, max_dB)
            
            channel%A_Index%vol := this_vol
            channel%A_Index%min := min_dB
            channel%A_Index%max := max_dB
            
            ; Scale all channels relative to the loudest channel.
            ; (This is how Vista's "Speakers Properties" dialog seems to work.)
            if (this_vol > vol_max)
                vol_max := this_vol
        }
        
        Loop, %channel_count%
        {
            this_vol := vol_max ? channel%A_Index%vol / vol_max * vol : vol
            this_vol := VA_Scalar2dB(this_vol/100, channel%A_Index%min, channel%A_Index%max)            
            VA_IPerChannelDbLevel_SetLevel(avl, A_Index-1, this_vol)
        }
    }
    else if channel between 1 and %channel_count%
    {
        channel -= 1
        VA_IPerChannelDbLevel_GetLevelRange(avl, channel, min_dB, max_dB, step_dB)
        VA_IPerChannelDbLevel_SetLevel(avl, channel, VA_Scalar2dB(vol/100, min_dB, max_dB))
    }
    ObjRelease(avl)
}

VA_GetChannelCount(subunit_desc="1", device_desc="playback")
{
    if ! avl := VA_GetDeviceSubunit(device_desc, subunit_desc, "{7FB7B48F-531D-44A2-BCB3-5AD5A134B3DC}")
        return
    VA_IPerChannelDbLevel_GetChannelCount(avl, channel_count)
    ObjRelease(avl)
    return channel_count
}

VA_SetMute(mute, subunit_desc="1", device_desc="playback")
{
    if ! amute := VA_GetDeviceSubunit(device_desc, subunit_desc, "{DF45AEEA-B74A-4B6B-AFAD-2366B6AA012E}")
        return
    VA_IAudioMute_SetMute(amute, mute)
    ObjRelease(amute)
}

VA_GetMute(subunit_desc="1", device_desc="playback")
{
    if ! amute := VA_GetDeviceSubunit(device_desc, subunit_desc, "{DF45AEEA-B74A-4B6B-AFAD-2366B6AA012E}")
        return
    VA_IAudioMute_GetMute(amute, muted)
    ObjRelease(amute)
    return muted
}

;
; AUDIO METERING
;

VA_GetAudioMeter(device_desc="playback")
{
    if ! device := VA_GetDevice(device_desc)
        return 0
    VA_IMMDevice_Activate(device, "{C02216F6-8C67-4B5B-9D00-D008E73E0064}", 7, 0, audioMeter)
    ObjRelease(device)
    return audioMeter
}

VA_GetDevicePeriod(device_desc, ByRef default_period, ByRef minimum_period="")
{
    defaultPeriod := minimumPeriod := 0
    if ! device := VA_GetDevice(device_desc)
        return false
    VA_IMMDevice_Activate(device, "{1CB9AD4C-DBFA-4c32-B178-C2F568A703B2}", 7, 0, audioClient)
    ObjRelease(device)
    ; IAudioClient::GetDevicePeriod
    DllCall(NumGet(NumGet(audioClient+0)+9*A_PtrSize), "ptr",audioClient, "int64*",default_period, "int64*",minimum_period)
    ; Convert 100-nanosecond units to milliseconds.
    default_period /= 10000
    minimum_period /= 10000    
    ObjRelease(audioClient)
    return true
}

VA_GetAudioEndpointVolume(device_desc="playback")
{
    if ! device := VA_GetDevice(device_desc)
        return 0
    VA_IMMDevice_Activate(device, "{5CDF2C82-841E-4546-9722-0CF74078229A}", 7, 0, endpointVolume)
    ObjRelease(device)
    return endpointVolume
}

VA_GetDeviceSubunit(device_desc, subunit_desc, subunit_iid)
{
    if ! device := VA_GetDevice(device_desc)
        return 0
    subunit := VA_FindSubunit(device, subunit_desc, subunit_iid)
    ObjRelease(device)
    return subunit
}

VA_FindSubunit(device, target_desc, target_iid)
{
    if target_desc is integer
        target_index := target_desc
    else
        RegExMatch(target_desc, "(?<_name>.*?)(?::(?<_index>\d+))?$", target)
    ; v2.01: Since target_name is now a regular expression, default to case-insensitive mode if no options are specified.
    if !RegExMatch(target_name,"^[^\(]+\)")
        target_name := "i)" target_name
    r := VA_EnumSubunits(device, "VA_FindSubunitCallback", target_name, target_iid
            , Object(0, target_index ? target_index : 1, 1, 0))
    return r
}

VA_FindSubunitCallback(part, interface, index)
{
    index[1] := index[1] + 1 ; current += 1
    if (index[0] == index[1]) ; target == current ?
    {
        ObjAddRef(interface)
        return interface
    }
}

VA_EnumSubunits(device, callback, target_name="", target_iid="", callback_param="")
{
    VA_IMMDevice_Activate(device, "{2A07407E-6497-4A18-9787-32F79BD0D98F}", 7, 0, deviceTopology)
    VA_IDeviceTopology_GetConnector(deviceTopology, 0, conn)
    ObjRelease(deviceTopology)
    VA_IConnector_GetConnectedTo(conn, conn_to)
    VA_IConnector_GetDataFlow(conn, data_flow)
    ObjRelease(conn)
    if !conn_to
        return ; blank to indicate error
    part := ComObjQuery(conn_to, "{AE2DE0E4-5BCA-4F2D-AA46-5D13F8FDB3A9}") ; IID_IPart
    ObjRelease(conn_to)
    if !part
        return
    r := VA_EnumSubunitsEx(part, data_flow, callback, target_name, target_iid, callback_param)
    ObjRelease(part)
    return r ; value returned by callback, or zero.
}

VA_EnumSubunitsEx(part, data_flow, callback, target_name="", target_iid="", callback_param="")
{
    r := 0
    
    VA_IPart_GetPartType(part, type)
   
    if type = 1 ; Subunit
    {
        VA_IPart_GetName(part, name)
        
        ; v2.01: target_name is now a regular expression.
        if RegExMatch(name, target_name)
        {
            if target_iid =
                r := %callback%(part, 0, callback_param)
            else
                if VA_IPart_Activate(part, 7, target_iid, interface) = 0
                {
                    r := %callback%(part, interface, callback_param)
                    ; The callback is responsible for calling ObjAddRef()
                    ; if it intends to keep the interface pointer.
                    ObjRelease(interface)
                }

            if r
                return r ; early termination
        }
    }
    
    if data_flow = 0
        VA_IPart_EnumPartsIncoming(part, parts)
    else
        VA_IPart_EnumPartsOutgoing(part, parts)
    
    VA_IPartsList_GetCount(parts, count)
    Loop %count%
    {
        VA_IPartsList_GetPart(parts, A_Index-1, subpart)        
        r := VA_EnumSubunitsEx(subpart, data_flow, callback, target_name, target_iid, callback_param)
        ObjRelease(subpart)
        if r
            break ; early termination
    }
    ObjRelease(parts)
    return r ; continue/finished enumeration
}

; device_desc = device_id
;               | ( friendly_name | 'playback' | 'capture' ) [ ':' index ]
VA_GetDevice(device_desc="playback")
{
    static CLSID_MMDeviceEnumerator := "{BCDE0395-E52F-467C-8E3D-C4579291692E}"
        , IID_IMMDeviceEnumerator := "{A95664D2-9614-4F35-A746-DE8DB63617E6}"
    if !(deviceEnumerator := ComObjCreate(CLSID_MMDeviceEnumerator, IID_IMMDeviceEnumerator))
        return 0
    
    device := 0
    
    if VA_IMMDeviceEnumerator_GetDevice(deviceEnumerator, device_desc, device) = 0
        goto VA_GetDevice_Return
    
    if device_desc is integer
    {
        m2 := device_desc
        if m2 >= 4096 ; Probably a device pointer, passed here indirectly via VA_GetAudioMeter or such.
        {
            ObjAddRef(device := m2)
            goto VA_GetDevice_Return
        }
    }
    else
        RegExMatch(device_desc, "(.*?)\s*(?::(\d+))?$", m)
    
    if m1 in playback,p
        m1 := "", flow := 0 ; eRender
    else if m1 in capture,c
        m1 := "", flow := 1 ; eCapture
    else if (m1 . m2) = ""  ; no name or number specified
        m1 := "", flow := 0 ; eRender (default)
    else
        flow := 2 ; eAll
    
    if (m1 . m2) = ""   ; no name or number (maybe "playback" or "capture")
    {
        VA_IMMDeviceEnumerator_GetDefaultAudioEndpoint(deviceEnumerator, flow, 0, device)
        goto VA_GetDevice_Return
    }

    VA_IMMDeviceEnumerator_EnumAudioEndpoints(deviceEnumerator, flow, 1, devices)
    
    if m1 =
    {
        VA_IMMDeviceCollection_Item(devices, m2-1, device)
        goto VA_GetDevice_Return
    }
    
    VA_IMMDeviceCollection_GetCount(devices, count)
    index := 0
    Loop % count
        if VA_IMMDeviceCollection_Item(devices, A_Index-1, device) = 0
            if InStr(VA_GetDeviceName(device), m1) && (m2 = "" || ++index = m2)
                goto VA_GetDevice_Return
            else
                ObjRelease(device), device:=0

VA_GetDevice_Return:
    ObjRelease(deviceEnumerator)
    if devices
        ObjRelease(devices)
    
    return device ; may be 0
}

VA_GetDeviceName(device)
{
    static PKEY_Device_FriendlyName
    if !VarSetCapacity(PKEY_Device_FriendlyName)
        VarSetCapacity(PKEY_Device_FriendlyName, 20)
        ,VA_GUID(PKEY_Device_FriendlyName :="{A45C254E-DF1C-4EFD-8020-67D146A850E0}")
        ,NumPut(14, PKEY_Device_FriendlyName, 16)
    VarSetCapacity(prop, 16)
    VA_IMMDevice_OpenPropertyStore(device, 0, store)
    ; store->GetValue(.., [out] prop)
    DllCall(NumGet(NumGet(store+0)+5*A_PtrSize), "ptr", store, "ptr", &PKEY_Device_FriendlyName, "ptr", &prop)
    ObjRelease(store)
    VA_WStrOut(deviceName := NumGet(prop,8))
    return deviceName
}

VA_SetDefaultEndpoint(device_desc, role)
{
    /* Roles:
         eConsole        = 0  ; Default Device
         eMultimedia     = 1
         eCommunications = 2  ; Default Communications Device
    */
    if ! device := VA_GetDevice(device_desc)
        return 0
    if VA_IMMDevice_GetId(device, id) = 0
    {
        cfg := ComObjCreate("{294935CE-F637-4E7C-A41B-AB255460B862}"
                          , "{568b9108-44bf-40b4-9006-86afe5b5a620}")
        hr := VA_xIPolicyConfigVista_SetDefaultEndpoint(cfg, id, role)
        ObjRelease(cfg)
    }
    ObjRelease(device)
    return hr = 0
}


;
; HELPERS
;

; Convert string to binary GUID structure.
VA_GUID(ByRef guid_out, guid_in="%guid_out%") {
    if (guid_in == "%guid_out%")
        guid_in :=   guid_out
    if  guid_in is integer
        return guid_in
    VarSetCapacity(guid_out, 16, 0)
	DllCall("ole32\CLSIDFromString", "wstr", guid_in, "ptr", &guid_out)
	return &guid_out
}

; Convert binary GUID structure to string.
VA_GUIDOut(ByRef guid) {
    VarSetCapacity(buf, 78)
    DllCall("ole32\StringFromGUID2", "ptr", &guid, "ptr", &buf, "int", 39)
    guid := StrGet(&buf, "UTF-16")
}

; Convert COM-allocated wide char string pointer to usable string.
VA_WStrOut(ByRef str) {
    str := StrGet(ptr := str, "UTF-16")
    DllCall("ole32\CoTaskMemFree", "ptr", ptr)  ; FREES THE STRING.
}

VA_dB2Scalar(dB, min_dB, max_dB) {
    min_s := 10**(min_dB/20), max_s := 10**(max_dB/20)
    return ((10**(dB/20))-min_s)/(max_s-min_s)*100
}

VA_Scalar2dB(s, min_dB, max_dB) {
    min_s := 10**(min_dB/20), max_s := 10**(max_dB/20)
    return log((max_s-min_s)*s+min_s)*20
}


;
; INTERFACE WRAPPERS
;   Reference: Core Audio APIs in Windows Vista -- Programming Reference
;       http://msdn2.microsoft.com/en-us/library/ms679156(VS.85).aspx
;

;
; IMMDevice : {D666063F-1587-4E43-81F1-B948E807363F}
;
VA_IMMDevice_Activate(this, iid, ClsCtx, ActivationParams, ByRef Interface) {
    return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "ptr", VA_GUID(iid), "uint", ClsCtx, "uint", ActivationParams, "ptr*", Interface)
}
VA_IMMDevice_OpenPropertyStore(this, Access, ByRef Properties) {
    return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "uint", Access, "ptr*", Properties)
}
VA_IMMDevice_GetId(this, ByRef Id) {
    hr := DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "uint*", Id)
    VA_WStrOut(Id)
    return hr
}
VA_IMMDevice_GetState(this, ByRef State) {
    return DllCall(NumGet(NumGet(this+0)+6*A_PtrSize), "ptr", this, "uint*", State)
}

;
; IDeviceTopology : {2A07407E-6497-4A18-9787-32F79BD0D98F}
;
VA_IDeviceTopology_GetConnectorCount(this, ByRef Count) {
    return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "uint*", Count)
}
VA_IDeviceTopology_GetConnector(this, Index, ByRef Connector) {
    return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "uint", Index, "ptr*", Connector)
}
VA_IDeviceTopology_GetSubunitCount(this, ByRef Count) {
    return DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "uint*", Count)
}
VA_IDeviceTopology_GetSubunit(this, Index, ByRef Subunit) {
    return DllCall(NumGet(NumGet(this+0)+6*A_PtrSize), "ptr", this, "uint", Index, "ptr*", Subunit)
}
VA_IDeviceTopology_GetPartById(this, Id, ByRef Part) {
    return DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "uint", Id, "ptr*", Part)
}
VA_IDeviceTopology_GetDeviceId(this, ByRef DeviceId) {
    hr := DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), "ptr", this, "uint*", DeviceId)
    VA_WStrOut(DeviceId)
    return hr
}
VA_IDeviceTopology_GetSignalPath(this, PartFrom, PartTo, RejectMixedPaths, ByRef Parts) {
    return DllCall(NumGet(NumGet(this+0)+9*A_PtrSize), "ptr", this, "ptr", PartFrom, "ptr", PartTo, "int", RejectMixedPaths, "ptr*", Parts)
}

;
; IConnector : {9c2c4058-23f5-41de-877a-df3af236a09e}
;
VA_IConnector_GetType(this, ByRef Type) {
    return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "int*", Type)
}
VA_IConnector_GetDataFlow(this, ByRef Flow) {
    return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "int*", Flow)
}
VA_IConnector_ConnectTo(this, ConnectTo) {
    return DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "ptr", ConnectTo)
}
VA_IConnector_Disconnect(this) {
    return DllCall(NumGet(NumGet(this+0)+6*A_PtrSize), "ptr", this)
}
VA_IConnector_IsConnected(this, ByRef Connected) {
    return DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "int*", Connected)
}
VA_IConnector_GetConnectedTo(this, ByRef ConTo) {
    return DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), "ptr", this, "ptr*", ConTo)
}
VA_IConnector_GetConnectorIdConnectedTo(this, ByRef ConnectorId) {
    hr := DllCall(NumGet(NumGet(this+0)+9*A_PtrSize), "ptr", this, "ptr*", ConnectorId)
    VA_WStrOut(ConnectorId)
    return hr
}
VA_IConnector_GetDeviceIdConnectedTo(this, ByRef DeviceId) {
    hr := DllCall(NumGet(NumGet(this+0)+10*A_PtrSize), "ptr", this, "ptr*", DeviceId)
    VA_WStrOut(DeviceId)
    return hr
}

;
; IPart : {AE2DE0E4-5BCA-4F2D-AA46-5D13F8FDB3A9}
;
VA_IPart_GetName(this, ByRef Name) {
    hr := DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "ptr*", Name)
    VA_WStrOut(Name)
    return hr
}
VA_IPart_GetLocalId(this, ByRef Id) {
    return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "uint*", Id)
}
VA_IPart_GetGlobalId(this, ByRef GlobalId) {
    hr := DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "ptr*", GlobalId)
    VA_WStrOut(GlobalId)
    return hr
}
VA_IPart_GetPartType(this, ByRef PartType) {
    return DllCall(NumGet(NumGet(this+0)+6*A_PtrSize), "ptr", this, "int*", PartType)
}
VA_IPart_GetSubType(this, ByRef SubType) {
    VarSetCapacity(SubType,16,0)
    hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "ptr", &SubType)
    VA_GUIDOut(SubType)
    return hr
}
VA_IPart_GetControlInterfaceCount(this, ByRef Count) {
    return DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), "ptr", this, "uint*", Count)
}
VA_IPart_GetControlInterface(this, Index, ByRef InterfaceDesc) {
    return DllCall(NumGet(NumGet(this+0)+9*A_PtrSize), "ptr", this, "uint", Index, "ptr*", InterfaceDesc)
}
VA_IPart_EnumPartsIncoming(this, ByRef Parts) {
    return DllCall(NumGet(NumGet(this+0)+10*A_PtrSize), "ptr", this, "ptr*", Parts)
}
VA_IPart_EnumPartsOutgoing(this, ByRef Parts) {
    return DllCall(NumGet(NumGet(this+0)+11*A_PtrSize), "ptr", this, "ptr*", Parts)
}
VA_IPart_GetTopologyObject(this, ByRef Topology) {
    return DllCall(NumGet(NumGet(this+0)+12*A_PtrSize), "ptr", this, "ptr*", Topology)
}
VA_IPart_Activate(this, ClsContext, iid, ByRef Object) {
    return DllCall(NumGet(NumGet(this+0)+13*A_PtrSize), "ptr", this, "uint", ClsContext, "ptr", VA_GUID(iid), "ptr*", Object)
}
VA_IPart_RegisterControlChangeCallback(this, iid, Notify) {
    return DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), "ptr", this, "ptr", VA_GUID(iid), "ptr", Notify)
}
VA_IPart_UnregisterControlChangeCallback(this, Notify) {
    return DllCall(NumGet(NumGet(this+0)+15*A_PtrSize), "ptr", this, "ptr", Notify)
}

;
; IPartsList : {6DAA848C-5EB0-45CC-AEA5-998A2CDA1FFB}
;
VA_IPartsList_GetCount(this, ByRef Count) {
    return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "uint*", Count)
}
VA_IPartsList_GetPart(this, INdex, ByRef Part) {
    return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "uint", Index, "ptr*", Part)
}

;
; IAudioEndpointVolume : {5CDF2C82-841E-4546-9722-0CF74078229A}
;
VA_IAudioEndpointVolume_RegisterControlChangeNotify(this, Notify) {
    return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "ptr", Notify)
}
VA_IAudioEndpointVolume_UnregisterControlChangeNotify(this, Notify) {
    return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "ptr", Notify)
}
VA_IAudioEndpointVolume_GetChannelCount(this, ByRef ChannelCount) {
    return DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "uint*", ChannelCount)
}
VA_IAudioEndpointVolume_SetMasterVolumeLevel(this, LevelDB, GuidEventContext="") {
    return DllCall(NumGet(NumGet(this+0)+6*A_PtrSize), "ptr", this, "float", LevelDB, "ptr", VA_GUID(GuidEventContext))
}
VA_IAudioEndpointVolume_SetMasterVolumeLevelScalar(this, Level, GuidEventContext="") {
    return DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "float", Level, "ptr", VA_GUID(GuidEventContext))
}
VA_IAudioEndpointVolume_GetMasterVolumeLevel(this, ByRef LevelDB) {
    return DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), "ptr", this, "float*", LevelDB)
}
VA_IAudioEndpointVolume_GetMasterVolumeLevelScalar(this, ByRef Level) {
    return DllCall(NumGet(NumGet(this+0)+9*A_PtrSize), "ptr", this, "float*", Level)
}
VA_IAudioEndpointVolume_SetChannelVolumeLevel(this, Channel, LevelDB, GuidEventContext="") {
    return DllCall(NumGet(NumGet(this+0)+10*A_PtrSize), "ptr", this, "uint", Channel, "float", LevelDB, "ptr", VA_GUID(GuidEventContext))
}
VA_IAudioEndpointVolume_SetChannelVolumeLevelScalar(this, Channel, Level, GuidEventContext="") {
    return DllCall(NumGet(NumGet(this+0)+11*A_PtrSize), "ptr", this, "uint", Channel, "float", Level, "ptr", VA_GUID(GuidEventContext))
}
VA_IAudioEndpointVolume_GetChannelVolumeLevel(this, Channel, ByRef LevelDB) {
    return DllCall(NumGet(NumGet(this+0)+12*A_PtrSize), "ptr", this, "uint", Channel, "float*", LevelDB)
}
VA_IAudioEndpointVolume_GetChannelVolumeLevelScalar(this, Channel, ByRef Level) {
    return DllCall(NumGet(NumGet(this+0)+13*A_PtrSize), "ptr", this, "uint", Channel, "float*", Level)
}
VA_IAudioEndpointVolume_SetMute(this, Mute, GuidEventContext="") {
    return DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), "ptr", this, "int", Mute, "ptr", VA_GUID(GuidEventContext))
}
VA_IAudioEndpointVolume_GetMute(this, ByRef Mute) {
    return DllCall(NumGet(NumGet(this+0)+15*A_PtrSize), "ptr", this, "int*", Mute)
}
VA_IAudioEndpointVolume_GetVolumeStepInfo(this, ByRef Step, ByRef StepCount) {
    return DllCall(NumGet(NumGet(this+0)+16*A_PtrSize), "ptr", this, "uint*", Step, "uint*", StepCount)
}
VA_IAudioEndpointVolume_VolumeStepUp(this, GuidEventContext="") {
    return DllCall(NumGet(NumGet(this+0)+17*A_PtrSize), "ptr", this, "ptr", VA_GUID(GuidEventContext))
}
VA_IAudioEndpointVolume_VolumeStepDown(this, GuidEventContext="") {
    return DllCall(NumGet(NumGet(this+0)+18*A_PtrSize), "ptr", this, "ptr", VA_GUID(GuidEventContext))
}
VA_IAudioEndpointVolume_QueryHardwareSupport(this, ByRef HardwareSupportMask) {
    return DllCall(NumGet(NumGet(this+0)+19*A_PtrSize), "ptr", this, "uint*", HardwareSupportMask)
}
VA_IAudioEndpointVolume_GetVolumeRange(this, ByRef MinDB, ByRef MaxDB, ByRef IncrementDB) {
    return DllCall(NumGet(NumGet(this+0)+20*A_PtrSize), "ptr", this, "float*", MinDB, "float*", MaxDB, "float*", IncrementDB)
}

;
; IPerChannelDbLevel  : {C2F8E001-F205-4BC9-99BC-C13B1E048CCB}
;   IAudioVolumeLevel : {7FB7B48F-531D-44A2-BCB3-5AD5A134B3DC}
;   IAudioBass        : {A2B1A1D9-4DB3-425D-A2B2-BD335CB3E2E5}
;   IAudioMidrange    : {5E54B6D7-B44B-40D9-9A9E-E691D9CE6EDF}
;   IAudioTreble      : {0A717812-694E-4907-B74B-BAFA5CFDCA7B}
;
VA_IPerChannelDbLevel_GetChannelCount(this, ByRef Channels) {
    return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "uint*", Channels)
}
VA_IPerChannelDbLevel_GetLevelRange(this, Channel, ByRef MinLevelDB, ByRef MaxLevelDB, ByRef Stepping) {
    return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "uint", Channel, "float*", MinLevelDB, "float*", MaxLevelDB, "float*", Stepping)
}
VA_IPerChannelDbLevel_GetLevel(this, Channel, ByRef LevelDB) {
    return DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "uint", Channel, "float*", LevelDB)
}
VA_IPerChannelDbLevel_SetLevel(this, Channel, LevelDB, GuidEventContext="") {
    return DllCall(NumGet(NumGet(this+0)+6*A_PtrSize), "ptr", this, "uint", Channel, "float", LevelDB, "ptr", VA_GUID(GuidEventContext))
}
VA_IPerChannelDbLevel_SetLevelUniform(this, LevelDB, GuidEventContext="") {
    return DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "float", LevelDB, "ptr", VA_GUID(GuidEventContext))
}
VA_IPerChannelDbLevel_SetLevelAllChannels(this, LevelsDB, ChannelCount, GuidEventContext="") {
    return DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), "ptr", this, "uint", LevelsDB, "uint", ChannelCount, "ptr", VA_GUID(GuidEventContext))
}

;
; IAudioMute : {DF45AEEA-B74A-4B6B-AFAD-2366B6AA012E}
;
VA_IAudioMute_SetMute(this, Muted, GuidEventContext="") {
    return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "int", Muted, "ptr", VA_GUID(GuidEventContext))
}
VA_IAudioMute_GetMute(this, ByRef Muted) {
    return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "int*", Muted)
}

;
; IAudioAutoGainControl : {85401FD4-6DE4-4b9d-9869-2D6753A82F3C}
;
VA_IAudioAutoGainControl_GetEnabled(this, ByRef Enabled) {
    return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "int*", Enabled)
}
VA_IAudioAutoGainControl_SetEnabled(this, Enable, GuidEventContext="") {
    return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "int", Enable, "ptr", VA_GUID(GuidEventContext))
}

;
; IAudioMeterInformation : {C02216F6-8C67-4B5B-9D00-D008E73E0064}
;
VA_IAudioMeterInformation_GetPeakValue(this, ByRef Peak) {
    return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "float*", Peak)
}
VA_IAudioMeterInformation_GetMeteringChannelCount(this, ByRef ChannelCount) {
    return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "uint*", ChannelCount)
}
VA_IAudioMeterInformation_GetChannelsPeakValues(this, ChannelCount, PeakValues) {
    return DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "uint", ChannelCount, "ptr", PeakValues)
}
VA_IAudioMeterInformation_QueryHardwareSupport(this, ByRef HardwareSupportMask) {
    return DllCall(NumGet(NumGet(this+0)+6*A_PtrSize), "ptr", this, "uint*", HardwareSupportMask)
}

;
; IAudioClient : {1CB9AD4C-DBFA-4c32-B178-C2F568A703B2}
;
VA_IAudioClient_Initialize(this, ShareMode, StreamFlags, BufferDuration, Periodicity, Format, AudioSessionGuid) {
    return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "int", ShareMode, "uint", StreamFlags, "int64", BufferDuration, "int64", Periodicity, "ptr", Format, "ptr", VA_GUID(AudioSessionGuid))
}
VA_IAudioClient_GetBufferSize(this, ByRef NumBufferFrames) {
    return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "uint*", NumBufferFrames)
}
VA_IAudioClient_GetStreamLatency(this, ByRef Latency) {
    return DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "int64*", Latency)
}
VA_IAudioClient_GetCurrentPadding(this, ByRef NumPaddingFrames) {
    return DllCall(NumGet(NumGet(this+0)+6*A_PtrSize), "ptr", this, "uint*", NumPaddingFrames)
}
VA_IAudioClient_IsFormatSupported(this, ShareMode, Format, ByRef ClosestMatch) {
    return DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "int", ShareMode, "ptr", Format, "ptr*", ClosestMatch)
}
VA_IAudioClient_GetMixFormat(this, ByRef Format) {
    return DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), "ptr", this, "uint*", Format)
}
VA_IAudioClient_GetDevicePeriod(this, ByRef DefaultDevicePeriod, ByRef MinimumDevicePeriod) {
    return DllCall(NumGet(NumGet(this+0)+9*A_PtrSize), "ptr", this, "int64*", DefaultDevicePeriod, "int64*", MinimumDevicePeriod)
}
VA_IAudioClient_Start(this) {
    return DllCall(NumGet(NumGet(this+0)+10*A_PtrSize), "ptr", this)
}
VA_IAudioClient_Stop(this) {
    return DllCall(NumGet(NumGet(this+0)+11*A_PtrSize), "ptr", this)
}
VA_IAudioClient_Reset(this) {
    return DllCall(NumGet(NumGet(this+0)+12*A_PtrSize), "ptr", this)
}
VA_IAudioClient_SetEventHandle(this, eventHandle) {
    return DllCall(NumGet(NumGet(this+0)+13*A_PtrSize), "ptr", this, "ptr", eventHandle)
}
VA_IAudioClient_GetService(this, iid, ByRef Service) {
    return DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), "ptr", this, "ptr", VA_GUID(iid), "ptr*", Service)
}

;
; IAudioSessionControl : {F4B1A599-7266-4319-A8CA-E70ACB11E8CD}
;
/*
AudioSessionStateInactive = 0
AudioSessionStateActive = 1
AudioSessionStateExpired = 2
*/
VA_IAudioSessionControl_GetState(this, ByRef State) {
    return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "int*", State)
}
VA_IAudioSessionControl_GetDisplayName(this, ByRef DisplayName) {
    hr := DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "ptr*", DisplayName)
    VA_WStrOut(DisplayName)
    return hr
}
VA_IAudioSessionControl_SetDisplayName(this, DisplayName, EventContext) {
    return DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "wstr", DisplayName, "ptr", VA_GUID(EventContext))
}
VA_IAudioSessionControl_GetIconPath(this, ByRef IconPath) {
    hr := DllCall(NumGet(NumGet(this+0)+6*A_PtrSize), "ptr", this, "ptr*", IconPath)
    VA_WStrOut(IconPath)
    return hr
}
VA_IAudioSessionControl_SetIconPath(this, IconPath) {
    return DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "wstr", IconPath)
}
VA_IAudioSessionControl_GetGroupingParam(this, ByRef Param) {
    VarSetCapacity(Param,16,0)
    hr := DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), "ptr", this, "ptr", &Param)
    VA_GUIDOut(Param)
    return hr
}
VA_IAudioSessionControl_SetGroupingParam(this, Param, EventContext) {
    return DllCall(NumGet(NumGet(this+0)+9*A_PtrSize), "ptr", this, "ptr", VA_GUID(Param), "ptr", VA_GUID(EventContext))
}
VA_IAudioSessionControl_RegisterAudioSessionNotification(this, NewNotifications) {
    return DllCall(NumGet(NumGet(this+0)+10*A_PtrSize), "ptr", this, "ptr", NewNotifications)
}
VA_IAudioSessionControl_UnregisterAudioSessionNotification(this, NewNotifications) {
    return DllCall(NumGet(NumGet(this+0)+11*A_PtrSize), "ptr", this, "ptr", NewNotifications)
}

;
; IAudioSessionManager : {BFA971F1-4D5E-40BB-935E-967039BFBEE4}
;
VA_IAudioSessionManager_GetAudioSessionControl(this, AudioSessionGuid) {
    return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "ptr", VA_GUID(AudioSessionGuid))
}
VA_IAudioSessionManager_GetSimpleAudioVolume(this, AudioSessionGuid, StreamFlags, ByRef AudioVolume) {
    return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "ptr", VA_GUID(AudioSessionGuid), "uint", StreamFlags, "uint*", AudioVolume)
}

;
; IMMDeviceEnumerator
;
VA_IMMDeviceEnumerator_EnumAudioEndpoints(this, DataFlow, StateMask, ByRef Devices) {
    return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "int", DataFlow, "uint", StateMask, "ptr*", Devices)
}
VA_IMMDeviceEnumerator_GetDefaultAudioEndpoint(this, DataFlow, Role, ByRef Endpoint) {
    return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "int", DataFlow, "int", Role, "ptr*", Endpoint)
}
VA_IMMDeviceEnumerator_GetDevice(this, id, ByRef Device) {
    return DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "wstr", id, "ptr*", Device)
}
VA_IMMDeviceEnumerator_RegisterEndpointNotificationCallback(this, Client) {
    return DllCall(NumGet(NumGet(this+0)+6*A_PtrSize), "ptr", this, "ptr", Client)
}
VA_IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(this, Client) {
    return DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "ptr", Client)
}

;
; IMMDeviceCollection
;
VA_IMMDeviceCollection_GetCount(this, ByRef Count) {
    return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "uint*", Count)
}
VA_IMMDeviceCollection_Item(this, Index, ByRef Device) {
    return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "uint", Index, "ptr*", Device)
}

;
; IControlInterface
;
VA_IControlInterface_GetName(this, ByRef Name) {
    hr := DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "ptr*", Name)
    VA_WStrOut(Name)
    return hr
}
VA_IControlInterface_GetIID(this, ByRef IID) {
    VarSetCapacity(IID,16,0)
    hr := DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "ptr", &IID)
    VA_GUIDOut(IID)
    return hr
}


/*
    INTERFACES REQUIRING WINDOWS 7 / SERVER 2008 R2
*/

;
; IAudioSessionControl2 : {bfb7ff88-7239-4fc9-8fa2-07c950be9c6d}
;   extends IAudioSessionControl
;
VA_IAudioSessionControl2_GetSessionIdentifier(this, ByRef id) {
    hr := DllCall(NumGet(NumGet(this+0)+12*A_PtrSize), "ptr", this, "ptr*", id)
    VA_WStrOut(id)
    return hr
}
VA_IAudioSessionControl2_GetSessionInstanceIdentifier(this, ByRef id) {
    hr := DllCall(NumGet(NumGet(this+0)+13*A_PtrSize), "ptr", this, "ptr*", id)
    VA_WStrOut(id)
    return hr
}
VA_IAudioSessionControl2_GetProcessId(this, ByRef pid) {
    return DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), "ptr", this, "uint*", pid)
}
VA_IAudioSessionControl2_IsSystemSoundsSession(this) {
    return DllCall(NumGet(NumGet(this+0)+15*A_PtrSize), "ptr", this)
}
VA_IAudioSessionControl2_SetDuckingPreference(this, OptOut) {
    return DllCall(NumGet(NumGet(this+0)+16*A_PtrSize), "ptr", this, "int", OptOut)
}

;
; IAudioSessionManager2 : {77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}
;   extends IAudioSessionManager
;
VA_IAudioSessionManager2_GetSessionEnumerator(this, ByRef SessionEnum) {
    return DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "ptr*", SessionEnum)
}
VA_IAudioSessionManager2_RegisterSessionNotification(this, SessionNotification) {
    return DllCall(NumGet(NumGet(this+0)+6*A_PtrSize), "ptr", this, "ptr", SessionNotification)
}
VA_IAudioSessionManager2_UnregisterSessionNotification(this, SessionNotification) {
    return DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "ptr", SessionNotification)
}
VA_IAudioSessionManager2_RegisterDuckNotification(this, SessionNotification) {
    return DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), "ptr", this, "ptr", SessionNotification)
}
VA_IAudioSessionManager2_UnregisterDuckNotification(this, SessionNotification) {
    return DllCall(NumGet(NumGet(this+0)+9*A_PtrSize), "ptr", this, "ptr", SessionNotification)
}

;
; IAudioSessionEnumerator : {E2F5BB11-0570-40CA-ACDD-3AA01277DEE8}
;
VA_IAudioSessionEnumerator_GetCount(this, ByRef SessionCount) {
    return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "int*", SessionCount)
}
VA_IAudioSessionEnumerator_GetSession(this, SessionCount, ByRef Session) {
    return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "int", SessionCount, "ptr*", Session)
}


/*
    UNDOCUMENTED INTERFACES
*/

; Thanks to Dave Amenta for publishing this interface - http://goo.gl/6L93L
; IID := "{568b9108-44bf-40b4-9006-86afe5b5a620}"
; CLSID := "{294935CE-F637-4E7C-A41B-AB255460B862}"
VA_xIPolicyConfigVista_SetDefaultEndpoint(this, DeviceId, Role) {
    return DllCall(NumGet(NumGet(this+0)+12*A_PtrSize), "ptr", this, "wstr", DeviceId, "int", Role)
}

9

Re: AHK: Управление микшером в контексте приложений

Это если не через флэш плеер, то да. А в скайпе?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

10

Re: AHK: Управление микшером в контексте приложений

В скайпе тоже всё ок.
Проверил, что если несколько процессов лисы, то можно регулировать любой - громкость меняется на всех.
Чтобы регулировать флеш нужно:

DetectHiddenWindows on
WinGet, WinPid, pid, ahk_exe FlashPlayerPlugin_21_0_0_242.exe

11

Re: AHK: Управление микшером в контексте приложений

Malcev пишет:

Чтобы регулировать флеш нужно:

Это понятно, но если например надо регулировать звук окна которое под мышкой. Как определить что именно этот флеш принадлежит окну?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

12

Re: AHK: Управление микшером в контексте приложений

Пользуюсь 3 года, часто не срабатывает. В том же скайпе по разному. Возможно требуется проверка методом IAudioSessionControl :: GetState. Ползунки некоторых приложений иногда в самом микшере ничего не регулируют.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

13

Re: AHK: Управление микшером в контексте приложений

Не понимаю, что значит этот?
У меня весь флеш из фаерфокса идет через один процесс - FlashPlayerPlugin_21_0_0_242.exe.

14

Re: AHK: Управление микшером в контексте приложений

То есть если запущено несколько окон фаерфокса, отключится звук во всех его окнах.
Получается что фаерфокс надо вносить в исключения, а интересен метод получения реального потока в микшере, выводящего звук указанного процесса.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

15

Re: AHK: Управление микшером в контексте приложений

Ну так у меня и в микшере всегда только одна аппликация фаерфокса и одна апликация флеш-плагина.
Так что я всё-равно не понимаю чего ты хочешь добиться.

16

Re: AHK: Управление микшером в контексте приложений

Как минимум, чтобы не было исключений.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

17

Re: AHK: Управление микшером в контексте приложений

Ну такое вряд ли получится - например у хрома отдельно флешплеер не запускается, то есть регулируется в chrome.exe.

18

Re: AHK: Управление микшером в контексте приложений

Протестировал скрипт из восьмого поста, но не понял, что он демонстрирует и как его использовать. Скажите, пожалуйста, можно ли с его помощью реализовать регулировку громкости отдельного приложения (как в микшере), например, при нажатии на WheelUp/WheelDown над заголовком окна данного приложения?

Win10x64

19 (изменено: svoboden, 2017-03-27 20:29:31)

Re: AHK: Управление микшером в контексте приложений

Уже отвечали на подобный вопрос.

20 (изменено: svoboden, 2017-04-07 00:42:56)

Re: AHK: Управление микшером в контексте приложений

becauseim, вот скрипт, работает по Win+Shift+WheelUp/WheelDown.

#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
#SingleInstance force
#Persistent ; Keeps a script permanently running, until ExitApp is encountered
#UseHook
#MaxHotkeysPerInterval 200 ; allow more keys

DetectHiddenWindows On ; Used for retriving the application path
SetBatchLines -1 ; Run with maximum speed
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
AutoTrim, Off ; do not auto trim strings

OnExit, ExitProgram ; exit event
OnMessage(0x404, "notifyIcon") ; Left click tray event
OnMessage(0x7E, "DisplayChange") ; fire on display resolution change

Gui +LastFound ; shell message hook
hWnd := WinExist()

AppName = One Audio Tool
RegName = One Key Tool

WinGet, prevWinID, ID, A
settimer, actPrevWin, -100 ; activate previous window


; --------------------------------------
; Volume Configuration
; --------------------------------------
; The percentage by which to raise or lower the volume each time
vol_Step_def = 10
vol_Step := vol_Step_def

; How long to display the volume level bar graphs (in milliseconds)
vol_DisplayTime = 2000

; Transparency of window (0-255)
vol_TransValue = 255

; Bar's background and text colour
vol_CW = EEEEEE
vol_Col_def = 3333AA
vol_Col_rdp = 333333
vol_Col := vol_Col_def

vol_Width = 220  ; width of bar
vol_Thick = 21   ; thickness of bar

vol_PosX :=
vol_PosY :=
vol_XY :=  
vol_oldXY := 0

;getResolution()
vol_text :=

; get current volume setting
vol_Master := VA_GetMasterVolume()


; initilize Volume OSD and dim layer
gosub, getResolution

; ---------------------------------------
; Read Settings
; ---------------------------------------
; Registry location to save the settings
reg_root = HKEY_CURRENT_USER
reg_path = Software\%RegName%
reg_path_run = Software\Microsoft\Windows\CurrentVersion\Run
modeBlock0 = Disabled
modeBlock1 = Always On
modeBlock2 = Only via RDP

nameRun = Run on Windows start
RegRead, enableAutorun, %reg_root%, %reg_path_run%, %Regname%
enableAutorun := ErrorLevel ? false : enableAutorun

RegRead, enableVol, %reg_root%, %reg_path%, enableVolume
enableVol := ErrorLevel ? true : enableVol
RegRead, newValue, %reg_root%, %reg_path%, valueVolume
vol_step := ErrorLevel ? vol_step : newValue

applySettings()

; Load Audio App substitude
audioApps =
audioAppFind =
audioAppNum = 0
getAudioApps()

; ---------------------------------------
; Tray Menu
; ---------------------------------------

Menu, TRAY, Tip, %AppName%
if A_IsCompiled  
    Menu, TRAY, NoStandard
Menu, TRAY, Add, About %AppName%, TrayAbout
Menu, TRAY, Add ; Separator
Menu, TRAY, Add, %nameRun%, menuAutorun
if (enableAutorun)
    Menu, TRAY, Check, %nameRun%
else
    Menu, TRAY, Uncheck, %nameRun%
Menu, TRAY, Add, Settings..., TraySettings
Menu, TRAY, Add ; Separator
if (A_IsCompiled != 1)
    Menu, TRAY, Add, Reload Script, Reload
Menu, TRAY, Add, Disable, Disable
Menu, TRAY, Add, Exit, exitProgram

; ---------------------------------------
; GUI elements, Settings
; ---------------------------------------

Gui, Font, S10 CDefault, Verdana
Gui, Add, GroupBox, x20 y18 w390 h110 , Keyboard Controls
Gui, Add, CheckBox, x40 y38 w150 h30 vboxVolume Checked%enableVol%, Control volume
Gui, Add, Text, x240 y44 w60 h24 , Steps:
Gui, Add, Edit, veditVolume x300 y42 w90 h26
Gui, Add, UpDown, vtextVolume Range1-50, %vol_Step%
Gui, Add, Button, x60 y68 w200 h26 gAudioDialog, Configure Applications...

Gui, Font, S11 CDefault, Verdana
Gui, Add, Button, x60 y145 w110 h28 Default, OK
Gui, Add, Button, x180 y145 w110 h28 , Cancel
Gui, Add, Button, x300 y145 w110 h28 , Apply


; ---------------------------------------
; GUI elements, About
; ---------------------------------------
Gui, 2:Font, S14 W700, Verdana
Gui, 2:Add, Text, x20 y10 w400 h24 , %AppName%
Gui, 2:Font, S10 W400, Verdana
Gui, 2:Add, Text, x20 y40 w470 h15 , Version 1.0.1 (c) 2013 Volker Semken
Gui, 2:Add, Link, x20 y60 w470 h15 , Licensed under the <a href="http://opensource.org/licenses/MIT">MIT license</a>
Gui, 2:Add, Text, x20 y85 w470 h15 , Includes Vista Audio Control Functions, by Lexikos
Gui, 2:Add, Link, x20 y100 w470 h15 , Licensed under Public Domain and available <a href="http://www.autohotkey.com/board/topic/21984-vista-audio-control-functions/">here</a>
Gui, 2:Add, Link, x20 y125 w470 h15 , Audio control OSD thanks to <a href="http://www.autohotkey.com/docs/scripts/VolumeOSD.htm/">Rajat</a>
Gui, 2:Add, Link, x20 y150 w470 h15 , <a href="http://www.autohotkey.com/board/topic/78224-possible-to-monitor-and-pseudo-lock-per-app-volume/">Application Audio control</a> thanks to No_Speak_Eng and Lexikos

Gui, 2:Font, S11 W700, Verdana
Gui, 2:Add, Text, x20 y230 w400 h20 , Available Hotkeys
Gui, 2:Font, S10 W400, Verdana
Gui, 2:Add, Text, x20 y255 w400 h20 , Volume Control
Gui, 2:Add, Text, x220 y255 w400 h20 , Win-WheelUp/Down, Win-PageUp/Down
Gui, 2:Add, Text, x20 y275 w400 h20 , Application Volume Control
Gui, 2:Add, Text, x220 y275 w400 h20 , Win-Shift-WheelUp/Down/PageUp/Down
Gui, 2:Add, Text, x20 y295 w400 h20 , Volume Mute
Gui, 2:Add, Text, x220 y295 w400 h20 , Win-Del, Pause, Media Mute

Gui, Font, S11 CDefault, Verdana
Gui, 2:Add, Button, x175 y335 w130 h30 gAboutClose Default vClose, Close
GuiControl,2: Focus, Close

; Select audio applications
textHelp2 = Enter application name of the active window as it appears in the process list in the Task Manager.
textHelp2 := textHelp2 . " Separate the beginning of process name that instead should be controlled with a space character."
textHelp2 := textHelp2 . " Each line represents one application, up to 20 are supported."
Gui, 4:+Owner1
Gui, 4:Font, S10 W400, Verdana
Gui, 4:Add, Text, x20 y15 w370 h80, %textHelp2%
Gui, 4:Font, S10 W400, Lucida Console
Gui, 4:Add, Edit, x25 y105 w350 h150 r10 vtextAudioApps,
Gui, 4:Font, S11 CDefault, Verdana
Gui, 4:Add, Button, x50 y255 w100 h30 gAudioClose Default, OK
Gui, 4:Add, Button, x200 y255 w100 h30 gAudioCancel, Cancel
GuiControl,4: Focus, OK
 
; ---------------------------------------  
Return  ; End of Auto Execute Section
; ---------------------------------------


; ---------------------------------------  
; retrive values from GUI and apply new values
; ---------------------------------------
retriveValues() {
    global
    enableVol = %boxVolume%
    vol_Step = %textVolume%
    RegWrite, REG_SZ, %reg_root%, %reg_path%, enableVolume, %boxVolume%
    RegWrite, REG_SZ, %reg_root%, %reg_path%, valueVolume, %textVolume%
    applySettings()
}

applySettings() {
    global
    if (strlen(trim(vol_step)) = 0)
        vol_step := vol_step_def
    Guicontrol, , textVolume, %vol_step%

    if (enableVol) {
        Hotkey, Volume_Up, VolumeUp, ON                 ; Media Volume
        Hotkey, Volume_down, VolumeDown, ON         ; Media Volume
        Hotkey, #PgUp, VolumeUp, ON                        ; Win-PageUp
        Hotkey, #PgDn, VolumeDown, ON                    ; Win-PageDown
        Hotkey, $#WheelUp, VolumeUp, ON                ; Win-MouseWheel
        Hotkey, $#WheelDown, VolumeDown, ON        ; Win-MouseWheel
        Hotkey, #Delete, VolumeMute, ON                  ; Win-Delete
        Hotkey, Volume_Mute, VolumeMute, ON          ; Media Mute
        Hotkey, Pause, VolumeMute, ON                     ; Media Mute
        Hotkey, #+WheelUp, AppVolUp, ON                ; App Volume Up
        Hotkey, #+WheelDown, AppVolDown, ON        ; App Volume Down
        Hotkey, #+PgUp, AppVolUp, ON                     ; Win-Shift-PageUp
        Hotkey, #+PgDn, AppVolDown, ON                ; Win-Shift-PageDown
        Hotkey, +Volume_Up, AppVolUp, ON             ; Shift-Media Volume
        Hotkey, +Volume_down, AppVolDown, ON     ; Shift-Media Volume
    } else {
        Hotkey, Volume_Up, VolumeUp, OFF             ; Media Volume
        Hotkey, Volume_down, VolumeDown, OFF     ; Media Volume
        Hotkey, #PgUp, VolumeUp, OFF                    ; Win-PageUp
        Hotkey, #PgDn, VolumeDown, OFF                ; Win-PageDown
        Hotkey, $#WheelUp, VolumeUp, OFF                ; Win-MouseWheel
        Hotkey, $#WheelDown, VolumeDown, OFF        ; Win-MouseWheel
        Hotkey, #Delete, VolumeMute, OFF             ; Win-Delete
        Hotkey, Volume_Mute, VolumeMute, OFF     ; Media Mute
        Hotkey, Pause, VolumeMute, OFF                 ; Media Mute
        Hotkey, #+WheelUp, AppVolUp, OFF            ; App Volume Up
        Hotkey, #+WheelDown, AppVolDown, OFF    ; App Volume Down
        Hotkey, #+PgUp, AppVolUp, OFF                    ; Win-Shift-PageUp
        Hotkey, #+PgDn, AppVolDown, OFF                ; Win-Shift-PageDown
        Hotkey, +Volume_Up, AppVolUp, OFF            ; Shift-Media Volume
        Hotkey, +Volume_down, AppVolDown, OFF     ; Shift-Media Volume
    }
}

getAudioApps() {
    global
    audioAppNum = 0
    loop, 20
    {
        RegRead, getVal, %reg_root%, %reg_path%, audioApp%A_Index%
        if !ErrorLevel && if Trim(getVal) <> ""
        {
            RegRead, getVal2, %reg_root%, %reg_path%, audioApp%A_Index%Value
            if !ErrorLevel && if Trim(getVal2) <> ""
            {
                audioAppNum += 1
                audioApps%audioAppNum% := trim(getVal)
                audioAppFind%audioAppNum% := trim(getVal2)
            }
        } else
            break
    }
    if audioAppNum = 0
    {
        audioApps1 := "firefox.exe"
        audioAppFind1 := "FlashPlayerPlugin"
        audioApps1 := "firefox.exe"
        audioAppFind1 := "plugin-container.exe"
        audioApps2 := "iexplore.exe"
        audioAppFind2 := "iexplore.exe"
        audioAppNum = 2
    }
}


; ---------------------------------------
; Global events and triggers
; ---------------------------------------
 
ExitProgram:
ExitApp

F24::
^+vk51::
    ExitApp
return

Reload:
    Reload
return

Disable:
    if disableHotkeys {
        Menu, TRAY, Check, Disable
        Suspend on
        if A_IsCompiled  ; would change to default H icon
            Menu, Tray, Icon , %A_ScriptFullPath%, 1, 1
    } else {
        Menu, TRAY, Uncheck, Disable
        Suspend off
    }
    disableHotkeys := !disableHotkeys
return

; activates previous active window
actPrevWin:
    WinGet, PName, ProcessName, ahk_pid %curpid%
    if PName <> Explorer.exe
        WinActivate, ahk_id %prevWinID%
return


; ---------------------------------------
; Tray Menu Functions
; ---------------------------------------

TraySettings:
    xpos := A_ScreenWidth / 2 - 430 / 2
    ypos := A_ScreenHeight / 2 - 200 / 2
    Gui, Show, x%xpos% y%ypos% h200 w430, %AppName% Settings
return

; Left Click Menu
notifyIcon(wParam, lParam) {
    if (lParam = 0x202) { ; WM_LBUTTONUP
        SetTimer, ShowRbuttonMenu, -1
        return 0
    }
}

TrayAbout:
    xpos := A_ScreenWidth / 2 - 500 / 2
    ypos := A_ScreenHeight / 2 - 400 / 2
    Gui, 2:Show, x%xpos% y%ypos% h400 w500, About %AppName%
return

ShowRbuttonMenu:
    Menu, Tray, Show
return

ButtonOK:
    Gui, Submit
    Gui, Hide
    retriveValues()
return

GuiClose:
    Gui, Submit
    Gui, Hide
    retriveValues()
return

ButtonCancel:
    Gui, Hide
return

ButtonApply:
    Gui, Submit, NoHide
    retriveValues()
return

GuiEscape:
    Gui, Hide
return

AboutClose:
    Gui, 2:Hide
return



AudioDialog:
    textAudioApps =
    loop, %audioAppNum%
    {
        ta := audioApps%A_Index% . A_Space . audioAppFind%A_Index%
        textAudioApps = %textAudioApps%%ta%`n
    }
    GuiControl, 4:, textAudioApps, %textAudioApps%
    xpos := A_ScreenWidth / 2 - 400 / 2
    ypos := A_ScreenHeight / 2 - 300 / 2
    Gui, 4:Show, x%xpos% y%ypos% h300 w400, Configure Audio Control for Applications
    Gui, 1:+Disabled
return

AudioClose:
    Gui, 1:-Disabled
    Gui, 4:Submit
    Gui, 4:Hide
    lastpos = 1
    audioAppNum = 0
    loop, parse, textAudioApps, `n    
    {
        line := Trim(A_LoopField)  ; trim leading characters
        if line =
            continue
        delimpos := InStr(line, " ")  ; position of delimiter, StringSplit did not work here
        if (delimpos > 0) {   ; must contain at least one white space
            aname := Trim(SubStr(line, 1, delimpos - 1))
            find := Trim(SubStr(line, delimpos + 1))
        } else
            continue
        if Strlen(aname) = 0 || Strlen(find) = 0
            continue
        audioAppNum += 1
        RegWrite, REG_SZ, %reg_root%, %reg_path%, audioApp%A_Index%, %aname%
        RegWrite, REG_SZ, %reg_root%, %reg_path%, audioApp%A_Index%Value, %find%
        if ErrorLevel
            break
        if audioAppNum = 20
            break
    }
    lastpos := audioAppNum + 1
    RegWrite, REG_SZ, %reg_root%, %reg_path%, audioApp%lastpos%
    getAudioApps()
return

AudioCancel:
4GuiClose:
4GuiEscape:
    Gui, 1:-Disabled
    Gui, 4:Hide    
return


; adds or removes the autorun entry
menuAutorun:
    ; get path of current AutoHotkey process, is active window, as it shows the tray menu
    WinGet, pid, PID, A ; for testing on the active windo
    h_process := DllCall("OpenProcess", UInt, 0x418, Int, 0, UInt,pid)
    VarSetCapacity(FilePath, 255)
    DllCall("psapi.dll\GetModuleFileNameEx" (A_IsUnicode ? "W" : "A"), UInt, h_process, UInt, 0, Str, FilePath, UInt, 255)
    DllCall("CloseHandle", UInt, h_process)

    enableAutorun := !enableAutorun
    Menu, TRAY, ToggleCheck, %nameRun%
    if enableAutorun
        RegWrite, REG_SZ , %reg_root%, %reg_path_run%, %RegName%, %FilePath%
    else
        RegDelete, %reg_root%, %reg_path_run%, %RegName%
return

getResolution:
    ; volume bar OSD
    vol_PosX := A_ScreenWidth - vol_Width - 50
    vol_PosY := A_ScreenHeight - vol_Thick - 100
    vol_XY := vol_PosX . "x" . vol_PosY
    vol_oldXY := vol_XY
return


; ---------------------------------------
; Volume Functions for applications
; ---------------------------------------
; http://www.autohotkey.com/board/topic/78224-possible-to-monitor-and-pseudo-lock-per-app-volume/

AppVolUp:
    setAppVolume(vol_step)
return

AppVolDown:
    setAppVolume(-vol_step)    
return

setAppVolume(vol_Step) {
    global
    Res :=
    vol := -1
    WinGet, Pid, PID, A
    WinGet, ProcessName, ProcessName, ahk_pid %Pid%
    if ProcessName = explorer.exe
        Pid := 0 , ProcessName := "System sound", Title = "System sound"    

    appvol_list := Trim(VA_getPID_list(Pid, ProcessName))
    loop, parse, appvol_list, %A_Space%
    {
        if (vol = -1) {
            Res := VA_ISimpleAudioUse("Vol", vol_Step, A_LoopField)
            if (Res <> "" && Res > 0)
                vol := Res
        } else
            VA_ISimpleAudioUse("SetVol", vol, A_LoopField)        
    }
    if (Res <> "") {   ; if an app was found, show bar        
        StringReplace vol_Text, ProcessName, .exe,
        StringLower, vol_Text, vol_Text, T
        vol_Text := vol_Text . " " . (Res = 0 ? "muted" : Res)
        IfWinNotExist, VolumeOSDxyz
            setVolBar()
        Progress, 1:%Res%, , %vol_Text%
        SetTimer, vol_BarOff, %vol_DisplayTime%
    }
    VolumeDelay() ; start delay timer to delay futher steps
}

VA_getPID_list(Pid = "!", ProcessName = "") {
    global
    alist =
    appType := 0
    appToFind :=
    loop, %audioAppNum% {
        if audioApps%A_Index% = %ProcessName%
            appToFind := appToFind . " " . audioAppFind%A_Index%    
    }
    appToFind := trim(appToFind)

    dev := VA_GetDevice()
    if !dev
        Return
    if VA_IMMDevice_Activate(dev, "{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}", 7, 0, mgr) != 0 ; IID_IAudioSessionManager2
        Return ObjRelease(dev)
    if VA_IAudioSessionManager2_GetSessionEnumerator(mgr, enm) != 0
        Return ObjRelease(mgr)
    ObjRelease(mgr)

    VA_IAudioSessionEnumerator_GetCount(enm, count)
    Loop %count% {
        VA_IAudioSessionEnumerator_GetSession(enm, A_Index-1, ssn)
        VA_IAudioSessionControl2_GetProcessId(ssn, curpid)
        if (Pid = curpid)                    ; process is in mixer list
            alist := alist . " " . curpid        
    }
    Loop %count% {
        VA_IAudioSessionEnumerator_GetSession(enm, A_Index-1, ssn)
        VA_IAudioSessionControl2_GetProcessId(ssn, curpid)
        if (curpid > 0 && appType <> "") {                ; find image name
            WinGet, PName, ProcessName, ahk_pid %curpid%
            Loop, parse, appToFind, %A_Space%
            if Instr(PName, A_LoopField)
                    alist := alist . " " . curpid
        }
    }
    return, alist
}

VA_ISimpleAudioUse(Key, Val = "", Pid = "!") {
    dev := VA_GetDevice()
    if !dev
        Return
    if VA_IMMDevice_Activate(dev, "{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}", 7, 0, mgr) != 0 ; IID_IAudioSessionManager2
        Return ObjRelease(dev)
    if VA_IAudioSessionManager2_GetSessionEnumerator(mgr, enm) != 0
        Return ObjRelease(mgr)
    ObjRelease(mgr)

    VA_IAudioSessionEnumerator_GetCount(enm, count)
    Loop %count% {
        VA_IAudioSessionEnumerator_GetSession(enm, A_Index-1, ssn)
        VA_IAudioSessionControl2_GetProcessId(ssn, curpid)
        if (Pid = curpid) {
            sav := ComObjQuery(ssn, "{87CE5498-68D6-44E5-9215-6DA47EF883D8}")                     ; IID_ISimpleAudioVolume
            ObjRelease(ssn)
            if !sav
                Return
            DllCall(NumGet(NumGet(sav+0)+6*A_PtrSize), "ptr", sav, "int*", mute)             ; VA_ISimpleAudioVolume_GetMute
            if (Key = "Vol") {
                DllCall(NumGet(NumGet(sav+0)+4*A_PtrSize), "ptr", sav, "float*", volume) ; VA_ISimpleAudioVolume_GetMasterVolume
                if (Val = "Get")
                    Return Round(volume*100), ObjRelease(sav), ObjRelease(enm)
                if mute = 1
                    DllCall(NumGet(NumGet(sav+0)+5*A_PtrSize), "ptr", sav, "int", 0, "ptr", 0)             ; VA_ISimpleAudioVolume_SetMute
                vol := (volume + Val / 100)
                vol := (vol > 1) ? 1 : (vol < 0) ? 0 : vol
                DllCall(NumGet(NumGet(sav+0)+3*A_PtrSize), "ptr", sav, "float", vol, "ptr", 0)  ; VA_ISimpleAudioVolume_SetMasterVolume
                Return Round(vol*100), ObjRelease(sav), ObjRelease(enm)
            }
            if (Key = "Mute") {
                if (Val = "Get")
                    Return mute, ObjRelease(sav), ObjRelease(enm)
                DllCall(NumGet(NumGet(sav+0)+5*A_PtrSize), "ptr", sav, "int", mute := (Val = 2) ? !mute : Val, "ptr", 0) ; VA_ISimpleAudioVolume_SetMute
                Return mute, ObjRelease(sav), ObjRelease(enm)
            }
            if (Key = "SetVol") {
                if mute = 1
                    DllCall(NumGet(NumGet(sav+0)+5*A_PtrSize), "ptr", sav, "int", 0, "ptr", 0) ; VA_ISimpleAudioVolume_SetMute  
                DllCall(NumGet(NumGet(sav+0)+3*A_PtrSize), "ptr", sav, "float", Val / 100, "ptr", 0) ; VA_ISimpleAudioVolume_SetMasterVolume
                Return Val, ObjRelease(sav), ObjRelease(enm)
            }
        }
        ObjRelease(ssn), ListPid .= curpid "|"
    }
    ObjRelease(enm)

    if (Key = "ListPid") {
        Loop, parse, ListPid, |
            List .= (WinExist("ahk_pid " A_LoopField) ? A_LoopField "|" : "")
        Return RTrim( List, "|")
    }
}


; ---------------------------------------
; Volume Control Functions
; ---------------------------------------
; http://www.autohotkey.com/board/topic/45383-vista-windows-7-simple-volume-control/

VolumeDown:
    if (vol_Master > .01)    {
        VA_SetMasterVolume(vol_Master-=vol_Step)
        if vol_Master <= 0
            VA_SetMasterMute(True)
    }
    Gosub, vol_ShowBars
    VolumeDelay()
return

VolumeUp:
    if (vol_Master <= 99) {
        VA_SetMasterVolume(vol_Master+=vol_Step)
        if vol_Master > 1
            VA_SetMasterMute(False)
    }
    Gosub, vol_ShowBars
    VolumeDelay()
return

VolumeDelay() {
    GetKeyState, winkeyL, LWin
    GetKeyState, winkeyR, RWin
    key = %winkeyL%%winkeyR%
    GetKeyState, volkey, Volume_Down   ; check key after delay
    key = %winkeyL%%winkeyR%%volkey%
  ; sometimes Autohotkey is buggy, none of the other key comparisons worked here
    IfInString, key, UUU        ; add short delay on single key presses
        Sleep, 150
}

VolumeMute:    
    VA_SetMasterMute(!VA_GetMasterMute())
    Gosub, vol_ShowBars
    Sleep, 300
return

vol_ShowBars:
    ; Get volumes in case the user or an external program changed them:
    vol_Master := VA_GetMasterVolume()    
    vol_Mute := VA_GetMasterMute()

    if vol_Mute = 1
    {
        vol_Master = 0
        vol_Text = Master Volume muted
    } else {
        vol_Level := SubStr(vol_Master, 1, StrLen(vol_Master) -4) ; remove fractions, last 4 chars
        vol_Text = Master Volume %vol_Level%
    }

    ; To prevent the "flashing" effect, only create the bar window if it doesn't already exist:
    IfWinNotExist, VolumeOSDxyz
        setVolBar()
    Progress, 1:%vol_Master%, , %vol_Text%
    SetTimer, vol_BarOff, %vol_DisplayTime%
return

vol_BarOff:
    SetTimer, vol_BarOff, off
    Progress, 1:Off
return

setVolBar() {
    global
    Sysget, isRDP, 4096
    vol_Col := isRDP ? vol_Col_rdp : vol_Col_def
    vol_BarOptionsMaster = 1:B1 ZH%vol_Thick% ZX8 ZY4 W%vol_Width% X%vol_PosX% Y%vol_PosY% CW%vol_CW%
    Progress, %vol_BarOptionsMaster% CB%vol_Col% CT%vol_Col%, , %vol_Text%, VolumeOSDxyz
    WinSet, Transparent, %vol_TransValue%, VolumeOSDxyz
}

21

Re: AHK: Управление микшером в контексте приложений

svoboden, спасибо! Работает! То, что нужно.

Win10x64

22

Re: AHK: Управление микшером в контексте приложений

svoboden, могли бы Вы помочь заменить имеющееся визуальное сопровождение посредством GUI обычными ToolTip'ами? Т.е. чтобы информация об уровне громкости отражалась в ToolTips, а все визуальное оформление было упразднено, включая настройки из TrayMenu.

Думаю, я бы мог поудалять все строки с упоминанием GUI, но добавить весто них ToolTips у меня вряд ли получится верным образом.

Win10x64

23 (изменено: svoboden, 2017-03-31 02:23:22)

Re: AHK: Управление микшером в контексте приложений

Замени Progress на ToolTip.

24

Re: AHK: Управление микшером в контексте приложений

svoboden, заменил, но могли бы Вы привести пример на одной из строк, чтобы информация в тултипе отражалась аналогично трейтипу? Т.к. сейчас там отражаются лишние значения, а названий приложений (в которых регулируется уровень громкости) нет вовсе.

Win10x64

25 (изменено: svoboden, 2017-04-07 00:46:07)

Re: AHK: Управление микшером в контексте приложений

becauseim, так найди нужную переменную и вставь ее в ToolTip, или создай ее сам.

26

Re: AHK: Управление микшером в контексте приложений

После 1.1.28.02 в анк32 под ос64 не работает.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

27

Re: AHK: Управление микшером в контексте приложений

У меня на такой же системе 1.1.29.01 код из 8 поста работает.

28 (изменено: serzh82saratov, 2018-06-18 17:09:31)

Re: AHK: Управление микшером в контексте приложений

Блин не проверил, тот работает. Не работает этот, Mute не переключается, громкость не регулируется. На предыдущих версиях уже очень давно всё норм.
Работает с окном под курсором.


#SingleInstance Force
#NoEnv

1::AppVolume("Vol", -10)
2:: AppVolume("Vol", +10)
3:: AppVolume("Mute", 2)  ;	Toggle Mute


AppVolume(Key, Val) { 
	MouseGetPos, , , winid
	WinGet, PID, PID, ahk_id %winid%
    WinGet, ProcessName, ProcessName, ahk_id %winid%   
	StringUpper, ProcessName, ProcessName
	SplitPath, ProcessName, , , , ProcessName					
    if ProcessName = explorer 
        Pid := 0 , ProcessName := "Системные`nзвуки"
    Res := VA_AppVolume(Key, Val, Pid)
	if Res =
		Message := ProcessName "`n`nОтсутствует в микшере", ColorF := "Red", Font := 22
	else if Key = Mute
		Message := ProcessName "`n`n" (Res = 0 ? "Mute OFF": "Mute ON") , ColorF := (Res = 0 ? "Yellow" : "Red") , Font := 22
	else
		Message := ProcessName "`n`n" Res  " `%", Font := (Res / 10 + 20), ColorF := 0xFFFFFF
	GuiTip( Message, Font, ColorF)
}

GuiTip( Text, sFont, ColorF = "", ColorG = "7890A1", Timer = 1000)     {
    Static hToolTip 
    Gui, TT: +AlwaysOnTop +ToolWindow -0x400000 +E0x08000000
    Gui, TT: Color, %ColorG% 
    Gui, TT: Font, s%sFont% Italic, Times New Roman
	DllCall("DestroyWindow", "Ptr", hToolTip) 
    Gui TT: Add, Text, Center gDestroyTT hwndhToolTip x30 y10 c%ColorF%, % Text 
	Gui TT: Show, NA xCenter y5 AutoSize
    SetTimer, DestroyTT, -%Timer%
    Return 
    DestroyTT:  
        Gui, TT: Destroy
        Return
}	

VA_AppVolume(Key, Val = "", Pid = "!")
{
    dev := VA_GetDevice()
    if !dev
        Return
    if VA_IMMDevice_Activate(dev, "{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}", 7, 0, mgr) != 0 ; IID_IAudioSessionManager2
        Return ObjRelease(dev)
    ObjRelease(dev)
    if VA_IAudioSessionManager2_GetSessionEnumerator(mgr, enm) != 0
        Return ObjRelease(mgr)
    ObjRelease(mgr)
    VA_IAudioSessionEnumerator_GetCount(enm, count) 
    Loop % count
    {
        VA_IAudioSessionEnumerator_GetSession(enm, A_Index-1, ssn)
        VA_IAudioSessionControl2_GetProcessId(ssn, curpid)
        if (Pid = curpid)
        {
			sav := ComObjQuery(ssn, "{87CE5498-68D6-44E5-9215-6DA47EF883D8}") ; IID_ISimpleAudioVolume
			ObjRelease(ssn)
			if !sav
				Return
            DllCall(NumGet(NumGet(sav+0)+6*A_PtrSize), "uint", sav, "int*", mute) ; GetMute
			if (Key = "Vol")
			{
				DllCall(NumGet(NumGet(sav+0)+4*A_PtrSize), "uint", sav, "float*", volume) ; GetVolume
				if mute = 1
					DllCall(NumGet(NumGet(sav+0)+5*A_PtrSize), "uint", sav, "int", 0) ; SetMute
				vol := (volume + Val / 100)
				vol := (vol > 1) ? 1 : (vol < 0) ? 0 : vol
				DllCall(NumGet(NumGet(sav+0)+3*A_PtrSize), "uint", sav, "float", vol) ; SetVolume
				Return Round(vol*100), ObjRelease(sav), ObjRelease(enm)
			}
            if (Key = "Mute")
            {
				if (Val = "Get")
					Return mute, ObjRelease(sav), ObjRelease(enm)
				DllCall(NumGet(NumGet(sav+0)+5*A_PtrSize), "uint", sav, "int", mute := (Val = 2) ? !mute : Val) ; SetMute
                Return mute, ObjRelease(sav), ObjRelease(enm)
            }
			if (Key = "SetVol")
			{
				if mute = 1
					DllCall(NumGet(NumGet(sav+0)+5*A_PtrSize), "uint", sav, "int", 0) ; SetMute
				DllCall(NumGet(NumGet(sav+0)+3*A_PtrSize), "uint", sav, "float", Val / 100) ; SetVolume
				Return Val, ObjRelease(sav), ObjRelease(enm)
			}
			if (Key = "GetVol")
			{
				DllCall(NumGet(NumGet(sav+0)+4*A_PtrSize), "uint", sav, "float*", volume) ; GetVolume
				Return Round(volume*100), ObjRelease(sav), ObjRelease(enm)
			}
        }
        ObjRelease(ssn)
		ListPid .= curpid "|"
    }
    ObjRelease(enm)

	if (Key = "ListPid")
	{
		Loop, parse, ListPid, |
			List .= (WinExist("ahk_pid " A_LoopField) ? A_LoopField "|" : "")
		Return RTrim( List, "|")
	}
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

29

Re: AHK: Управление микшером в контексте приложений

А чего не хочешь заменить свою функцию, на ту, которая работает?

30

Re: AHK: Управление микшером в контексте приложений

А тут где не рабочая, разве не тоже самое?
Во вторых интересно почему на 1.1.28.02 и более ранних всё работает.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

31

Re: AHK: Управление микшером в контексте приложений

Ну раз не работает, значит не тоже самое.
А зачем ты сократил изначальную функцию:

VA_ISimpleAudioVolume_SetMute(this, Mute, EventContext="") {
    return DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "uint", this, "int", Mute, "uint", VA_GUID(EventContext))

на:

DllCall(NumGet(NumGet(sav+0)+5*A_PtrSize), "uint", sav, "int", mute := (Val = 2) ? !mute : Val) ; SetMute

32

Re: AHK: Управление микшером в контексте приложений

Давно писал уже, видимо тогда хотелось всё сократить, но там последний параметр всё равно 0.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

33

Re: AHK: Управление микшером в контексте приложений

Если вставить этот параметр, то работает.

34

Re: AHK: Управление микшером в контексте приложений

Да, действительно добавил нули, заработало. Значит ошибка была в предыдущих версиях, вроде в DllCall последние опущенные параметры равнялись нулю, во всяком случае я так думал.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

35

Re: AHK: Управление микшером в контексте приложений

Кстати не знаешь что должен делать VA_GUID(EventContext) в SetMute и SetVolume.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

36

Re: AHK: Управление микшером в контексте приложений

https://msdn.microsoft.com/en-us/librar … s.85).aspx
И кстати, он не равен нулю.

msgbox % VA_GUID("")

37

Re: AHK: Управление микшером в контексте приложений

Я из описания не понял что это и зачем, подумал может ты это как то используешь.
Заменил 0 на VA_GUID(""), тоже норм.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

38 (изменено: Malcev, 2018-06-18 19:04:25)

Re: AHK: Управление микшером в контексте приложений

Не, не использую.
Я даже не вдавался в подробности, как этот интерфейс работает.

serzh82saratov пишет:

Заменил 0 на VA_GUID(""), тоже норм.

До следующего апдейта. )))

39

Re: AHK: Управление микшером в контексте приложений

В каком посте последняя обновленная рабочая версия скрипта?

Win10x64

40 (изменено: serzh82saratov, 2018-06-18 19:59:26)

Re: AHK: Управление микшером в контексте приложений

У меня это работает, писал давно, с тех пор код не причёсывал.
Работает с окном под курсором.


1:: AppVolume("Vol", -10)
2:: AppVolume("Vol", +10)
3:: AppVolume("Mute", 2)  ; переключать Mute
4:: ExclusiveAppVolume() ; оставить звук только этого приложения 
5:: AppVolume("SetVol", 10)
6:: AppVolume("Mute", "Get")
7:: AppVolume("GetVol")

AppVolume(Key, Val = "") { 
	MouseGetPos, , , winid
	WinGet, PID, PID, ahk_id %winid%
    WinGet, ProcessName, ProcessName, ahk_id %winid%   
	StringUpper, ProcessName, ProcessName
	SplitPath, ProcessName, , , , ProcessName					
    if ProcessName = explorer 
        Pid := 0 , ProcessName := "Системные`nзвуки"
    Res := VA_AppVolume(Key, Val, Pid)
	if Res =
		Message := ProcessName "`n`nОтсутствует в микшере", ColorF := "Red", Font := 22
	else if Key = Mute
		Message := ProcessName "`n`n" (Res = 0 ? "Mute OFF": "Mute ON") , ColorF := (Res = 0 ? "Yellow" : "Red") , Font := 22
	else
		Message := ProcessName "`n`n" Res  " `%", Font := (Res / 10 + 20), ColorF := 0xFFFFFF
	GuiTip( Message, Font, ColorF)
}

ExclusiveAppVolume() {
    Static T, PrPid
	MouseGetPos, , , winid
	WinGet, PID, PID, ahk_id %winid%
    WinGet, Text, ProcessName, ahk_pid %Pid%
    Text := RTrim( Text, "\.exe")
    StringUpper, Text, Text
	if Text = explorer 
        Pid := 0 , Text := "Системные звуки" 
    ListPid := 0 "|" VA_AppVolume("ListPid")
    ListPid := RTrim( RegExReplace( ListPid, "S)(^|\|)" Pid "($|\|)", "$1", Count, 1), "|") 
    If !Count
        Return
    T := PrPid = Pid ? !T : 1
    PrPid := Pid
    Loop, parse, ListPid, | 
        VA_AppVolume("Mute", T, A_LoopField) 
    VA_AppVolume("Mute", 0, Pid)    
	GuiTip( "Exclusive app sound `n" (T ? "Только `n`n""  " Text """ " : "`nВсе звуки включены "), 22, !T ? "Yellow" : "Red", 696969, 1500)
}

GuiTip( Text, sFont, ColorF = "", ColorG = "7890A1", Timer = 1000)     {
    Static hToolTip 
    Gui, TT: +AlwaysOnTop +ToolWindow -0x400000 +E0x08000000
    Gui, TT: Color, %ColorG% 
    Gui, TT: Font, s%sFont% Italic, Times New Roman
	DllCall("DestroyWindow", "Ptr", hToolTip) 
    Gui TT: Add, Text, Center gDestroyTT hwndhToolTip x30 y10 c%ColorF%, % Text 
	Gui TT: Show, NA xCenter y5 AutoSize
    SetTimer, DestroyTT, -%Timer%
    Return 
    DestroyTT:  
        Gui, TT: Destroy
        Return
}

VA_AppVolume(Key, Val = "", Pid = "!")
{
    dev := VA_GetDevice()
    if !dev
        Return
    if VA_IMMDevice_Activate(dev, "{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}", 7, 0, mgr) != 0 ; IID_IAudioSessionManager2
        Return ObjRelease(dev)
    ObjRelease(dev)
    if VA_IAudioSessionManager2_GetSessionEnumerator(mgr, enm) != 0
        Return ObjRelease(mgr)
    ObjRelease(mgr)
    VA_IAudioSessionEnumerator_GetCount(enm, count) 
    Loop % count
    {
        VA_IAudioSessionEnumerator_GetSession(enm, A_Index-1, ssn)
        VA_IAudioSessionControl2_GetProcessId(ssn, curpid)
        if (Pid = curpid) 
        {
			sav := ComObjQuery(ssn, "{87CE5498-68D6-44E5-9215-6DA47EF883D8}") ; IID_ISimpleAudioVolume
			ObjRelease(ssn)
			if !sav
				Return
            DllCall(NumGet(NumGet(sav+0)+6*A_PtrSize), "uint", sav, "int*", mute) ; GetMute
			if (Key = "Vol")
			{
				DllCall(NumGet(NumGet(sav+0)+4*A_PtrSize), "uint", sav, "float*", volume) ; GetVolume
				if mute = 1
					DllCall(NumGet(NumGet(sav+0)+5*A_PtrSize), "uint", sav, "int", 0, "uint", 0, "uint", VA_GUID("")) ; SetMute
				vol := (volume + Val / 100)
				vol := (vol > 1) ? 1 : (vol < 0) ? 0 : vol
				DllCall(NumGet(NumGet(sav+0)+3*A_PtrSize), "uint", sav, "float", vol, "uint", VA_GUID("")) ; SetVolume
				Return Round(vol*100), ObjRelease(sav), ObjRelease(enm)
			}
            if (Key = "Mute")
            {
				if (Val = "Get")
					Return mute, ObjRelease(sav), ObjRelease(enm)
				DllCall(NumGet(NumGet(sav+0)+5*A_PtrSize), "uint", sav, "int", mute := (Val = 2) ? !mute : Val, "uint", VA_GUID("")) ; SetMute
                Return mute, ObjRelease(sav), ObjRelease(enm)
            }
			if (Key = "SetVol")
			{
				if mute = 1
					DllCall(NumGet(NumGet(sav+0)+5*A_PtrSize), "uint", sav, "int", 0, "uint", VA_GUID("")) ; SetMute
				DllCall(NumGet(NumGet(sav+0)+3*A_PtrSize), "uint", sav, "float", Val / 100, "uint", VA_GUID("")) ; SetVolume
				Return Val, ObjRelease(sav), ObjRelease(enm)
			}
			if (Key = "GetVol")
			{
				DllCall(NumGet(NumGet(sav+0)+4*A_PtrSize), "uint", sav, "float*", volume) ; GetVolume
				Return Round(volume*100), ObjRelease(sav), ObjRelease(enm)
			}
        }
        ObjRelease(ssn)
		ListPid .= curpid "|"
    }
    ObjRelease(enm)

	if (Key = "ListPid")
	{
		Loop, parse, ListPid, |
			List .= (WinExist("ahk_pid " A_LoopField) ? A_LoopField "|" : "")
		Return RTrim( List, "|")
	}
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.32.00 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

41

Re: AHK: Управление микшером в контексте приложений

serzh82saratov, добавьте, пожалуйста, хоткей на сброс параметров микшера до 100% для всех приложений (если возможно, то в т.ч. и закрытых в данный момент), кроме системных звуков.

Win10x64