#Region - TimeStamp
; 2012-07-26 23:34:55   v 0.1
#EndRegion - TimeStamp

#include-once
#include <GuiSlider.au3>
#include <WinAPI.au3>

OnAutoItExitRegister('_CloseSound')

Global $__aSound_Apps = _Win7_AppSoundGetApps()
Global $__aSound_iPID

;===============================================================================
; Function Name....: _Win7_AppSoundGet
; Description......: Gibt die lineare Position des Sliders zurück (0-100)
; .................: für übergebenes Sliderhandle oder Anwendungsname
; Parameter(s).....: $hSlider  Handle des Slider (aus _Win7_GetApps)
; .................: $sApp     Name der Anwendung (aus _Win7_GetApps)
; Return Value(s)..: Linearer Wert des Sliders
; Author(s)........: BugFix ( bugfix@autoit.de )
;===============================================================================
Func _Win7_AppSoundGet($hSlider=-1, $sApp='Systemsounds')
	For $i = 0 To UBound($__aSound_Apps) -1
		If $hSlider = -1 Then
			If $__aSound_Apps[$i][1] = $sApp Then
				Return 100 - _GUICtrlSlider_GetPos($__aSound_Apps[$i][0])
			EndIf
		Else
			Return 100 - _GUICtrlSlider_GetPos($hSlider)
		EndIf
	Next
EndFunc  ;==>_Win7_AppSoundGet

;===============================================================================
; Function Name....: _Win7_AppSoundSet
; Description......: Setzt die lineare Position des Sliders (0-100)
; .................: für übergebenes Sliderhandle oder Anwendungsname
; Parameter(s).....: $iVal     der zu setzende Wert
; .................: $hSlider  Handle des Slider (aus _Win7_GetApps)
; .................: $sApp     Name der Anwendung (aus _Win7_GetApps)
; Return Value(s)..: keiner
; Author(s)........: BugFix ( bugfix@autoit.de )
;===============================================================================
Func _Win7_AppSoundSet($iVal, $hSlider=-1, $sApp='Systemsounds')
	For $i = 0 To UBound($__aSound_Apps) -1
		If $hSlider = -1 Then
			If $__aSound_Apps[$i][1] = $sApp Then
				_GUICtrlSlider_SetPos($__aSound_Apps[$i][0], 100 - $iVal)
			EndIf
		Else
			_GUICtrlSlider_SetPos($hSlider, 100 - $iVal)
		EndIf
	Next
EndFunc  ;==>_Win7_AppSoundSet

;===============================================================================
; Function Name....: _Win7_AppSoundRefresh
; Description......: Aktualisieren der Anwendungen / Handle
; Author(s)........: BugFix ( bugfix@autoit.de )
;===============================================================================
Func _Win7_AppSoundRefresh()
	$__aSound_Apps = _Win7_AppSoundGetApps()
EndFunc  ;==>_Win7_AppSoundRefresh


;===============================================================================
; Function Name....: _Win7_AppSoundGetApps
; Description......: Ermittelt die anwendungspezifischen Slider im Soundmixer
; Parameter(s).....: keine
; Requirement(s)...: OS Vista oder höher
; Return Value(s)..: 2D-Array [[Handle-Slider, Name Anwendung]]
; Author(s)........: BugFix ( bugfix@autoit.de )
;===============================================================================
Func _Win7_AppSoundGetApps()
	Local Const $GW_CHILD = 5
	Local Const $GW_HWNDNEXT = 2
	$__aSound_iPID = Run("sndvol", @WorkingDir, @SW_HIDE)
	Local $hMixer = WinWait("Lautstärkemixer")
	Local $oldOpt = Opt("WinTitleMatchMode", 2)
	Opt("WinTitleMatchMode", $oldOpt)

    Local $iTop, $iLeft, $aPos
    _SystemGetWindowBorder($iTop, $iLeft)
	Local $iInst = 2, $aWnd = WinGetPos("Lautstärkemixer")
	Local $sText = StringReplace(ControlGetText("Lautstärkemixer", '', '[CLASS:ToolbarWindow32; INSTANCE:' & $iInst & ']'), 'Stumm für ', '')
	Local $sApp
    While $sText <> ""
		$aPos = ControlGetPos("Lautstärkemixer", '', '[CLASS:ToolbarWindow32; INSTANCE:' & $iInst & ']')
		$sApp &= $iLeft+$aPos[0]+$aWnd[0] & ',' & $iLeft+$aPos[0]+$aPos[2]+$aWnd[0] +5 & '|' & $sText & @LF
		$iInst += 2
		$sText = StringReplace(ControlGetText("Lautstärkemixer", '', '[CLASS:ToolbarWindow32; INSTANCE:' & $iInst & ']'), 'Stumm für ', '')
    WEnd
	Local $aTmp = StringSplit(StringTrimRight($sApp, 1), @LF), $aSplit

	Local $aApp[$aTmp[0]][2]
	For $i = 1 To $aTmp[0]
		$aSplit = StringSplit($aTmp[$i], '|')
		$aApp[$i-1][0] = $aSplit[1]
		$aApp[$i-1][1] = $aSplit[2]
	Next

	Local $hChildMix  = _WinAPI_GetWindow($hMixer, $GW_CHILD)
	Local $hAppsOuter = _WinAPI_GetWindow($hChildMix, $GW_HWNDNEXT)
	Local $hAppsInner = _WinAPI_GetWindow($hAppsOuter, $GW_CHILD)
	Local $aHWnd[$aTmp[0]][2]
	Local $hTmp = _WinAPI_GetWindow($hAppsInner, $GW_CHILD)
	Local $hSub, $n = 0, $i = 0, $aRange
	While $hTmp <> 0x00000000
		$aHWnd[$i][0] = $hTmp
		$hTmp = _WinAPI_GetWindow($hTmp, $GW_HWNDNEXT)
		$i += 1
	WEnd

	For $i = 0 To $aTmp[0] -1
		$hSub = _WinAPI_GetWindow($aHWnd[$i][0], $GW_CHILD)
		$n = 0
		While $hSub <> 0x00000000
			$n += 1
			If $n = 5 Then
				$aHWnd[$i][0] = $hSub
				$tRect = _WinAPI_GetWindowRect($hSub)
				$aHWnd[$i][1] = DllStructGetData($tRect, 3)
				For $j = 0 To $aTmp[0] -1
					$aRange = StringSplit($aApp[$j][0], ',')
					If $aHWnd[$i][1] > $aRange[1] And $aHWnd[$i][1] < $aRange[2] Then
						$aHWnd[$i][1] = $aApp[$j][1]
						ExitLoop
					EndIf
				Next
				ExitLoop
			EndIf
			$hSub = _WinAPI_GetWindow($hSub, $GW_HWNDNEXT)
		WEnd
	Next
	Return $aHWnd
EndFunc  ;==>_Win7_AppSoundGetApps

Func _CloseSound()
	ProcessClose($__aSound_iPID)
EndFunc

;===============================================================================
; Function Name....: _SystemGetWindowBorder
; Description......: Calculates side and top border of window
; Author(s)........: BugFix ( bugfix@autoit.de )
;===============================================================================
Func _SystemGetWindowBorder(ByRef $_iTopBorder, ByRef $_iSideBorder)
	Local Const $SM_CYCAPTION = 4, $SM_CYEDGE = 46, $SM_CYBORDER = 6, $SM_CXBORDER = 5, $SM_CXEDGE = 45
	Local $aMetrics[5][2] = [[$SM_CYCAPTION], [$SM_CYEDGE], [$SM_CYBORDER], [$SM_CXBORDER], [$SM_CXEDGE]]
	Local $dll = DllOpen("user32.dll"), $aRet
	For $i = 0 To 4
		$aRet = DllCall($dll, "int", "GetSystemMetrics", "int", $aMetrics[$i][0])
		If IsArray($aRet) Then $aMetrics[$i][1] = $aRet[0]
	Next
	DllClose($dll)
	$_iTopBorder  = $aMetrics[0][1] + $aMetrics[1][1] + $aMetrics[2][1]
	$_iSideBorder = $aMetrics[3][1] + $aMetrics[4][1]
EndFunc  ;==>_SystemGetWindowBorder