;#NoTrayIcon
#include <Array.au3>
; Autoit 3.3.8.0 и выше
If Not StringRegExp(@OSVersion, '(WIN_7)|(Win_8)|', 0) Then Exit ; WIN 7 и выше
$Count = 20 ; количество элементов в массиве для анализа средней громкости, чем больше, тем реже будет корректироваться громкость
$AudioLevel = 500 ; некий эталонный уровень громкости, подбирается вручную
Dim $aAudio[1]
$summ = 0
_Global()
HotKeySet('{ESC}', '_Exit')
AdlibRegister('_LevelMeter', 100)
While 1
Sleep(100)
WEnd
Func _LevelMeter()
Local $iPeak
If $oAudioMeterInformation.GetPeakValue($iPeak) = $S_OK Then
$iCurrentRead = 100 * $iPeak
$audiovolume = Round($iCurrentRead, 1)
;ConsoleWrite($audiovolume & @CR)
If $audiovolume > 0 Then
If UBound($aAudio) - 1 < $Count Then
_ArrayAdd($aAudio, $audiovolume)
Else
_ArrayDelete($aAudio, 0)
For $i = 0 To UBound($aAudio) - 1
$summ += $aAudio[$i]
Next
$summ = $summ / $Count
$summ = Round($AudioLevel / $summ)
If $summ >= 100 Then $summ = 98
If $summ <= 0 Then $summ = 2
If $summ <> Round(_GetMasterVolumeLevelScalar()) Then
_SetMasterVolumeLevelScalar($summ)
ConsoleWrite('Громкость ' & $summ & @CR)
EndIf
ReDim $aAudio[1]
EndIf
EndIf
EndIf
EndFunc ;==>_LevelMeter
Func _Exit()
Exit
EndFunc ;==>_Exit
Func _Global()
Global Const $S_OK = 0
;===============================================================================
#interface "IMMDeviceEnumerator"
Global Const $sCLSID_MMDeviceEnumerator = "{BCDE0395-E52F-467C-8E3D-C4579291692E}"
Global Const $sIID_IMMDeviceEnumerator = "{A95664D2-9614-4F35-A746-DE8DB63617E6}"
; Definition
Global Const $tagIMMDeviceEnumerator = "EnumAudioEndpoints hresult(dword;dword;ptr*);" & _
"GetDefaultAudioEndpoint hresult(dword;dword;ptr*);" & _
"GetDevice hresult(wstr;ptr*);" & _
"RegisterEndpointNotificationCallback hresult(ptr);" & _
"UnregisterEndpointNotificationCallback hresult(ptr);"
;===============================================================================
;===============================================================================
#interface "IMMDevice"
Global Const $sIID_IMMDevice = "{D666063F-1587-4E43-81F1-B948E807363F}"
; Definition
Global Const $tagIMMDevice = "Activate hresult(clsid;dword;variant*;ptr*);" & _
"OpenPropertyStore hresult(dword;ptr*);" & _
"GetId hresult(ptr*);" & _
"GetState hresult(dword*);"
;===============================================================================
;===============================================================================
#interface "IAudioMeterInformation"
Global Const $sIID_IAudioMeterInformation = "{C02216F6-8C67-4B5B-9D00-D008E73E0064}"
; Definition
Global Const $tagIAudioMeterInformation = "GetPeakValue hresult(float*);" & _
"GetMeteringChannelCount hresult(dword*);" & _
"GetChannelsPeakValues hresult(dword;float*);" & _
"QueryHardwareSupport hresult(dword*);"
;===============================================================================
Global $oAudioMeterInformation = _AudioVolObject()
If Not IsObj($oAudioMeterInformation) Then Exit -1 ; Will happen on non-supported systems
Global Const $CLSID_MMDeviceEnumerator = "{BCDE0395-E52F-467C-8E3D-C4579291692E}"
Global Const $IID_IMMDeviceEnumerator = "{A95664D2-9614-4F35-A746-DE8DB63617E6}"
Global Const $IID_IMMDevice = "{D666063F-1587-4E43-81F1-B948E807363F}"
Global Const $eRender = 0, $eConsole = 0
Global Const $IID_IAudioEndpointVolume = "{5CDF2C82-841E-4546-9722-0CF74078229A}"
Global Const $tagIAudioEndpointVolume = _
"RegisterControlChangeNotify hresult(ptr);" & _
"UnregisterControlChangeNotify hresult(ptr);" & _
"GetChannelCount hresult(uint*);" & _
"SetMasterVolumeLevel hresult(float;ptr);" & _
"SetMasterVolumeLevelScalar hresult(float;ptr);" & _
"GetMasterVolumeLevel hresult(float*);" & _
"GetMasterVolumeLevelScalar hresult(float*);" & _
"SetChannelVolumeLevel hresult(uint;float;ptr);" & _
"SetChannelVolumeLevelScalar hresult(uint;float;ptr);" & _
"GetChannelVolumeLevel hresult(uint;float*);" & _
"GetChannelVolumeLevelScalar hresult(uint;float*);" & _
"SetMute hresult(int;ptr);" & _
"GetMute hresult(int*);" & _
"GetVolumeStepInfo hresult(uint*;uint*);" & _
"VolumeStepUp hresult(ptr);" & _
"VolumeStepDown hresult(ptr);" & _
"QueryHardwareSupport hresult(dword*);" & _
"GetVolumeRange hresult(float*;float*;float*)"
Global Const $CLSCTX_INPROC_SERVER = 1
Global $__g_oEndpointVolume = 0
OnAutoItExitRegister('_EndpointVolume_Close')
EndFunc ;==>_Global
Func _AudioVolObject()
; Sequences of code below are taken from the source of plugin written for AutoIt for setting master volume on Vista and above systems.
; Code was written by wraithdu in C++.
; MMDeviceEnumerator
Local $oMMDeviceEnumerator = ObjCreateInterface($sCLSID_MMDeviceEnumerator, $sIID_IMMDeviceEnumerator, $tagIMMDeviceEnumerator)
If @error Then Return SetError(1, 0, 0)
Local Const $eRender = 0
Local Const $eConsole = 0
; DefaultAudioEndpoint
Local $pDefaultDevice
$oMMDeviceEnumerator.GetDefaultAudioEndpoint($eRender, $eConsole, $pDefaultDevice)
If Not $pDefaultDevice Then Return SetError(2, 0, 0)
; Turn that pointer into object
Local $oDefaultDevice = ObjCreateInterface($pDefaultDevice, $sIID_IMMDevice, $tagIMMDevice)
Local Const $CLSCTX_INPROC_SERVER = 0x1
; AudioMeterInformation
Local $pAudioMeterInformation
$oDefaultDevice.Activate($sIID_IAudioMeterInformation, $CLSCTX_INPROC_SERVER, 0, $pAudioMeterInformation)
If Not $pAudioMeterInformation Then Return SetError(3, 0, 0)
Return ObjCreateInterface($pAudioMeterInformation, $sIID_IAudioMeterInformation, $tagIAudioMeterInformation)
EndFunc ;==>_AudioVolObject
; #FUNCTION# ====================================================================================================================
; Name ..........: _GetMasterVolumeLevelScalar
; Description ...: Get master volume level in scalar units, 0.0 to 100.0.
; Syntax ........: _GetMasterVolumeLevelScalar()
; Parameters ....:
; Return values .: Success - Master volume level in scalar units, 0.0 to 100.0 (float)
; Failure - 0 and sets @error
; Author ........: Erik Pilsits
; Modified ......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func _GetMasterVolumeLevelScalar()
_EndpointVolume_Init()
If @error Then Return SetError(-1, 0, 0)
;
Local $iVol
If __SUCCEEDED($__g_oEndpointVolume.GetMasterVolumeLevelScalar($iVol)) Then
Return($iVol * 100)
Else
Return SetError(1, 0, 0)
EndIf
EndFunc ;==>_GetMasterVolumeLevelScalar
; #FUNCTION# ====================================================================================================================
; Name ..........: _SetMasterVolumeLevelScalar
; Description ...: Set master volume level in scalar units, 0.0 to 100.0.
; Syntax ........: _SetMasterVolumeLevelScalar($iVol)
; Parameters ....: $iVol - Volume level in scalar units, 0.0 to 100.0 (float)
; Return values .: Success - 1
; Failure - 0 and sets @error
; Author ........: Erik Pilsits
; Modified ......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func _SetMasterVolumeLevelScalar($iVol)
_EndpointVolume_Init()
If @error Then Return SetError(-1, 0, 0)
;
If __SUCCEEDED($__g_oEndpointVolume.SetMasterVolumeLevelScalar($iVol / 100, 0)) Then
Return 1
Else
Return SetError(1, 0, 0)
EndIf
EndFunc ;==>_SetMasterVolumeLevelScalar
; #FUNCTION# ====================================================================================================================
; Name ..........: _EndpointVolume_Init
; Description ...: Create global endpoint volume object used by other functions
; Syntax ........: _EndpointVolume_Init()
; Parameters ....:
; Return values .: Failure - Sets @error
; | 1 - Failed to create IMMDeviceEnumerator interface
; | 2 - Failed to get default audio endpoint interface pointer
; | 3 - Failed to create IMMDevice interface
; | 4 - Failed to get endpoint volume interface pointer
; | 5 - Failed to create IAudioEndpointVolume interface
; Author ........: Erik Pilsits
; Modified ......:
; Remarks .......: Calling a function before calling Init will automatically call Init. In this case if an error occurs,
; @error is set to -1. Explicitly call Init to get the actual @error code.
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func _EndpointVolume_Init()
If IsObj($__g_oEndpointVolume) Then Return
$__g_oEndpointVolume = __GetDefaultEndpointVolume()
If @error Then Return SetError(@error)
EndFunc ;==>_EndpointVolume_Init
#region INTERNAL FUNCTIONS
Func __GetDefaultEndpointVolume()
Local $oIAudioEndpointVolume = 0, $err = 1
; create device enumerator interface
Local $oDevEnum = ObjCreateInterface($CLSID_MMDeviceEnumerator, $IID_IMMDeviceEnumerator, $tagIMMDeviceEnumerator)
If IsObj($oDevEnum) Then
$err = 2
; get default audio endpoint interface pointer
Local $pDefaultDevice = 0
If __SUCCEEDED($oDevEnum.GetDefaultAudioEndpoint($eRender, $eConsole, $pDefaultDevice)) Then
$err = 3
; create default audio endpoint interface
Local $oIMMDevice = ObjCreateInterface($pDefaultDevice, $IID_IMMDevice, $tagIMMDevice)
If IsObj($oIMMDevice) Then
$err = 4
; get endpoint volume interface pointer
Local $pEndpointVolume = 0
If __SUCCEEDED($oIMMDevice.Activate(__uuidof($IID_IAudioEndpointVolume), $CLSCTX_INPROC_SERVER, 0, $pEndpointVolume)) Then
$err = 5
; create endpoint volume interface
$oIAudioEndpointVolume = ObjCreateInterface($pEndpointVolume, $IID_IAudioEndpointVolume, $tagIAudioEndpointVolume)
EndIf
$oIMMDevice = 0
EndIf
EndIf
$oDevEnum = 0
EndIf
;
If IsObj($oIAudioEndpointVolume) Then
Return $oIAudioEndpointVolume
Else
Return SetError($err, 0, 0)
EndIf
EndFunc ;==>__GetDefaultEndpointVolume
Func __SUCCEEDED($hr)
Return($hr >= 0)
EndFunc ;==>__SUCCEEDED
Func __uuidof($sGUID)
Local $tGUID = DllStructCreate("ulong Data1;ushort Data2;ushort Data3;byte Data4[8]")
DllCall("ole32.dll", "long", "CLSIDFromString", "wstr", $sGUID, "struct*", $tGUID)
If @error Then Return SetError(@error, @extended, 0)
Return $tGUID
EndFunc ;==>__uuidof
#endregion INTERNAL FUNCTIONS