wraithdu

Control Vista+ Master Volume

74 posts in this topic

#1 ·  Posted (edited)

UPDATE:

With the addition of the ObjCreateInterface function and enhanced COM functionality by trancexxx, these interfaces are now accessible directly in AutoIt. I've rewritten the plugin as a native UDF which will work when compiled as x64 as well. I've attached the new UDF as well as updated plugin and UDF versions of my OSD Volume script.

UDF Example:

#include <_AudioEndpointVolume.au3>

; ## Get current volume levels
$vol = _GetMasterVolumeLevel()
ConsoleWrite("Get Vol Error: " & @error & @CRLF)
ConsoleWrite("Volume: " & $vol & " (decibels)" & @CRLF)

$vol = _GetMasterVolumeLevelScalar()
ConsoleWrite("Get Vol Error: " & @error & @CRLF)
ConsoleWrite("Volume: " & $vol & " (scalar)" & @CRLF)

; ## Set new volume levels
ConsoleWrite("Set vol to -20db..." & @CRLF)
_SetMasterVolumeLevel(-20)
ConsoleWrite("Set Vol Error: " & @error & @CRLF)

$vol = _GetMasterVolumeLevel()
ConsoleWrite("Get Vol Error: " & @error & @CRLF)
ConsoleWrite("Volume: " & $vol & " (decibels)" & @CRLF)

ConsoleWrite("Set vol to scalar 30..." & @CRLF)
_SetMasterVolumeLevelScalar(30)
ConsoleWrite("Set Vol Error: " & @error & @CRLF)

$vol = _GetMasterVolumeLevelScalar()
ConsoleWrite("Get Vol Error: " & @error & @CRLF)
ConsoleWrite("Volume: " & $vol & " (scalar)" & @CRLF)

; ## Get volume range information
ConsoleWrite("Get range info..." & @CRLF)
$aInfo = _GetVolumeRange()
ConsoleWrite("Get Range Error: " & @error & @CRLF)
ConsoleWrite("MinDB: " & $aInfo[0] & @CRLF)
ConsoleWrite("MaxDB: " & $aInfo[1] & @CRLF)
ConsoleWrite("Increment: " & $aInfo[2] & @CRLF)

; ## Set mute states
ConsoleWrite("Set mute on..." & @CRLF)
_SetMute(1)
ConsoleWrite("Set Mute Error: " & @error & @CRLF)

$mute = _GetMute()
ConsoleWrite("Get Mute Error: " & @error & @CRLF)
ConsoleWrite("Muted: " & $mute & @CRLF)

Sleep(2000)

ConsoleWrite("Set mute off..." & @CRLF)
_SetMute(0)
ConsoleWrite("Set Mute Error: " & @error & @CRLF)

$mute = _GetMute()
ConsoleWrite("Get Mute Error: " & @error & @CRLF)
ConsoleWrite("Muted: " & $mute & @CRLF)

; ## Get volume step info
; ## Steps range from 0 to nStepCount - 1
ConsoleWrite("Get step info..." & @CRLF)
$aInfo = _GetVolumeStepInfo()
ConsoleWrite("Get Step Error: " & @error & @CRLF)
ConsoleWrite("Current step: " & $aInfo[0] & @CRLF)
ConsoleWrite("Total steps: 0 to " & $aInfo[1] - 1 & @CRLF)

ConsoleWrite("Increase 5 steps..." & @CRLF)
For $i = 1 To 5
    _VolumeStepUp()
Next
$aInfo = _GetVolumeStepInfo()
ConsoleWrite("Get Step Error: " & @error & @CRLF)
ConsoleWrite("Current step: " & $aInfo[0] & @CRLF)

ConsoleWrite("Decrease 2 steps..." & @CRLF)
For $i = 1 To 2
    _VolumeStepDown()
Next
$aInfo = _GetVolumeStepInfo()
ConsoleWrite("Get Step Error: " & @error & @CRLF)
ConsoleWrite("Current step: " & $aInfo[0] & @CRLF)

OLD PLUGIN VERSION

NOTE: This plugin requires the Microsoft VC++ 2008 SP1 Redistributable to be installed.

It's well known that the sound volume functions do not work for Vista's master volume because of Vista's new audio stream system. There's a way to do it, but it requires COM interfaces / objects that AutoIt cannot natively access, so I wrote a plugin. Here's a collection of the useful interface methods, and an example script. Enjoy!

/****************************************************************************
* _GetMasterVolume_Vista()
*
* Returns master volume level in decibels.
****************************************************************************
* _GetMasterVolumeScalar_Vista()
*
* Returns master volume level as a scalar value from 0 to 100.
****************************************************************************
* _SetMasterVolume_Vista()
*
* Sets master volume in decibels.
****************************************************************************
* _SetMasterVolumeScalar_Vista()
*
* Sets master volume level as a scalar value from 0 to 100.
****************************************************************************
* _GetVolumeRange_Vista()
*
* Gets volume decibel range information:
* LevelMinDB = minimum decibel value
* LevelMaxDB = maximum decibel value
* VolumeIncrementDB = decibel increment value
****************************************************************************
* _IsMute_Vista()
*
* Gets the mute state.
****************************************************************************
* _SetMute_Vista()
*
* Sets the mute state.
****************************************************************************
* _GetVolumeStepInfo_Vista()
*
* Gets volume step information:
* nStep = current volume step
* nStepCount = step range; from 0 to nStepCount - 1
****************************************************************************
* _VolumeStepUp_Vista()
*
* Increases the volume by 1 step.
****************************************************************************
* _VolumeStepDown_Vista()
*
* Decreases the volume by 1 step.
****************************************************************************/

Example -

#AutoIt3Wrapper_Plugin_Funcs=_GetMasterVolume_Vista,_GetMasterVolumeScalar_Vista, _
_SetMasterVolume_Vista,_SetMasterVolumeScalar_Vista,_GetVolumeRange_Vista,_IsMute_Vista, _
_SetMute_Vista,_GetVolumeStepInfo_Vista,_VolumeStepUp_Vista,_VolumeStepDown_Vista

$hDLL = PluginOpen("vista_vol.dll")

; ## Get current volume levels
$vol = _GetMasterVolume_Vista()
ConsoleWrite("Get Vol Error: " & @error & @CRLF)
ConsoleWrite("Volume: " & $vol & " (decibels)" & @CRLF)

$vol = _GetMasterVolumeScalar_Vista()
ConsoleWrite("Get Vol Error: " & @error & @CRLF)
ConsoleWrite("Volume: " & $vol & " (scalar)" & @CRLF)

; ## Set new volume levels
ConsoleWrite("Set vol to -20db..." & @CRLF)
_SetMasterVolume_Vista(-20)
ConsoleWrite("Set Vol Error: " & @error & @CRLF)

$vol = _GetMasterVolume_Vista()
ConsoleWrite("Get Vol Error: " & @error & @CRLF)
ConsoleWrite("Volume: " & $vol & " (decibels)" & @CRLF)

ConsoleWrite("Set vol to scalar 30..." & @CRLF)
_SetMasterVolumeScalar_Vista(30)
ConsoleWrite("Set Vol Error: " & @error & @CRLF)

$vol = _GetMasterVolumeScalar_Vista()
ConsoleWrite("Get Vol Error: " & @error & @CRLF)
ConsoleWrite("Volume: " & $vol & " (scalar)" & @CRLF)

; ## Get volume range information
$range = DllStructCreate("float LevelMinDB;float LevelMaxDB;float VolumeIncrementDB")
ConsoleWrite("Get range info..." & @CRLF)
_GetVolumeRange_Vista(DllStructGetPtr($range))
ConsoleWrite("Get Range Error: " & @error & @CRLF)
ConsoleWrite("MinDB: " & DllStructGetData($range, "LevelMinDB") & @CRLF)
ConsoleWrite("MaxDB: " & DllStructGetData($range, "LevelMaxDB") & @CRLF)
ConsoleWrite("Increment: " & DllStructGetData($range, "VolumeIncrementDB") & @CRLF)

; ## Set mute states
ConsoleWrite("Set mute true..." & @CRLF)
_SetMute_Vista(True)
ConsoleWrite("Set Mute Error: " & @error & @CRLF)

$mute = _IsMute_Vista()
ConsoleWrite("Get Mute Error: " & @error & @CRLF)
ConsoleWrite("Muted: " & $mute & @CRLF)

Sleep(2000)

ConsoleWrite("Set mute false..." & @CRLF)
_SetMute_Vista(False)
ConsoleWrite("Set Mute Error: " & @error & @CRLF)

$mute = _IsMute_Vista()
ConsoleWrite("Get Mute Error: " & @error & @CRLF)
ConsoleWrite("Muted: " & $mute & @CRLF)

; ## Get volume step info
; ## Steps range from 0 to nStepCount - 1
$step = DllStructCreate("uint nStep;uint nStepCount")
ConsoleWrite("Get step info..." & @CRLF)
_GetVolumeStepInfo_Vista(DllStructGetPtr($step))
ConsoleWrite("Get Step Error: " & @error & @CRLF)
ConsoleWrite("Current step: " & DllStructGetData($step, "nStep") & @CRLF)
ConsoleWrite("Total steps: 0 to " & DllStructGetData($step, "nStepCount") - 1 & @CRLF)

ConsoleWrite("Increase 5 steps..." & @CRLF)
For $i = 1 To 5
    _VolumeStepUp_Vista()
Next
_GetVolumeStepInfo_Vista(DllStructGetPtr($step))
ConsoleWrite("Get Step Error: " & @error & @CRLF)
ConsoleWrite("Current step: " & DllStructGetData($step, "nStep") & @CRLF)

ConsoleWrite("Decrease 2 steps..." & @CRLF)
For $i = 1 To 2
    _VolumeStepDown_Vista()
Next
_GetVolumeStepInfo_Vista(DllStructGetPtr($step))
ConsoleWrite("Get Step Error: " & @error & @CRLF)
ConsoleWrite("Current step: " & DllStructGetData($step, "nStep") & @CRLF)

PluginClose($hDLL)

vista_vol_plugin.zip

_AudioEndpointVolume.au3

VolumeOSD.zip

VolumeOSD_plugin.zip

Edited by wraithdu
3 people like this

Share this post


Link to post
Share on other sites



Fixed a few things in the OSD Volume script.

Share this post


Link to post
Share on other sites

It works great !!! Many thanks for this.

Tested on Vista x64

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

PluinOpen returns a "handle" to the opende plugin which you can use in PluinClose. The first loaded plugin is assigned to index 0, but also 0 is returned for an error.

This wrapper-func should return -1 if the plugin can't be loaded.

Func _PluginOpen($DLL)
    ; Prog@ndy
    Local $handle = PluginOpen($DLL)
    If $handle > 0 Then Return $handle
    Local $aResult = DLLCall("Kernel32.dll", "ptr", "GetModuleHandleW", "wstr", StringReplace($DLL,"/","\"))
    If @error Or $aResult[0]=Ptr(0) Then Return SetError(1,0,-1)
    Return $handle
EndFunc
Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

PluinOpen returns a "handle" to the opende plugin which you can use in PluinClose. The first loaded plugin is assigned to index 0, but also 0 is returned for an error.

This wrapper-func should return -1 if the plugin can't be loaded.

Func _PluginOpen($DLL)
    ; Prog@ndy
    Local $handle = PluginOpen($DLL)
    If $handle > 0 Then Return $handle
    Local $aResult = DLLCall("Kernel32.dll", "ptr", "GetModuleHandleW", "wstr", StringReplace($DLL,"/","\"))
    If @error Or $aResult[0]=Ptr(0) Then Return SetError(1,0,-1)
    Return $handle
EndFunc
Returns (-1). Plugin does not work.

Share this post


Link to post
Share on other sites

I think the plugin needs VC 2008 redistributables. Try to install them:

http://www.microsoft.com/downloads/en/resu...p;stype=s_basic


*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

Share this post


Link to post
Share on other sites

Hello, wraithdu.

I found out your work while searching for a way to give a particular application the control of Vista/Win7 master volume.

The thing is that I have an old Sony Vaio laptop (VGN S2XP) that needs a special application (Sony Hotkey Utility) to control the laptop FN keys. The problem is that this program was designed for Windows XP and Sony doesn't support Vista on this laptop. As Vista/Win7 has per-application volume control, this program doesn't work anymore. It detects the VOL + and VOL -, but instead of changing master volume it only changes the volume associated with the app.

Here's a screenshot:

Posted Image

My hope was to "modify" this application so it could control directly Vista master volume. This utility consists of two .exe and two .dll files. I was thinking if there was some way to decompile this app and to adapt it using your plugin, but my programming skills aren't good enough. Do you think you can help me? Is this possible or is it an impossible mission?

The program can be downloaded here: Sony HotKey Utility.

Thanks in advance.

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Share this post


Link to post
Share on other sites

I am curious that Sony had written in the license agreement for this program? Do you think? :D

Maybe you like this.

Hmmm... That program is nice, although it doesn't detect my FN+VOL+ and FN+VOL- keys.

Regarding my previous questions... Do you think it is possible?

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

No, not possible. No way can I hack Sony's program to change how it works. Your best bet is to try and find out how to detect your volume hot keys. Maybe write a keyboard hook and integrate it into my volume OSD script? Or try to find out what those hotkeys are exactly, and set them using AutoIt or a direct call to the RegisterHotKey API. You'll need to figure out what the virtual key code is for the FN key on a laptop though.

Edited by wraithdu

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

Hello, wraithdu.

I found out your work while searching for a way to give a particular application the control of Vista/Win7 master volume.

The thing is that I have an old Sony Vaio laptop (VGN S2XP) that needs a special application (Sony Hotkey Utility) to control the laptop FN keys. The problem is that this program was designed for Windows XP and Sony doesn't support Vista on this laptop. As Vista/Win7 has per-application volume control, this program doesn't work anymore. It detects the VOL + and VOL -, but instead of changing master volume it only changes the volume associated with the app.

Here's a screenshot:

My hope was to "modify" this application so it could control directly Vista master volume. This utility consists of two .exe and two .dll files. I was thinking if there was some way to decompile this app and to adapt it using your plugin, but my programming skills aren't good enough. Do you think you can help me? Is this possible or is it an impossible mission?

The program can be downloaded here: Sony HotKey Utility.

Thanks in advance.

How skilled are you when it comes to more low-level winapi stuff? I would simply inject a dll that hooks the winapi function that handles setting the sound level (my guess: waveOutSetVolume) and then call a function that changes vista's sound level instead.

Some info on api hooking in my sig, if you still don't get it, hit me a pm and we'll see if we can work something out :)

Edited by monoceres

Broken link? PM me and I'll send you the file!

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

Share this post


Link to post
Share on other sites

Iteresting info on the Fn key, and good idea monoceres. Looks like it might be possible though to find out what virtual key code is being sent by the *combination* of the Fn+Vol keys. Then you can hook that, either with a global keyboard hook or with the RegisterHotKey api.

Share this post


Link to post
Share on other sites

How skilled are you when it comes to more low-level winapi stuff? I would simply inject a dll that hooks the winapi function that handles setting the sound level (my guess: waveOutSetVolume) and then call a function that changes vista's sound level instead.

Some info on api hooking in my sig, if you still don't get it, hit me a pm and we'll see if we can work something out :)

As I told before, my programing skills aren't good enough to make this on my own. I've only learned C in the university, but didn't practice anymore.

Could you help me getting this to work?

Share this post


Link to post
Share on other sites

having trouble installing Control Vista Master Volume, Plugin + OSD Volume Script, could i get some help please. :)

Share this post


Link to post
Share on other sites

I replied to your PM. Try to keep your communication to one avenue. Spamming forum posts and PMs is a good way to anger the forum gods.

Share this post


Link to post
Share on other sites

Thanks for your quick reply, misunderstood purpose of script. I thought it was a script that actually affected vistaX64 OS software volume control. Having trouble with low volume output on my new systems onboard sound card. :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now