Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Get "Volume Mixer" Application Specific Mute Button State



  • Please log in to reply
26 replies to this topic
soulkobk
  • Members
  • 10 posts
  • Last active: Jan 09 2016 04:30 AM
  • Joined: 26 Dec 2014

@Masonjar13, thanks for the info... yeh, I cannot find anything that refers to the mute state apart from the tooltip/hover, but again, IDK how to extract the text for it.

 

@Linear Spoon. hmm, it seems I may have no choice to use VA.ahk and the script you provided, or parts of it. I'll check it out tomorrow and see if all is well.

 

Thanks again everyone for their input. :) Much appreciated.



soulkobk
  • Members
  • 10 posts
  • Last active: Jan 09 2016 04:30 AM
  • Joined: 26 Dec 2014

Well... I went to try and use the VA.ahk script, but it won't work. It says it needs the COM.ahk script also, but that won't work either.. it comes up with errors... so it's kind of useless.

 

I'm using "Version 1.0.48.05" which I downloaded from the front page... this is the latest one? *EDIT*, so I found and upgraded to Version v1.1.19.01.. and edited my script, it now works again. yet to test out the VA and COM scripts.

 

Can anyone give me a working VA.ahk and COM.ahk to get this thing to work? Thanks.\

 

So since the update to 1.1.19.01 and editing my script for it to function again, I have no idea where to start in extracting the mute information via VA. I see the VA_GetMute() function... but how do I use it? Like I said, I'm a newbie when it comes to AHK, so I'm learning as I go.

 

Thanks in advance.



Masonjar13
  • Members
  • 1517 posts
  • Last active:
  • Joined: 16 Sep 2012

You don't need COM.ahk, it's obsolete. Using the newest version of AHK (http://ahkscript.org/download), use the exact code Linear Spoon posted, then go from there.


OS: Windows 7 Ultimate / Windows 8.1 Pro | Editor: Notepad++


T_Lube
  • Members
  • 640 posts
  • Last active: Sep 09 2016 02:19 AM
  • Joined: 16 Oct 2014

alright since the control click works perfectly and you can't seem to get the mute state from the control, you could try something where when you start the script you set what the mute state is and when you go to click it the state reverses and that would be your variable. I have tried reading out of tooltips before and have found it not very workable. Just to make sure that you are not missing some thing simple, are you testing the control text both before and after muting to see if it changes? It looks to me based on what you are showing me that the tooltip shows pretty much the same text as the control, that makes me believe that maybe they would be the same if muted or not. Just a thought. some idea of a code for the above:

msgbox, 4, Mute state? Is the Arma volume muted?
IfMsgbox, Yes
	ArmaMute := 1
Else IfMsgbox, No
	ArmaMute := 0
Return


soulkobk
  • Members
  • 10 posts
  • Last active: Jan 09 2016 04:30 AM
  • Joined: 26 Dec 2014

@Masonjar13, yup, thanks. I downloaded/installed the latest version and have VA.ahk, but like I said, I'm a newbie when it comes to AHK, so I have no idea on how to get the mute state from the application within volume mixer. *completely lost atm*

 

@T_Lube, thanks. The ControlGetText stays static on that button as "Mute For Arma 3", it doesn't change. As for the tooltip (when I hover my mouse), the text does change from "Mute Arma 3" to "Unmute Arma 3". Again, no idea how to extract it without me hovering my mouse over the button itself (which is something I can't do).

 

As for manually setting the mute state into a variable... I thought about doing that.. but opted not to, I'd rather read the current mute state and then set the variable based on that information.

 

TBCH, I'm about ready to give up... it's frustrating and difficult to try and get the most simplest state, muted/unmuted... yet extracting this information seems almost impossible *sigh*.



Masonjar13
  • Members
  • 1517 posts
  • Last active:
  • Joined: 16 Sep 2012

use the exact code Linear Spoon posted

I meant that literally.. Copy and paste it into a script by itself, with VA in the same folder, and run it.. It will tell you if the current application exists in the mixer and if it does, what it's mute state is, then will change it to the opposite state.


OS: Windows 7 Ultimate / Windows 8.1 Pro | Editor: Notepad++


Linear Spoon
  • Members
  • 842 posts
  • Last active: Sep 29 2015 03:56 AM
  • Joined: 29 Oct 2011
✓  Best Answer

Spent a bit more time looking through VA.ahk and this code, which was originally posted here. It seems the author of this provided functions to get the volume level in addition to the mute state. The volume level returned by these functions are not the same as what is shown in "Volume Mixer"; it seems a process specific volume level gets rescaled by the global volume level.

 

I've modified the original script to show the volume status of the window under the mouse in a tooltip. It should match what "Volume Mixer" displays now. 

Requirements:

OS: Vista+

AHK 1.1+ (The download on this site is an old version, use http://ahkscript.org/ instead)

VA.ahk v2.4

 

Paste the code below into a new AHK file.

Place VA.ahk in the same directory as the first file (or modify the #Include line with a full path to VA.ahk)

Run the first script. It can be closed using the tray icon near the system clock.

Volume level and mute status of the process owning a window will be shown in a tooltip near the mouse as you hover over the window.

#Include VA.ahk
#Persistent
SetTimer, Update, 100

Update:
  ;Get hwnd of the window under the mouse
  MouseGetPos, x, y, hwnd
  
  ;Skip processing if the mouse hasn't moved
  if (x = oldX && y = oldY)
    return
  oldX := x, oldY := y
  
  ;Get PID and window title of the window handle found earlier
  WinGet, ActivePid, PID, ahk_id %hwnd%
  WinGetTitle, Title, ahk_id %hwnd%
  
  ;Get process specific volume object
  ;Note: Pass 0 instead of ActivePid for "System Sounds" volume object
  if !(VolumeObject := GetVolumeObject(ActivePid))
  {
    tooltip, No volume information for this process.
    return
  }
  ;Get process specific volume level and mute status
  VA_ISimpleAudioVolume_GetMute(VolumeObject, AppMute)  ;AppMute = true or false
  VA_ISimpleAudioVolume_GetMasterVolume(VolumeObject, AppVolume)  ;AppVolume = floating point number between 0 and 1 (Multiply by 100 for percent)
  ObjRelease(VolumeObject) ;Cleanup
  
  ;Get "global" volume level and mute status
  GlobalVolume := VA_GetMasterVolume()  ;Returns volume 0-100
  GlobalMute := VA_GetMasterMute()
  
  ;Show gathered information
  ;Window titles are trimmed to 30 characters, volume level is rounded to the nearest integer to match volume mixer output
  tooltip % (StrLen(Title) > 30 ? SubStr(Title, 1, 30) "..." : Title) " : " (GlobalMute || AppMute ? "Muted" : Round(AppVolume*GlobalVolume,0) "%")
return

;Required for app specific mute
GetVolumeObject(Param = 0)
{
    static IID_IASM2 := "{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}"
    , IID_IASC2 := "{bfb7ff88-7239-4fc9-8fa2-07c950be9c6d}"
    , IID_ISAV := "{87CE5498-68D6-44E5-9215-6DA47EF883D8}"
    
    ; Get PID from process name
    if Param is not Integer
    {
        Process, Exist, %Param%
        Param := ErrorLevel
    }
    
    ; GetDefaultAudioEndpoint
    DAE := VA_GetDevice()
    
    ; activate the session manager
    VA_IMMDevice_Activate(DAE, IID_IASM2, 0, 0, IASM2)
    
    ; enumerate sessions for on this device
    VA_IAudioSessionManager2_GetSessionEnumerator(IASM2, IASE)
    VA_IAudioSessionEnumerator_GetCount(IASE, Count)
    
    ; search for an audio session with the required name
    Loop, % Count
    {
        ; Get the IAudioSessionControl object
        VA_IAudioSessionEnumerator_GetSession(IASE, A_Index-1, IASC)
        
        ; Query the IAudioSessionControl for an IAudioSessionControl2 object
        IASC2 := ComObjQuery(IASC, IID_IASC2)
        ObjRelease(IASC)
        
        ; Get the session's process ID
        VA_IAudioSessionControl2_GetProcessID(IASC2, SPID)
        
        ; If the process name is the one we are looking for
        if (SPID == Param)
        {
            ; Query for the ISimpleAudioVolume
            ISAV := ComObjQuery(IASC2, IID_ISAV)
            
            ObjRelease(IASC2)
            break
        }
        ObjRelease(IASC2)
    }
    ObjRelease(IASE)
    ObjRelease(IASM2)
    ObjRelease(DAE)
    return ISAV
}
 
;
; ISimpleAudioVolume : {87CE5498-68D6-44E5-9215-6DA47EF883D8}
;
VA_ISimpleAudioVolume_SetMasterVolume(this, ByRef fLevel, GuidEventContext="") {
    return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "float", fLevel, "ptr", VA_GUID(GuidEventContext))
}
VA_ISimpleAudioVolume_GetMasterVolume(this, ByRef fLevel) {
    return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "float*", fLevel)
}
VA_ISimpleAudioVolume_SetMute(this, ByRef Muted, GuidEventContext="") {
    return DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "int", Muted, "ptr", VA_GUID(GuidEventContext))
}
VA_ISimpleAudioVolume_GetMute(this, ByRef Muted) {
    return DllCall(NumGet(NumGet(this+0)+6*A_PtrSize), "ptr", this, "int*", Muted)
}

Join us at the new forum - http://www.ahkscript.org/

 


Linear Spoon
  • Members
  • 842 posts
  • Last active: Sep 29 2015 03:56 AM
  • Joined: 29 Oct 2011

Edit: Double posted


Join us at the new forum - http://www.ahkscript.org/

 


soulkobk
  • Members
  • 10 posts
  • Last active: Jan 09 2016 04:30 AM
  • Joined: 26 Dec 2014

@Linear Spoon, thanks again for the reference script for use with VA.ahk.

 

I have sat down and gone through the code and decided to go ahead and use what I need in order to get the mute state of said process.

 

I noted that I need the PID in order for that to happen, so I adjusted my script to get the PID of the process, and go from there.

 

The mute proc is now as follows...

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

ToggleMute()
{
	IfWinExist, %Arma3Title%
	{
		Process, Exist, %Arma3Exe%
		If !(Arma3PID := ErrorLevel)
		{
		MsgBox, 16, %Arma3Title% Error!, ERROR: %Arma3Exe% does not exist - please make sure %Arma3Title% is running.
		return
		}
		ToolbarWindowNumber = 322
		msctls_trackbarNumber = 321
		ControlGetPos, refX, refY, refW, refH, %Arma3Title%, %VolMixTitle%
		x = -1
		while ( x != "")
		{
			tbIDX := (A_Index * 2)
			ControlGetPos, x, y, w, h, ToolbarWindow32%tbIDX%, %VolMixTitle%
			diff := x - refX
			if (diff > 0 && diff < refW)
			{
			ControlClick, ToolbarWindow32%tbIDX%, %VolMixTitle%
			VolumeObject := GetVolumeObject(Arma3PID)
			VA_ISimpleAudioVolume_GetMute(VolumeObject, AppMute)
			VA_ISimpleAudioVolume_GetMasterVolume(VolumeObject, AppVolume)
			ObjRelease(VolumeObject)
			GlobalVolume := VA_GetMasterVolume()
			GlobalMute := VA_GetMasterMute()
			ArmaCurVol := % (GlobalMute || AppMute ? "MUTED" : Round(AppVolume*GlobalVolume,0))
			If (OSDShow = "YES")
			{
			OSD(ArmaCurVol)
			}
			Break
			}
		}
	}
	Return
}

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

This now shows a "progress" bar on the screen (proc not shown) whilst using volume up/down, and also has a mute state which also shows on screen until unmuted.

 

I appreciate all the help you have given me in attempting to gather the mute state (which also gathers the volume of the PID also).

 

I have changed my code to gather the volume % and mute status via VA.ahk.

 

Thanks again all.



T_Lube
  • Members
  • 640 posts
  • Last active: Sep 09 2016 02:19 AM
  • Joined: 16 Oct 2014

Make sure to mark the topic as solved if you are all done then.



skribb
  • Members
  • 38 posts
  • Last active: Jan 16 2017 01:24 AM
  • Joined: 13 Oct 2009

Edit: Double posted

Would you be able to adapt this http://stackoverflow...367829#14367829

 

to get the current volume peak for a given app?

 

I don't understand the code enough to attempt it myself



Igrac813
  • Members
  • 1 posts
  • Last active: Dec 26 2015 06:15 PM
  • Joined: 23 Dec 2015

I used the code that masonjar said "Forget everything I said and use this. Works perfectly." This is true that it works but a problem I have is that it creates a message box which takes me out of full screened programs. I would like to use this script but not have the message box generated so that it does not take me out of the program.