Control the volume of all programs and current program - code cleansing

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
submeg
Posts: 335
Joined: 14 Apr 2017, 20:39
Contact:

Control the volume of all programs and current program - code cleansing

05 Jun 2022, 03:08

Hi all,

I've been looking to control the volume of different applications on my PC using AHK. From some searching, I came across the following threads:

1. Control the Volume of each program; thanks to @Flipeador and @Bunker D for their input on this thread.
2. Control the volume of the current program; thanks to @mikeyww for his contribution on this thread.

Using these two as a guide, I created my own script. What it does -

1. F1 = Mutes all applications.
2. F2 = Sets all applications to 25% of the master volume.
3. F3 = Sets all applications to 50% of the master volume.
4. F4 = Prompts the user if they wish to set all applications to 100% of the master volume.
5. F5 = Increases the volume of the current application in steps of 10% of the master volume until 90% of the volume, and then mutes. This is a continuous cycle, pressing F5 steps through each stage.

I'd like to neaten up my code, specifically if I can completely remove FindAppVolume(appName), as this is just a copy of @Bunker D's ShiftAppVolume( appName, incr ) code, just without changing the volume. The only reason I copied it was that I didn't understand exactly how to extract PrevVolume without increasing the volume as well. Any pointers / descriptions / understanding / explanations would be greatly appreciated. Thanks!

Code: Select all


#NoEnv
#SingleInstance Force
SetBatchLines -1

ProcessPID := ""		;The ID of the current program

;Cycling through all the active processes, see here - https://www.autohotkey.com/boards/viewtopic.php?p=180272#p180272
;Changing the volumes of programs - https://www.autohotkey.com/boards/viewtopic.php?p=210533&sid=7424e9efc9c2600470b2492266161dbb#p210533
	
OUT_LIST := ""						;The variable for storing the list of open processes.
COUNT_NO_PATHS := 0					;The count of open processes.

;AccessRights_EnableSeDebug()		;Commented out this as works without. 
;Enables the SE_DEBUG_PRIVILEGE for the current process. Maybe it can be useful to resolve some "access denied" stuff when dealing with processes.
;https://www.autohotkey.com/boards/viewtopic.php?t=2039

;Clipboard := OUT_LIST 				;used for placing all process IDs into the clipboard so it can sent to an application.

;This is to reset any tool tip
RemoveToolTip:						;;Tooltip reset
ToolTip

;---------------------------------------------

F12::

run, C:\Windows\System32\SndVol.exe		;Show the volume mixer

Return


F1::

SetAllVolume(0)

msg:= "All applications muted."
	
ToolTip, %msg%

SetTimer, RemoveToolTip, -700

msg := ""

Return


F2::

SetAllVolume(25)

msg:= "All applications set to 25% of master volume."
	
ToolTip, %msg%

SetTimer, RemoveToolTip, -700

msg := ""

Return


F3::

SetAllVolume(50)

msg:= "All applications set to 50% of master volume."
	
ToolTip, %msg%

SetTimer, RemoveToolTip, -700

msg := ""

Return


F4::

SetAllVolume_100()

msg:= "All applications set to 100% of master volume."
	
ToolTip, %msg%

SetTimer, RemoveToolTip, -700

msg := ""

Return


F5::

;Cycle through the volume levels for the active program.
VolumeCycle(VolCycleLevel)

Return

;---------------------------------------
;=======================================

SetAllVolume(VolValue)
{

	for i, v in WTSEnumerateProcessesEx()
	{
		
		SetAppVolume(v.ProsessID, VolValue)
		
		;FullEXEPath := GetModuleFileNameEx( v.ProsessID )
		;OUT_LIST := OUT_LIST . "Name: " . v.ProcessName . "`nPath: " . FullEXEPath . "`nLegal: " .  FileGetInfo( FullEXEPath ).LegalCopyright . "`n`n"
		
	}

}
Return


SetAllVolume_100()
{
	
	MsgBox, 4,, WARNING! `r`rThis will set ALL volume to 100. Would you like to continue? (press Yes or No)
	IfMsgBox Yes
		for i, v in WTSEnumerateProcessesEx()
		{
			FullEXEPath := GetModuleFileNameEx( v.ProsessID )
			SetAppVolume(v.ProsessID, 100)

			;OUT_LIST := OUT_LIST . "Name: " . v.ProcessName . "`nPath: " . FullEXEPath . "`nLegal: " .  FileGetInfo( FullEXEPath ).LegalCopyright . "`n`n"
			
		}

}
Return


VolumeCycle(VolCycleLevel)
{
	
	;First, find the active program (name and PID).
	DetectHiddenWindows on
	
    WinGet, PID, PID, A
    IfWinExist ahk_pid %PID%
    {
        WinGet, ProcessEXE, ProcessName
		WinGet, ProcessPID, PID
    }
	
	;msgbox % "PID is: " ProcessPID "`rEXE is: " ProcessEXE
	
	;Find the volume level of the current program.
	CurrentVolLevel := FindAppVolume(ProcessEXE)
	;msgbox % "Current Volume level of " ProcessEXE " is: " CurrentVolLevel " of the Master volume level"

	
	Switch 
	{
		
		case CurrentVolLevel == 0:		;Change from mute to 10%.
			
			SetAppVolume(ProcessPID, 10)
			
			msg:= ProcessEXE . " set to 10% of master volume."
	
			ToolTip, %msg%

			SetTimer, RemoveToolTip, -700

			msg := ""
	
		case CurrentVolLevel <= 0.1:		;Change from 10% to 20%.
					
			SetAppVolume(ProcessPID, 20)
			
			msg:= ProcessEXE . " set to 20% of master volume."
	
			ToolTip, %msg%

			SetTimer, RemoveToolTip, -700

			msg := ""
		
		case CurrentVolLevel <= 0.2:		;Change from 20% to 30%.
			
			SetAppVolume(ProcessPID, 30)
			
			msg:= ProcessEXE . " set to 30% of master volume."
	
			ToolTip, %msg%

			SetTimer, RemoveToolTip, -700

			msg := ""
		
		case CurrentVolLevel <= 0.3:		;Change from 30% to 40%.
			
			SetAppVolume(ProcessPID, 40)
			
			msg:= ProcessEXE . " set to 40% of master volume."
	
			ToolTip, %msg%

			SetTimer, RemoveToolTip, -700

			msg := ""
			
		case CurrentVolLevel <= 0.4:		;Change from 40% to 50%.
			
			SetAppVolume(ProcessPID, 50)
			
			msg:= ProcessEXE . " set to 50% of master volume."
	
			ToolTip, %msg%

			SetTimer, RemoveToolTip, -700

			msg := ""
			
		case CurrentVolLevel <= 0.5:		;Change from 50% to 60%.
			
			SetAppVolume(ProcessPID, 60)
			
			msg:= ProcessEXE . " set to 60% of master volume."
	
			ToolTip, %msg%

			SetTimer, RemoveToolTip, -700

			msg := ""
			
		case CurrentVolLevel <= 0.6:		;Change from 60% to 70%.
			
			SetAppVolume(ProcessPID, 70)
			
			msg:= ProcessEXE . " set to 70% of master volume."
	
			ToolTip, %msg%

			SetTimer, RemoveToolTip, -700

			msg := ""
			
		case CurrentVolLevel <= 0.7:		;Change from 70% to 80%.
			
			SetAppVolume(ProcessPID, 80)
			
			msg:= ProcessEXE . " set to 80% of master volume."
	
			ToolTip, %msg%

			SetTimer, RemoveToolTip, -700

			msg := ""
			
		case CurrentVolLevel <= 0.8:		;Change from 80% to 90%.
		
			SetAppVolume(ProcessPID, 90)
			
			msg:= ProcessEXE . " set to 90% of master volume."
	
			ToolTip, %msg%

			SetTimer, RemoveToolTip, -700

			msg := ""
			
		case CurrentVolLevel <= 0.9:		;Change from 90% to mute.
		
			SetAppVolume(ProcessPID, 0)
			
			msg:= ProcessEXE . " muted."
	
			ToolTip, %msg%

			SetTimer, RemoveToolTip, -700

			msg := ""

	}
	
	
}
Return 


; ==============================================================
; WTSEnumerateProcessesEx() By JNIZM - https://autohotkey.com/boards/viewtopic.php?t=19323
;==============================================================

Return
WTSEnumerateProcessesEx()
{
    static hWTSAPI := DllCall("LoadLibrary", "str", "wtsapi32.dll", "ptr")

    if !(DllCall("wtsapi32\WTSEnumerateProcessesEx", "ptr", 0, "uint*", 0, "uint", -2, "ptr*", buf, "uint*", TTL))
        throw Exception("WTSEnumerateProcessesEx failed", -1)
    
	addr := buf 
	WTS_PROCESS_INFO := []
    
	loop % TTL
    {
        WTS_PROCESS_INFO[A_Index, "SessionID"]   := NumGet(addr+0, "uint")
        WTS_PROCESS_INFO[A_Index, "ProsessID"]   := NumGet(addr+4, "uint")
        WTS_PROCESS_INFO[A_Index, "ProcessName"] := StrGet(NumGet(addr+8, "ptr"))
        WTS_PROCESS_INFO[A_Index, "UserSID"]     := NumGet(addr+8+A_PtrSize, "ptr")
        addr += 8 + (A_PtrSize * 2)
    }
    if !(DllCall("wtsapi32\WTSFreeMemoryEx", "int", 0, "ptr", buf, "uint", TTL))
        throw Exception("WTSFreeMemoryEx failed", -1)
    return WTS_PROCESS_INFO
}

Return


; =================================================================================================
; GetModuleFileNameEx() By Shimanov as cited by SKAN - https://autohotkey.com/board/topic/41197-getting-a-full-executable-path-from-a-running-process/
; Modified to use GetModuleFileNameExW if A_IsUnicode - By Gio - 03-11-17
;=================================================================================================

GetModuleFileNameEx( p_pid ) ; by shimanov -  www.autohotkey.com/forum/viewtopic.php?t=9000
{
   if A_OSVersion in WIN_95,WIN_98,WIN_ME
   {
      MsgBox, This Windows version (%A_OSVersion%) is not supported.
      return
   }
   h_process := DllCall( "OpenProcess", "uint", 0x10|0x400, "int", false, "uint", p_pid )
   if ( ErrorLevel or h_process = 0 )
      return
   name_size = 255
   VarSetCapacity( name, name_size )
   If A_IsUnicode
      result := DllCall( "psapi.dll\GetModuleFileNameExW", "uint", h_process, "uint", 0, "str" , name, "uint", name_size )
    Else
      result := DllCall( "psapi.dll\GetModuleFileNameExA", "uint", h_process, "uint", 0, "str" , name, "uint", name_size )
   DllCall( "CloseHandle", h_process )
   return, name
}


SetAppVolume(pid, MasterVolume)    ; WIN_V+
{
    IMMDeviceEnumerator := ComObjCreate("{BCDE0395-E52F-467C-8E3D-C4579291692E}", "{A95664D2-9614-4F35-A746-DE8DB63617E6}")
    DllCall(NumGet(NumGet(IMMDeviceEnumerator+0)+4*A_PtrSize), "UPtr", IMMDeviceEnumerator, "UInt", 0, "UInt", 1, "UPtrP", IMMDevice, "UInt")
    ObjRelease(IMMDeviceEnumerator)

    VarSetCapacity(GUID, 16)
    DllCall("Ole32.dll\CLSIDFromString", "Str", "{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}", "UPtr", &GUID)
    DllCall(NumGet(NumGet(IMMDevice+0)+3*A_PtrSize), "UPtr", IMMDevice, "UPtr", &GUID, "UInt", 23, "UPtr", 0, "UPtrP", IAudioSessionManager2, "UInt")
    ObjRelease(IMMDevice)

    DllCall(NumGet(NumGet(IAudioSessionManager2+0)+5*A_PtrSize), "UPtr", IAudioSessionManager2, "UPtrP", IAudioSessionEnumerator, "UInt")
    ObjRelease(IAudioSessionManager2)

    DllCall(NumGet(NumGet(IAudioSessionEnumerator+0)+3*A_PtrSize), "UPtr", IAudioSessionEnumerator, "UIntP", SessionCount, "UInt")
    Loop % SessionCount
    {
        DllCall(NumGet(NumGet(IAudioSessionEnumerator+0)+4*A_PtrSize), "UPtr", IAudioSessionEnumerator, "Int", A_Index-1, "UPtrP", IAudioSessionControl, "UInt")
        IAudioSessionControl2 := ComObjQuery(IAudioSessionControl, "{BFB7FF88-7239-4FC9-8FA2-07C950BE9C6D}")
        ObjRelease(IAudioSessionControl)

        DllCall(NumGet(NumGet(IAudioSessionControl2+0)+14*A_PtrSize), "UPtr", IAudioSessionControl2, "UIntP", ProcessId, "UInt")
        If (pid == ProcessId)
        {
            ISimpleAudioVolume := ComObjQuery(IAudioSessionControl2, "{87CE5498-68D6-44E5-9215-6DA47EF883D8}")
            DllCall(NumGet(NumGet(ISimpleAudioVolume+0)+3*A_PtrSize), "UPtr", ISimpleAudioVolume, "Float", MasterVolume/100.0, "UPtr", 0, "UInt")
            ObjRelease(ISimpleAudioVolume)
        }
        ObjRelease(IAudioSessionControl2)
    }
    ObjRelease(IAudioSessionEnumerator)
}



ShiftAppVolume( appName, incr )
{
    if !appName
    {
        WinGet, activePID, ID, A
        WinGet, activeName, ProcessName, ahk_id %activePID%
        appName := activeName        
    }
    
    IMMDeviceEnumerator := ComObjCreate( "{BCDE0395-E52F-467C-8E3D-C4579291692E}", "{A95664D2-9614-4F35-A746-DE8DB63617E6}" )
    DllCall( NumGet( NumGet( IMMDeviceEnumerator+0 ) + 4*A_PtrSize ), "UPtr", IMMDeviceEnumerator, "UInt", 0, "UInt", 1, "UPtrP", IMMDevice, "UInt" )
    ObjRelease(IMMDeviceEnumerator)

    VarSetCapacity( GUID, 16 )
    DllCall( "Ole32.dll\CLSIDFromString", "Str", "{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}", "UPtr", &GUID)
    DllCall( NumGet( NumGet( IMMDevice+0 ) + 3*A_PtrSize ), "UPtr", IMMDevice, "UPtr", &GUID, "UInt", 23, "UPtr", 0, "UPtrP", IAudioSessionManager2, "UInt" )

    DllCall( NumGet( NumGet( IAudioSessionManager2+0 ) + 5*A_PtrSize ), "UPtr", IAudioSessionManager2, "UPtrP", IAudioSessionEnumerator, "UInt" )
    ObjRelease( IAudioSessionManager2 )
    
    DllCall( NumGet( NumGet( IAudioSessionEnumerator+0 ) + 3*A_PtrSize ), "UPtr", IAudioSessionEnumerator, "UIntP", SessionCount, "UInt" )
    levels := []
    maxlevel := 0
    targets := []
    t := 0
    ISAVs := []
    Loop % SessionCount
    {
        DllCall( NumGet( NumGet( IAudioSessionEnumerator+0 ) + 4*A_PtrSize ), "UPtr", IAudioSessionEnumerator, "Int", A_Index-1, "UPtrP", IAudioSessionControl, "UInt" )
        IAudioSessionControl2 := ComObjQuery( IAudioSessionControl, "{BFB7FF88-7239-4FC9-8FA2-07C950BE9C6D}" )
        ObjRelease( IAudioSessionControl )
        
        DllCall( NumGet( NumGet( IAudioSessionControl2+0 ) + 14*A_PtrSize ), "UPtr", IAudioSessionControl2, "UIntP", PID, "UInt" )
        
        PHandle := DllCall( "OpenProcess", "uint", 0x0010|0x0400, "Int", false, "UInt", PID )
        if !( ErrorLevel or PHandle = 0 )
        {
            name_size = 1023
            VarSetCapacity( PName, name_size )
            DllCall( "psapi.dll\GetModuleFileNameEx" . ( A_IsUnicode ? "W" : "A" ), "UInt", PHandle, "UInt", 0, "Str", PName, "UInt", name_size )
            DllCall( "CloseHandle", PHandle )
            SplitPath PName, PName
            
            if incr
            {
                t += 1
                
                ISimpleAudioVolume := ComObjQuery(IAudioSessionControl2, "{87CE5498-68D6-44E5-9215-6DA47EF883D8}")
                DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 4*A_PtrSize ), "UPtr", ISimpleAudioVolume, "FloatP", level, "UInt" )  ; Get volume
                
                if ( PName = appName )
                {
                    level += incr
                    targets.push( t )
                    DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 5*A_PtrSize ), "UPtr", ISimpleAudioVolume, "Int", 0, "UPtr", 0, "UInt" )  ; Unmute
                }
                ISAVs.push( ISimpleAudioVolume )
                levels.push( level )
                maxlevel := max( maxlevel, level )
            }
            else
            {
                if ( PName = appName )
                {
                    ISimpleAudioVolume := ComObjQuery(IAudioSessionControl2, "{87CE5498-68D6-44E5-9215-6DA47EF883D8}")
                    DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 6*A_PtrSize ), "UPtr", ISimpleAudioVolume, "IntP", muted )  ; Get mute status
                    maxlevel := maxlevel or muted
                    ISAVs.push( ISimpleAudioVolume )
                }
            }
        }
        ObjRelease(IAudioSessionControl2)
    }
    ObjRelease(IAudioSessionEnumerator)
    
    if incr
    {
        if ( maxlevel = 0.0 ) or ( maxlevel = 1.0 )
        {
            for i, t in targets
                DllCall( NumGet( NumGet( ISAVs[t]+0 ) + 3*A_PtrSize ), "UPtr", ISAVs[t], "Float", levels[t], "UPtr", 0, "UInt" )
        }
        else
        {
            VarSetCapacity( GUID, 16 )
            DllCall( "Ole32.dll\CLSIDFromString", "Str", "{5CDF2C82-841E-4546-9722-0CF74078229A}", "UPtr", &GUID)
            DllCall( NumGet( NumGet( IMMDevice+0 ) + 3*A_PtrSize ), "UPtr", IMMDevice, "UPtr", &GUID, "UInt", 7, "UPtr", 0, "UPtrP", IEndpointVolume, "UInt" )

            DllCall( NumGet( NumGet( IEndpointVolume+0 ) + 9*A_PtrSize ), "UPtr", IEndpointVolume, "FloatP", MasterLevel ) ; Get master level
            DllCall( NumGet( NumGet( IEndpointVolume+0 ) + 7*A_PtrSize ), "UPtr", IEndpointVolume, "Float", MasterLevel * maxlevel, "UPtr", 0, "UInt" ) ; Set master level
            ObjRelease( IEndpointVolume )
            
            for i, ISimpleAudioVolume in ISAVs
                DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 3*A_PtrSize ), "UPtr", ISimpleAudioVolume, "Float", min( 1.0, levels[i] / maxlevel ) , "UPtr", 0, "UInt" )  ; Set volume
        }        
    }
    else
    {
        for i, ISimpleAudioVolume in ISAVs
            DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 5*A_PtrSize ), "UPtr", ISimpleAudioVolume, "Int", !maxlevel, "UPtr", 0, "UInt" )  ; Toggle mute status
    }
    ObjRelease( IMMDevice )
    for i, ISimpleAudioVolume in ISAVs
        ObjRelease(ISimpleAudioVolume)
}



;created by submeg 05/06/2022
;modified the code I found here by Bunker D - https://www.autohotkey.com/boards/viewtopic.php?style=19&p=433963#p433963
FindAppVolume(appName)
{
    if !appName
    {
        WinGet, activePID, ID, A
        WinGet, activeName, ProcessName, ahk_id %activePID%
        appName := activeName        
    }
    
    IMMDeviceEnumerator := ComObjCreate( "{BCDE0395-E52F-467C-8E3D-C4579291692E}", "{A95664D2-9614-4F35-A746-DE8DB63617E6}" )
    DllCall( NumGet( NumGet( IMMDeviceEnumerator+0 ) + 4*A_PtrSize ), "UPtr", IMMDeviceEnumerator, "UInt", 0, "UInt", 1, "UPtrP", IMMDevice, "UInt" )
    ObjRelease(IMMDeviceEnumerator)

    VarSetCapacity( GUID, 16 )
    DllCall( "Ole32.dll\CLSIDFromString", "Str", "{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}", "UPtr", &GUID)
    DllCall( NumGet( NumGet( IMMDevice+0 ) + 3*A_PtrSize ), "UPtr", IMMDevice, "UPtr", &GUID, "UInt", 23, "UPtr", 0, "UPtrP", IAudioSessionManager2, "UInt" )
    ObjRelease( IMMDevice )

    DllCall( NumGet( NumGet( IAudioSessionManager2+0 ) + 5*A_PtrSize ), "UPtr", IAudioSessionManager2, "UPtrP", IAudioSessionEnumerator, "UInt" )
    ObjRelease( IAudioSessionManager2 )

    DllCall( NumGet( NumGet( IAudioSessionEnumerator+0 ) + 3*A_PtrSize ), "UPtr", IAudioSessionEnumerator, "UIntP", SessionCount, "UInt" )
    Loop % SessionCount
    {
        DllCall( NumGet( NumGet( IAudioSessionEnumerator+0 ) + 4*A_PtrSize ), "UPtr", IAudioSessionEnumerator, "Int", A_Index-1, "UPtrP", IAudioSessionControl, "UInt" )
        IAudioSessionControl2 := ComObjQuery( IAudioSessionControl, "{BFB7FF88-7239-4FC9-8FA2-07C950BE9C6D}" )
        ObjRelease( IAudioSessionControl )

        DllCall( NumGet( NumGet( IAudioSessionControl2+0 ) + 14*A_PtrSize ), "UPtr", IAudioSessionControl2, "UIntP", PID, "UInt" )
        
        PHandle := DllCall( "OpenProcess", "uint", 0x0010|0x0400, "Int", false, "UInt", PID )
        if !( ErrorLevel or PHandle = 0 )
        {
            name_size = 1023
            VarSetCapacity( PName, name_size )
            DllCall( "psapi.dll\GetModuleFileNameEx" . ( A_IsUnicode ? "W" : "A" ), "uint", PHandle, "uint", 0, "str", PName, "uint", name_size )
            DllCall( "CloseHandle", PHandle )
            SplitPath PName, PName
            if ( PName = appName )
            {
                ISimpleAudioVolume := ComObjQuery(IAudioSessionControl2, "{87CE5498-68D6-44E5-9215-6DA47EF883D8}")
                DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 4*A_PtrSize ), "UPtr", ISimpleAudioVolume, "FloatP", PrevVolume, "UInt" )
                ObjRelease(ISimpleAudioVolume)
            }
        }
        ObjRelease(IAudioSessionControl2)
    }
    ObjRelease(IAudioSessionEnumerator)

	Return PrevVolume

}


;Scripts called above that are currently commented out.

/*

;=================================================================================================
; AccessRights_EnableSeDebug() By Cyruz - https://autohotkey.com/boards/viewtopic.php?t=2039
;=================================================================================================
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: AccessRights_EnableSeDebug
; Description ..: Enable the SE_DEBUG_PRIVILEGE on the current script instance.
; AHK Version ..: AHK_L x32/64 Unicode
; Author .......: Cyruz - http://ciroprincipe.info
; License ......: WTFPL - http://www.wtfpl.net/txt/copying/
; Changelog ....: Feb. 5, 2014 - v0.1 - First version.
; ----------------------------------------------------------------------------------------------------------------------
AccessRights_EnableSeDebug() {
	hProc := DllCall( "OpenProcess", UInt,0x0400, Int,0, UInt,DllCall("GetCurrentProcessId"), "Ptr" )
	DllCall( "Advapi32.dll\OpenProcessToken", Ptr,hProc, UInt,0x0020|0x0008, PtrP,hToken )

	VarSetCapacity(LUID, 8, 0)
	DllCall( "Advapi32.dll\LookupPrivilegeValue", Ptr,0, Str,"SeDebugPrivilege", Ptr,&LUID )

	VarSetCapacity( TOKPRIV, 16, 0   )					      ; TOKEN_PRIVILEGES structure: http://goo.gl/AGXeAp.
	NumPut( 1, &TOKPRIV, 0,   "UInt" )                        ; TOKEN_PRIVILEGES > PrivilegeCount.
	NumPut( NumGet( &LUID, 0, "UInt" ), &TOKPRIV, 4, "UInt" ) ; TOKEN_PRIVILEGES > LUID_AND_ATTRIBUTES > LUID > LoPart.
	NumPut( NumGet( &LUID, 4, "UInt" ), &TOKPRIV, 8, "UInt" ) ; TOKEN_PRIVILEGES > LUID_AND_ATTRIBUTES > LUID > HiPart.
	NumPut( 2, &TOKPRIV, 12,  "UInt" )                        ; TOKEN_PRIVILEGES > LUID_AND_ATTRIBUTES > Attributes.
														      ; SE_PRIVILEGE_ENABLED = 2.

	DllCall( "Advapi32.dll\AdjustTokenPrivileges", Ptr,hToken, Int,0, Ptr,&TOKPRIV, UInt,0, Ptr,0, Ptr,0 )
    DllCall( "CloseHandle", Ptr,hToken )
    DllCall( "CloseHandle", Ptr,hProc  )
}

; ==================================================
; FileGetInfo() By Lexikos - https://autohotkey.com/boards/viewtopic.php?t=4282
;===================================================

FileGetInfo( lptstrFilename) {
	List := "Comments InternalName ProductName CompanyName LegalCopyright ProductVersion"
		. " FileDescription LegalTrademarks PrivateBuild FileVersion OriginalFilename SpecialBuild"
	dwLen := DllCall("Version.dll\GetFileVersionInfoSize", "Str", lptstrFilename, "Ptr", 0)
	dwLen := VarSetCapacity( lpData, dwLen + A_PtrSize)
	DllCall("Version.dll\GetFileVersionInfo", "Str", lptstrFilename, "UInt", 0, "UInt", dwLen, "Ptr", &lpData) 
	DllCall("Version.dll\VerQueryValue", "Ptr", &lpData, "Str", "\VarFileInfo\Translation", "PtrP", lplpBuffer, "PtrP", puLen )
	sLangCP := Format("{:04X}{:04X}", NumGet(lplpBuffer+0, "UShort"), NumGet(lplpBuffer+2, "UShort"))
	i := {}
	Loop, Parse, % List, %A_Space%
		DllCall("Version.dll\VerQueryValue", "Ptr", &lpData, "Str", "\StringFileInfo\" sLangCp "\" A_LoopField, "PtrP", lplpBuffer, "PtrP", puLen )
		? i[A_LoopField] := StrGet(lplpBuffer, puLen) : ""
	return i
}

Return

*/

____________________________________
Check out my site, submeg.com
Connect with me on LinkedIn
Courses on AutoHotkey :ugeek:
User avatar
submeg
Posts: 335
Joined: 14 Apr 2017, 20:39
Contact:

Re: Control the volume of all programs and current program - code cleansing

05 Jun 2022, 17:00

I just tried this on my PC at work, and only the volume setting of all the programs to a particular level is working - when I try to cycle through the different volume levels on a single program, it does nothing?

Ideas?
____________________________________
Check out my site, submeg.com
Connect with me on LinkedIn
Courses on AutoHotkey :ugeek:
User avatar
JoeWinograd
Posts: 2214
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Control the volume of all programs and current program - code cleansing

05 Jun 2022, 17:41

submeg wrote:I came across the following threads
In addition to those two threads, here's another one in which you and I participated:
viewtopic.php?f=76&t=93159
submeg wrote:when I try to cycle through the different volume levels on a single program, it does nothing?
Ideas?
It may simply be one of those programs where volume control doesn't work. Note my comment at thread above:
I've done a fair amount of testing with this. Quick summary...it works with some apps, but not others. When it works, it is perfect...changes the volume only in that app...does not affect the Master volume.

It works great in Firefox...doesn't matter what the active tab is. I tried numerous Chromium-based browsers...Brave, Chrome, Edge, Opera, Vivaldi...does not work in any of them. It works in Amazon Music, Total Recorder, and VLC (although Amazon Music resets the volume to 50 when it is auto-playing the next track). It does not work in Skype. It does not work in the W10 built-in apps that I tried...Groove Music, Movies & TV, Voice Recorder.
Regards, Joe
User avatar
submeg
Posts: 335
Joined: 14 Apr 2017, 20:39
Contact:

Re: Control the volume of all programs and current program - code cleansing

06 Jun 2022, 07:21

JoeWinograd wrote:
05 Jun 2022, 17:41
submeg wrote:I came across the following threads
In addition to those two threads, here's another one in which you and I participated:
viewtopic.php?f=76&t=93159
submeg wrote:when I try to cycle through the different volume levels on a single program, it does nothing?
Ideas?
It may simply be one of those programs where volume control doesn't work. Note my comment at thread above:
I've done a fair amount of testing with this. Quick summary...it works with some apps, but not others. When it works, it is perfect...changes the volume only in that app...does not affect the Master volume.

It works great in Firefox...doesn't matter what the active tab is. I tried numerous Chromium-based browsers...Brave, Chrome, Edge, Opera, Vivaldi...does not work in any of them. It works in Amazon Music, Total Recorder, and VLC (although Amazon Music resets the volume to 50 when it is auto-playing the next track). It does not work in Skype. It does not work in the W10 built-in apps that I tried...Groove Music, Movies & TV, Voice Recorder.
Regards, Joe
Hey @JoeWinograd , I did indeed complete forget about that thread! Wow, talk about short term memory!

So looking at that thread, I have added in the #Include D:\AutoHotkey\Lib\VA.ahk, and then changed my VolumeCycle() function to:

Code: Select all


VolumeCycle()
{
	
	;First, find the active program (name and PID).
	DetectHiddenWindows on
	
    WinGet, PID, PID, A
    IfWinExist ahk_pid %PID%
    {
        WinGet, ProcessEXE, ProcessName
		WinGet, ProcessPID, PID
    }
	
	;msgbox % "PID is: " ProcessPID "`rEXE is: " ProcessEXE
	
	;Find the volume level of the current program.
	CurrentVolLevel := FindAppVolume(ProcessEXE)
	;msgbox % "Current Volume level of " ProcessEXE " is: " CurrentVolLevel " of the Master volume level"

	If (CurrentVolLevel < 1.0)
	{
		
		;SetAppVolume(ProcessPID, 100)
		setWindowVol(,"+10")
		
		CurrentVolLevel := FindAppVolume(ProcessEXE)
		
		CurrentVolLevel := Floor(CurrentVolLevel * 100)
		
		msg:= ProcessEXE . " set to " CurrentVolLevel "% of master volume."
		
		ToolTip, %msg%
		
		SetTimer, RemoveToolTip, -700
		
		msg := ""
		
	}
	else
	{
		
		setWindowVol(,"-100")
		
		msg:= ProcessEXE . " muted."
		
		ToolTip, %msg%
		
		SetTimer, RemoveToolTip, -700
		
		msg := ""
		
	}
	
}
Return

Works perfectly; checked on Spotify and a browser (firefox). Thank you for this, I have all of the code in one place, will test at work tomorrow and see how it goes!
____________________________________
Check out my site, submeg.com
Connect with me on LinkedIn
Courses on AutoHotkey :ugeek:
User avatar
JoeWinograd
Posts: 2214
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Control the volume of all programs and current program - code cleansing

06 Jun 2022, 07:34

Hi @submeg,
Glad to hear that it works perfectly in Spotify (which I don't use) and that, like me, you found it to work in Firefox. The problem may be when you test it at work tomorrow...for some apps it works, for some it doesn't...will all depend on the apps at work. If the browser at work is Chromium-based, my experience is that it won't work. Let me know how it goes. Regards, Joe
User avatar
submeg
Posts: 335
Joined: 14 Apr 2017, 20:39
Contact:

Re: Control the volume of all programs and current program - code cleansing

06 Jun 2022, 19:35

JoeWinograd wrote:
06 Jun 2022, 07:34
Hi @submeg,
Glad to hear that it works perfectly in Spotify (which I don't use) and that, like me, you found it to work in Firefox. The problem may be when you test it at work tomorrow...for some apps it works, for some it doesn't...will all depend on the apps at work. If the browser at work is Chromium-based, my experience is that it won't work. Let me know how it goes. Regards, Joe
Hi @JoeWinograd, thanks for the heads up! I just tested and found that yes, it works in Firefox, Outlook, Razer Synapse. It doesn't work on Chrome, nor Microsoft Edge!

What's the deal with that?!

Please see below my full code; I have cleaned it up and any functions that are currently not called are located in the commented out section at the end. If there is more than can be simplified here, that would be fantastic!

Note: It requires Lexikos' VA.ahk script to run.

Code: Select all


#NoEnv
#SingleInstance Force
;SetBatchLines -1

ProcessPID := ""		;The ID of the current program

;Cycling through all the active processes, see here - https://www.autohotkey.com/boards/viewtopic.php?p=180272#p180272
;Changing the volumes of programs - https://www.autohotkey.com/boards/viewtopic.php?p=210533&sid=7424e9efc9c2600470b2492266161dbb#p210533
	
OUT_LIST := ""						;The variable for storing the list of open processes.
COUNT_NO_PATHS := 0					;The count of open processes.
;Clipboard := OUT_LIST 				;used for placing all process IDs into the clipboard so it can sent to an application.

;required by the functions below. Uploaded by Lexikos - https://autohotkey.com/board/topic/21984-vista-audio-control-functions/
#Include C:\Users\USER\AutoHotkey\Lib\VA.ahk

;https://www.autohotkey.com/boards/viewtopic.php?t=2039
;AccessRights_EnableSeDebug()		;Enables the SE_DEBUG_PRIVILEGE for the current process. Maybe it can be useful to resolve some "access denied" stuff when dealing with processes.
;Commented out this as works without. 

;=======================================
;---------------------------------------
;Hotkeys
;---------------------------------------

;---------------------------------------

;Show the Windows volume mixer

F12::

run, C:\Windows\System32\SndVol.exe		;Show the volume mixer

Return

;---------------------------------------

;---------------------------------------

;Mute all open programs
;Note: this may take a moment, please wait until you see the tooltip appear.

F1::

SetAllVolume(0)

msg:= "All applications muted."
	
ToolTip, %msg%

SetTimer, RemoveToolTip, -700

msg := ""

Return

;---------------------------------------

;---------------------------------------

;Set volume level to 25% for all open programs
;Note: this may take a moment, please wait until you see the tooltip appear.

F2::

SetAllVolume(25)

msg:= "All applications set to 25% of master volume."
	
ToolTip, %msg%

SetTimer, RemoveToolTip, -700

msg := ""

Return

;---------------------------------------

;---------------------------------------

;Set volume level to 50% for all open programs
;Note: this may take a moment, please wait until you see the tooltip appear.


F3::

SetAllVolume(50)

msg:= "All applications set to 50% of master volume."
	
ToolTip, %msg%

SetTimer, RemoveToolTip, -700

msg := ""

Return

;---------------------------------------

;---------------------------------------

;Set volume level to 25% for all open programs
;Note: this may take a moment, please wait until you see the tooltip appear.

F4::

SetAllVolume_100()

msg:= "All applications set to 100% of master volume."
	
ToolTip, %msg%

SetTimer, RemoveToolTip, -700

msg := ""

Return

;---------------------------------------

;---------------------------------------

;Cycle through the volume levels for the active program.

F5::

VolumeCycle()

Return

;---------------------------------------
;=======================================

;=======================================

;---------------------------------------

;FUNCTIONS
;This is to reset any tool tip
RemoveToolTip:						;;Tooltip reset
ToolTip

Return

;---------------------------------------

;---------------------------------------

SetAllVolume(VolValue)
{

	for i, v in WTSEnumerateProcessesEx()
	{
		
		SetAppVolume(v.ProsessID, VolValue)
		
		;FullEXEPath := GetModuleFileNameEx( v.ProsessID )
		;OUT_LIST := OUT_LIST . "Name: " . v.ProcessName . "`nPath: " . FullEXEPath . "`nLegal: " .  FileGetInfo( FullEXEPath ).LegalCopyright . "`n`n"
		
	}

}
Return

;---------------------------------------

;---------------------------------------

SetAllVolume_100()
{
	
	MsgBox, 4,, WARNING! `r`rThis will set ALL volume to 100. Would you like to continue? (press Yes or No)
	IfMsgBox Yes
		for i, v in WTSEnumerateProcessesEx()
		{
			FullEXEPath := GetModuleFileNameEx( v.ProsessID )
			SetAppVolume(v.ProsessID, 100)

			;OUT_LIST := OUT_LIST . "Name: " . v.ProcessName . "`nPath: " . FullEXEPath . "`nLegal: " .  FileGetInfo( FullEXEPath ).LegalCopyright . "`n`n"
			
		}

}
Return

;---------------------------------------

;---------------------------------------

VolumeCycle()
{
	
	;First, find the active program (name and PID).
	DetectHiddenWindows on
	
    WinGet, PID, PID, A
    IfWinExist ahk_pid %PID%
    {
        WinGet, ProcessEXE, ProcessName
		WinGet, ProcessPID, PID
    }
	
	;msgbox % "PID is: " ProcessPID "`rEXE is: " ProcessEXE
	
	;Find the volume level of the current program.
	CurrentVolLevel := FindAppVolume(ProcessEXE)
	;msgbox % "Current Volume level of " ProcessEXE " is: " CurrentVolLevel " of the Master volume level"

	If (CurrentVolLevel < 1.0)
	{
		
		;SetAppVolume(ProcessPID, 100)
		setWindowVol(,"+10")
		
		CurrentVolLevel := FindAppVolume(ProcessEXE)
		
		CurrentVolLevel := Floor(CurrentVolLevel * 100)
		
		msg:= ProcessEXE . " set to " CurrentVolLevel "% of master volume."
		
		ToolTip, %msg%
		
		SetTimer, RemoveToolTip, -700
		
		msg := ""
		
	}
	else
	{
		
		setWindowVol(,"-100")
		
		msg:= ProcessEXE . " muted."
		
		ToolTip, %msg%
		
		SetTimer, RemoveToolTip, -700
		
		msg := ""
		
	}
	
}
Return
 
;---------------------------------------

;---------------------------------------
;https://www.autohotkey.com/boards/viewtopic.php?p=412459#p412459

setWindowVol(winName:="a",vol:="n"){
	if (vol=="n")
		return
	winGet,winPid,PID,% winName
	if !(volume:=GetVolumeObject(winPid))
		return
	vsign:=subStr(vol,1,1)
	if (vsign="+"||vsign="-") {
		vol:=subStr(vol,2),vol/=100
		
		VA_ISimpleAudioVolume_GetMasterVolume(volume,cvol)
		if (vsign="+")
			vol:=cvol+vol>1?1:cvol+vol
		else if (vsign="-")
			vol:=cvol-vol<0?0:cvol-vol
	} else
		vol/=100
	VA_ISimpleAudioVolume_SetMasterVolume(volume,vol),objRelease(volume)
}

;---------------------------------------

; ==============================================================
; WTSEnumerateProcessesEx() By JNIZM - https://autohotkey.com/boards/viewtopic.php?t=19323
;==============================================================

Return
WTSEnumerateProcessesEx()
{
    static hWTSAPI := DllCall("LoadLibrary", "str", "wtsapi32.dll", "ptr")

    if !(DllCall("wtsapi32\WTSEnumerateProcessesEx", "ptr", 0, "uint*", 0, "uint", -2, "ptr*", buf, "uint*", TTL))
        throw Exception("WTSEnumerateProcessesEx failed", -1)
    
	addr := buf 
	WTS_PROCESS_INFO := []
    
	loop % TTL
    {
        WTS_PROCESS_INFO[A_Index, "SessionID"]   := NumGet(addr+0, "uint")
        WTS_PROCESS_INFO[A_Index, "ProsessID"]   := NumGet(addr+4, "uint")
        WTS_PROCESS_INFO[A_Index, "ProcessName"] := StrGet(NumGet(addr+8, "ptr"))
        WTS_PROCESS_INFO[A_Index, "UserSID"]     := NumGet(addr+8+A_PtrSize, "ptr")
        addr += 8 + (A_PtrSize * 2)
    }
    if !(DllCall("wtsapi32\WTSFreeMemoryEx", "int", 0, "ptr", buf, "uint", TTL))
        throw Exception("WTSFreeMemoryEx failed", -1)
    return WTS_PROCESS_INFO
}

Return


; =================================================================================================
; GetModuleFileNameEx() By Shimanov as cited by SKAN - https://autohotkey.com/board/topic/41197-getting-a-full-executable-path-from-a-running-process/
; Modified to use GetModuleFileNameExW if A_IsUnicode - By Gio - 03-11-17
;=================================================================================================

GetModuleFileNameEx( p_pid ) ; by shimanov -  www.autohotkey.com/forum/viewtopic.php?t=9000
{
   if A_OSVersion in WIN_95,WIN_98,WIN_ME
   {
      MsgBox, This Windows version (%A_OSVersion%) is not supported.
      return
   }
   h_process := DllCall( "OpenProcess", "uint", 0x10|0x400, "int", false, "uint", p_pid )
   if ( ErrorLevel or h_process = 0 )
      return
   name_size = 255
   VarSetCapacity( name, name_size )
   If A_IsUnicode
      result := DllCall( "psapi.dll\GetModuleFileNameExW", "uint", h_process, "uint", 0, "str" , name, "uint", name_size )
    Else
      result := DllCall( "psapi.dll\GetModuleFileNameExA", "uint", h_process, "uint", 0, "str" , name, "uint", name_size )
   DllCall( "CloseHandle", h_process )
   return, name
}



SetAppVolume(PID, MasterVolume)    ; WIN_V+
{
    MasterVolume := MasterVolume > 100 ? 100 : MasterVolume < 0 ? 0 : MasterVolume

    IMMDeviceEnumerator := ComObjCreate("{BCDE0395-E52F-467C-8E3D-C4579291692E}", "{A95664D2-9614-4F35-A746-DE8DB63617E6}")
    DllCall(NumGet(NumGet(IMMDeviceEnumerator+0)+4*A_PtrSize), "UPtr", IMMDeviceEnumerator, "UInt", 0, "UInt", 1, "UPtrP", IMMDevice, "UInt")
    ObjRelease(IMMDeviceEnumerator)

    VarSetCapacity(GUID, 16)
    DllCall("Ole32.dll\CLSIDFromString", "Str", "{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}", "UPtr", &GUID)
    DllCall(NumGet(NumGet(IMMDevice+0)+3*A_PtrSize), "UPtr", IMMDevice, "UPtr", &GUID, "UInt", 23, "UPtr", 0, "UPtrP", IAudioSessionManager2, "UInt")
    ObjRelease(IMMDevice)

    DllCall(NumGet(NumGet(IAudioSessionManager2+0)+5*A_PtrSize), "UPtr", IAudioSessionManager2, "UPtrP", IAudioSessionEnumerator, "UInt")
    ObjRelease(IAudioSessionManager2)

    DllCall(NumGet(NumGet(IAudioSessionEnumerator+0)+3*A_PtrSize), "UPtr", IAudioSessionEnumerator, "UIntP", SessionCount, "UInt")
    Loop % SessionCount
    {
        DllCall(NumGet(NumGet(IAudioSessionEnumerator+0)+4*A_PtrSize), "UPtr", IAudioSessionEnumerator, "Int", A_Index-1, "UPtrP", IAudioSessionControl, "UInt")
        IAudioSessionControl2 := ComObjQuery(IAudioSessionControl, "{BFB7FF88-7239-4FC9-8FA2-07C950BE9C6D}")
        ObjRelease(IAudioSessionControl)

        DllCall(NumGet(NumGet(IAudioSessionControl2+0)+14*A_PtrSize), "UPtr", IAudioSessionControl2, "UIntP", currentProcessId, "UInt")
        If (PID == currentProcessId)
        {
            ISimpleAudioVolume := ComObjQuery(IAudioSessionControl2, "{87CE5498-68D6-44E5-9215-6DA47EF883D8}")
            DllCall(NumGet(NumGet(ISimpleAudioVolume+0)+3*A_PtrSize), "UPtr", ISimpleAudioVolume, "Float", MasterVolume/100.0, "UPtr", 0, "UInt")
            ObjRelease(ISimpleAudioVolume)
        }
        ObjRelease(IAudioSessionControl2)
    }
    ObjRelease(IAudioSessionEnumerator)
}






;created by submeg 05/06/2022
;modified the code I found here by Bunker D - https://www.autohotkey.com/boards/viewtopic.php?style=19&p=433963#p433963
FindAppVolume(appName)
{
    if !appName
    {
        WinGet, activePID, ID, A
        WinGet, activeName, ProcessName, ahk_id %activePID%
        appName := activeName        
    }
    
    IMMDeviceEnumerator := ComObjCreate( "{BCDE0395-E52F-467C-8E3D-C4579291692E}", "{A95664D2-9614-4F35-A746-DE8DB63617E6}" )
    DllCall( NumGet( NumGet( IMMDeviceEnumerator+0 ) + 4*A_PtrSize ), "UPtr", IMMDeviceEnumerator, "UInt", 0, "UInt", 1, "UPtrP", IMMDevice, "UInt" )
    ObjRelease(IMMDeviceEnumerator)

    VarSetCapacity( GUID, 16 )
    DllCall( "Ole32.dll\CLSIDFromString", "Str", "{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}", "UPtr", &GUID)
    DllCall( NumGet( NumGet( IMMDevice+0 ) + 3*A_PtrSize ), "UPtr", IMMDevice, "UPtr", &GUID, "UInt", 23, "UPtr", 0, "UPtrP", IAudioSessionManager2, "UInt" )
    ObjRelease( IMMDevice )

    DllCall( NumGet( NumGet( IAudioSessionManager2+0 ) + 5*A_PtrSize ), "UPtr", IAudioSessionManager2, "UPtrP", IAudioSessionEnumerator, "UInt" )
    ObjRelease( IAudioSessionManager2 )

    DllCall( NumGet( NumGet( IAudioSessionEnumerator+0 ) + 3*A_PtrSize ), "UPtr", IAudioSessionEnumerator, "UIntP", SessionCount, "UInt" )
    Loop % SessionCount
    {
        DllCall( NumGet( NumGet( IAudioSessionEnumerator+0 ) + 4*A_PtrSize ), "UPtr", IAudioSessionEnumerator, "Int", A_Index-1, "UPtrP", IAudioSessionControl, "UInt" )
        IAudioSessionControl2 := ComObjQuery( IAudioSessionControl, "{BFB7FF88-7239-4FC9-8FA2-07C950BE9C6D}" )
        ObjRelease( IAudioSessionControl )

        DllCall( NumGet( NumGet( IAudioSessionControl2+0 ) + 14*A_PtrSize ), "UPtr", IAudioSessionControl2, "UIntP", PID, "UInt" )
        
        PHandle := DllCall( "OpenProcess", "uint", 0x0010|0x0400, "Int", false, "UInt", PID )
        if !( ErrorLevel or PHandle = 0 )
        {
            name_size = 1023
            VarSetCapacity( PName, name_size )
            DllCall( "psapi.dll\GetModuleFileNameEx" . ( A_IsUnicode ? "W" : "A" ), "uint", PHandle, "uint", 0, "str", PName, "uint", name_size )
            DllCall( "CloseHandle", PHandle )
            SplitPath PName, PName
            if ( PName = appName )
            {
                ISimpleAudioVolume := ComObjQuery(IAudioSessionControl2, "{87CE5498-68D6-44E5-9215-6DA47EF883D8}")
                DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 4*A_PtrSize ), "UPtr", ISimpleAudioVolume, "FloatP", PrevVolume, "UInt" )
                ObjRelease(ISimpleAudioVolume)
            }
        }
        ObjRelease(IAudioSessionControl2)
    }
    ObjRelease(IAudioSessionEnumerator)

	Return PrevVolume

}



/*

;Scripts called above that are currently commented out.

;---------------------------------------

;=================================================================================================
; AccessRights_EnableSeDebug() By Cyruz - https://autohotkey.com/boards/viewtopic.php?t=2039
;=================================================================================================
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: AccessRights_EnableSeDebug
; Description ..: Enable the SE_DEBUG_PRIVILEGE on the current script instance.
; AHK Version ..: AHK_L x32/64 Unicode
; Author .......: Cyruz - http://ciroprincipe.info
; License ......: WTFPL - http://www.wtfpl.net/txt/copying/
; Changelog ....: Feb. 5, 2014 - v0.1 - First version.
; ----------------------------------------------------------------------------------------------------------------------
AccessRights_EnableSeDebug() {
	hProc := DllCall( "OpenProcess", UInt,0x0400, Int,0, UInt,DllCall("GetCurrentProcessId"), "Ptr" )
	DllCall( "Advapi32.dll\OpenProcessToken", Ptr,hProc, UInt,0x0020|0x0008, PtrP,hToken )

	VarSetCapacity(LUID, 8, 0)
	DllCall( "Advapi32.dll\LookupPrivilegeValue", Ptr,0, Str,"SeDebugPrivilege", Ptr,&LUID )

	VarSetCapacity( TOKPRIV, 16, 0   )					      ; TOKEN_PRIVILEGES structure: http://goo.gl/AGXeAp.
	NumPut( 1, &TOKPRIV, 0,   "UInt" )                        ; TOKEN_PRIVILEGES > PrivilegeCount.
	NumPut( NumGet( &LUID, 0, "UInt" ), &TOKPRIV, 4, "UInt" ) ; TOKEN_PRIVILEGES > LUID_AND_ATTRIBUTES > LUID > LoPart.
	NumPut( NumGet( &LUID, 4, "UInt" ), &TOKPRIV, 8, "UInt" ) ; TOKEN_PRIVILEGES > LUID_AND_ATTRIBUTES > LUID > HiPart.
	NumPut( 2, &TOKPRIV, 12,  "UInt" )                        ; TOKEN_PRIVILEGES > LUID_AND_ATTRIBUTES > Attributes.
														      ; SE_PRIVILEGE_ENABLED = 2.

	DllCall( "Advapi32.dll\AdjustTokenPrivileges", Ptr,hToken, Int,0, Ptr,&TOKPRIV, UInt,0, Ptr,0, Ptr,0 )
    DllCall( "CloseHandle", Ptr,hToken )
    DllCall( "CloseHandle", Ptr,hProc  )
}

;---------------------------------------

;---------------------------------------

; ==================================================
; FileGetInfo() By Lexikos - https://autohotkey.com/boards/viewtopic.php?t=4282
;===================================================

FileGetInfo( lptstrFilename) {
	List := "Comments InternalName ProductName CompanyName LegalCopyright ProductVersion"
		. " FileDescription LegalTrademarks PrivateBuild FileVersion OriginalFilename SpecialBuild"
	dwLen := DllCall("Version.dll\GetFileVersionInfoSize", "Str", lptstrFilename, "Ptr", 0)
	dwLen := VarSetCapacity( lpData, dwLen + A_PtrSize)
	DllCall("Version.dll\GetFileVersionInfo", "Str", lptstrFilename, "UInt", 0, "UInt", dwLen, "Ptr", &lpData) 
	DllCall("Version.dll\VerQueryValue", "Ptr", &lpData, "Str", "\VarFileInfo\Translation", "PtrP", lplpBuffer, "PtrP", puLen )
	sLangCP := Format("{:04X}{:04X}", NumGet(lplpBuffer+0, "UShort"), NumGet(lplpBuffer+2, "UShort"))
	i := {}
	Loop, Parse, % List, %A_Space%
		DllCall("Version.dll\VerQueryValue", "Ptr", &lpData, "Str", "\StringFileInfo\" sLangCp "\" A_LoopField, "PtrP", lplpBuffer, "PtrP", puLen )
		? i[A_LoopField] := StrGet(lplpBuffer, puLen) : ""
	return i
}

Return

;---------------------------------------

;---------------------------------------

;code by fubos - https://www.autohotkey.com/boards/viewtopic.php?p=322665&sid=bb731d1dbd1a61db0ca9c8a5f6b21a10#p322665
GetAppVolume(PID)
{
    Local MasterVolume := ""

    IMMDeviceEnumerator := ComObjCreate("{BCDE0395-E52F-467C-8E3D-C4579291692E}", "{A95664D2-9614-4F35-A746-DE8DB63617E6}")
    DllCall(NumGet(NumGet(IMMDeviceEnumerator+0)+4*A_PtrSize), "UPtr", IMMDeviceEnumerator, "UInt", 0, "UInt", 1, "UPtrP", IMMDevice, "UInt")
    ObjRelease(IMMDeviceEnumerator)

    VarSetCapacity(GUID, 16)
    DllCall("Ole32.dll\CLSIDFromString", "Str", "{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}", "UPtr", &GUID)
    DllCall(NumGet(NumGet(IMMDevice+0)+3*A_PtrSize), "UPtr", IMMDevice, "UPtr", &GUID, "UInt", 23, "UPtr", 0, "UPtrP", IAudioSessionManager2, "UInt")
    ObjRelease(IMMDevice)

    DllCall(NumGet(NumGet(IAudioSessionManager2+0)+5*A_PtrSize), "UPtr", IAudioSessionManager2, "UPtrP", IAudioSessionEnumerator, "UInt")
    ObjRelease(IAudioSessionManager2)

    DllCall(NumGet(NumGet(IAudioSessionEnumerator+0)+3*A_PtrSize), "UPtr", IAudioSessionEnumerator, "UIntP", SessionCount, "UInt")
    Loop % SessionCount
    {
        DllCall(NumGet(NumGet(IAudioSessionEnumerator+0)+4*A_PtrSize), "UPtr", IAudioSessionEnumerator, "Int", A_Index-1, "UPtrP", IAudioSessionControl, "UInt")
        IAudioSessionControl2 := ComObjQuery(IAudioSessionControl, "{BFB7FF88-7239-4FC9-8FA2-07C950BE9C6D}")
        ObjRelease(IAudioSessionControl)

        DllCall(NumGet(NumGet(IAudioSessionControl2+0)+14*A_PtrSize), "UPtr", IAudioSessionControl2, "UIntP", currentProcessId, "UInt")
        If (PID == currentProcessId)
        {
            ISimpleAudioVolume := ComObjQuery(IAudioSessionControl2, "{87CE5498-68D6-44E5-9215-6DA47EF883D8}")
            DllCall(NumGet(NumGet(ISimpleAudioVolume+0)+4*A_PtrSize), "UPtr", ISimpleAudioVolume, "FloatP", MasterVolume, "UInt")
            ObjRelease(ISimpleAudioVolume)
        }
        ObjRelease(IAudioSessionControl2)
    }
    ObjRelease(IAudioSessionEnumerator)

    Return Round(MasterVolume * 100)
}

;---------------------------------------

;---------------------------------------

;code by Bunker D - https://www.autohotkey.com/boards/viewtopic.php?style=19&p=433963#p433963
ShiftAppVolume( appName, incr )
{
    if !appName
    {
        WinGet, activePID, ID, A
        WinGet, activeName, ProcessName, ahk_id %activePID%
        appName := activeName        
    }
    
    IMMDeviceEnumerator := ComObjCreate( "{BCDE0395-E52F-467C-8E3D-C4579291692E}", "{A95664D2-9614-4F35-A746-DE8DB63617E6}" )
    DllCall( NumGet( NumGet( IMMDeviceEnumerator+0 ) + 4*A_PtrSize ), "UPtr", IMMDeviceEnumerator, "UInt", 0, "UInt", 1, "UPtrP", IMMDevice, "UInt" )
    ObjRelease(IMMDeviceEnumerator)

    VarSetCapacity( GUID, 16 )
    DllCall( "Ole32.dll\CLSIDFromString", "Str", "{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}", "UPtr", &GUID)
    DllCall( NumGet( NumGet( IMMDevice+0 ) + 3*A_PtrSize ), "UPtr", IMMDevice, "UPtr", &GUID, "UInt", 23, "UPtr", 0, "UPtrP", IAudioSessionManager2, "UInt" )

    DllCall( NumGet( NumGet( IAudioSessionManager2+0 ) + 5*A_PtrSize ), "UPtr", IAudioSessionManager2, "UPtrP", IAudioSessionEnumerator, "UInt" )
    ObjRelease( IAudioSessionManager2 )
    
    DllCall( NumGet( NumGet( IAudioSessionEnumerator+0 ) + 3*A_PtrSize ), "UPtr", IAudioSessionEnumerator, "UIntP", SessionCount, "UInt" )
    levels := []
    maxlevel := 0
    targets := []
    t := 0
    ISAVs := []
    Loop % SessionCount
    {
        DllCall( NumGet( NumGet( IAudioSessionEnumerator+0 ) + 4*A_PtrSize ), "UPtr", IAudioSessionEnumerator, "Int", A_Index-1, "UPtrP", IAudioSessionControl, "UInt" )
        IAudioSessionControl2 := ComObjQuery( IAudioSessionControl, "{BFB7FF88-7239-4FC9-8FA2-07C950BE9C6D}" )
        ObjRelease( IAudioSessionControl )
        
        DllCall( NumGet( NumGet( IAudioSessionControl2+0 ) + 14*A_PtrSize ), "UPtr", IAudioSessionControl2, "UIntP", PID, "UInt" )
        
        PHandle := DllCall( "OpenProcess", "uint", 0x0010|0x0400, "Int", false, "UInt", PID )
        if !( ErrorLevel or PHandle = 0 )
        {
            name_size = 1023
            VarSetCapacity( PName, name_size )
            DllCall( "psapi.dll\GetModuleFileNameEx" . ( A_IsUnicode ? "W" : "A" ), "UInt", PHandle, "UInt", 0, "Str", PName, "UInt", name_size )
            DllCall( "CloseHandle", PHandle )
            SplitPath PName, PName
            
            if incr
            {
                t += 1
                
                ISimpleAudioVolume := ComObjQuery(IAudioSessionControl2, "{87CE5498-68D6-44E5-9215-6DA47EF883D8}")
                DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 4*A_PtrSize ), "UPtr", ISimpleAudioVolume, "FloatP", level, "UInt" )  ; Get volume
                
                if ( PName = appName )
                {
                    level += incr
                    targets.push( t )
                    DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 5*A_PtrSize ), "UPtr", ISimpleAudioVolume, "Int", 0, "UPtr", 0, "UInt" )  ; Unmute
                }
                ISAVs.push( ISimpleAudioVolume )
                levels.push( level )
                maxlevel := max( maxlevel, level )
            }
            else
            {
                if ( PName = appName )
                {
                    ISimpleAudioVolume := ComObjQuery(IAudioSessionControl2, "{87CE5498-68D6-44E5-9215-6DA47EF883D8}")
                    DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 6*A_PtrSize ), "UPtr", ISimpleAudioVolume, "IntP", muted )  ; Get mute status
                    maxlevel := maxlevel or muted
                    ISAVs.push( ISimpleAudioVolume )
                }
            }
        }
        ObjRelease(IAudioSessionControl2)
    }
    ObjRelease(IAudioSessionEnumerator)
    
    if incr
    {
        if ( maxlevel = 0.0 ) or ( maxlevel = 1.0 )
        {
            for i, t in targets
                DllCall( NumGet( NumGet( ISAVs[t]+0 ) + 3*A_PtrSize ), "UPtr", ISAVs[t], "Float", levels[t], "UPtr", 0, "UInt" )
        }
        else
        {
            VarSetCapacity( GUID, 16 )
            DllCall( "Ole32.dll\CLSIDFromString", "Str", "{5CDF2C82-841E-4546-9722-0CF74078229A}", "UPtr", &GUID)
            DllCall( NumGet( NumGet( IMMDevice+0 ) + 3*A_PtrSize ), "UPtr", IMMDevice, "UPtr", &GUID, "UInt", 7, "UPtr", 0, "UPtrP", IEndpointVolume, "UInt" )

            DllCall( NumGet( NumGet( IEndpointVolume+0 ) + 9*A_PtrSize ), "UPtr", IEndpointVolume, "FloatP", MasterLevel ) ; Get master level
            DllCall( NumGet( NumGet( IEndpointVolume+0 ) + 7*A_PtrSize ), "UPtr", IEndpointVolume, "Float", MasterLevel * maxlevel, "UPtr", 0, "UInt" ) ; Set master level
            ObjRelease( IEndpointVolume )
            
            for i, ISimpleAudioVolume in ISAVs
                DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 3*A_PtrSize ), "UPtr", ISimpleAudioVolume, "Float", min( 1.0, levels[i] / maxlevel ) , "UPtr", 0, "UInt" )  ; Set volume
        }        
    }
    else
    {
        for i, ISimpleAudioVolume in ISAVs
            DllCall( NumGet( NumGet( ISimpleAudioVolume+0 ) + 5*A_PtrSize ), "UPtr", ISimpleAudioVolume, "Int", !maxlevel, "UPtr", 0, "UInt" )  ; Toggle mute status
    }
    ObjRelease( IMMDevice )
    for i, ISimpleAudioVolume in ISAVs
        ObjRelease(ISimpleAudioVolume)
}

;---------------------------------------

*/



____________________________________
Check out my site, submeg.com
Connect with me on LinkedIn
Courses on AutoHotkey :ugeek:
User avatar
JoeWinograd
Posts: 2214
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: Control the volume of all programs and current program - code cleansing

06 Jun 2022, 20:56

submeg wrote:What's the deal with that?!
I don't know. In case you missed my results earlier, I'll repeat them here:
I've done a fair amount of testing with this. Quick summary...it works with some apps, but not others. When it works, it is perfect...changes the volume only in that app...does not affect the Master volume.

It works great in Firefox...doesn't matter what the active tab is. I tried numerous Chromium-based browsers...Brave, Chrome, Edge, Opera, Vivaldi...does not work in any of them. It works in Amazon Music, Total Recorder, and VLC (although Amazon Music resets the volume to 50 when it is auto-playing the next track). It does not work in Skype. It does not work in the W10 built-in apps that I tried...Groove Music, Movies & TV, Voice Recorder.
I don't know why it works with some programs and not others. Regards, Joe

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Mateusz53, mikeyww, MrHue, mstrauss2021 and 313 guests