Jump to content
Sign in to follow this  
b9k

Automating SoundWire Server's Master Volume slider

Recommended Posts

Hi, I am stuck on a GUI problem and would like your help to solve it.

I am trying to automate the SoundWire Server app to match my current system volume level while it is minimized to the notification area (so no clicking or stealing focus),

I can already get the handle and alter the tracker position by sending a WM_SETPOS message, but somehow the actual volume is not changed: I think I need to do something else to trigger the event handler for the value change and propagate it correctly.

This is the control summary from Au3 info:

>>>> Window <<<<
Title:  SoundWire Server
Class:  #32770
Position:   441, 218
Size:   566, 429
Style:  0x94CA00C4
ExStyle:    0x00050101
Handle: 0x0000000000510E12

>>>> Control <<<<
Class:  msctls_trackbar32
Instance:   4
ClassnameNN:    msctls_trackbar324
Name:   
Advanced (Class):   [CLASS:msctls_trackbar32; INSTANCE:4]
ID: 6002
Text:   
Position:   51, 222
Size:   47, 126
ControlClick Coords:    1, 101
Style:  0x5001000A
ExStyle:    0x00000000
Handle: 0x00000000001234C8

>>>> Mouse <<<<
Position:   496, 567
Cursor ID:  2
Color:  0xF0F0F0

>>>> StatusBar <<<<

>>>> ToolsBar <<<<

>>>> Visible Text <<<<
Default multimedia device
Tray on Start
Static
Server Address:
 192.168.1.8
Status:
 Connected to B9K~OP3
Audio Output          Audio Input                  Level                   Record to File
Input Select:
 44.1 kHz
Minimize to
Master Volume
Mute


>>>> Hidden Text <<<<
Slider2
Mute
OK
Cancel
Label
Balance
Slider1
Volume
Front L/R
Fr C/LFE
Side L/R
Back L/R


I am attaching the program in question so you don't have to install it (i don't know if it is portable enough, tough): 

SoundWire Server_files.zip

Thanks in advance and I hope I didn't post in the wrong section :D

Edited by b9k
more info

Share this post


Link to post
Share on other sites

d'oh, I actually posted in the wrong category. can some moderator move this thread to the right place?

Share this post


Link to post
Share on other sites

On Windows7 I use a DLL to get and put the system volume.  I have done it other ways on XP but I forget atm and I'm at work.

Author: JohnOne

 

Func _SetMasterVolume($vol) ; 0 - 100
    Local $V7Voldll = "W7VVol.dll"
    DllCall($V7Voldll, 'long', 'setvol', 'float', $vol / 100)
    If @error Then
        MsgBox(0, $gScript_name, "_SetMasterVolume(): Error", @error)
        ;Exit MsgBox($gScript_name, "Error", @error)
    EndIf
EndFunc   ;==>_SetMasterVolume

Func _GetMasterVolume()
    Local $V7Voldll = "W7VVol.dll"
    $aDllCall = DllCall($V7Voldll, 'float', 'getvol')
    If @error Then
        MsgBox(0, $gScript_name, "_GetMasterVolume(): Error", @error)
        ;Exit MsgBox(0, "Error", @error)
    EndIf
    Return Round($aDllCall[0], 2) * 100
EndFunc   ;==>_GetMasterVolume

 

W7VVol.dll

Edited by Xandy

Share this post


Link to post
Share on other sites

Getting the system volume is working, so now the real problem is how to change the "Master Volume" slider in Sound Wire Server. 

I tried to send a TBS_SETPOS window message to the slider control, but while the head is moved no event handler is invoked because the volume does not change.
I believe this may be due to some other window message i need to send or because that GUI seems to be made with qt.

 

image.png

Edited by b9k

Share this post


Link to post
Share on other sites

Update: I also tried sending TBM_SETPOSNOTIFY but it does not seem to move.

I believe it may be due to the fact that the slider does not normally react to the scrolling wheel and that message's documentation said it uses a scroll message to alert the parent window of the change.

Edited by b9k
more info

Share this post


Link to post
Share on other sites

@EarthshineHere is the failing code:

#include <SendMessage.au3> ; 1029 is TBM_SETPOS, 1 is to redraw the control, 65535 is the slider position (65535 = 0%, 0 = 100%)
_SendMessage(ControlGetHandle(WinGetHandle("SoundWire Server"), "", "[CLASS:msctls_trackbar32; INSTANCE:4]"), 1029, 1, 65535)

Which actually is the same as using _GUICtrlSlider_SetPos on that control, and it does nothing.


This is the program window before running the code, with volume set to maximum (look at the Level indicator):

image.png.3384b9826351e0dad4251c2a7f05badd.png

 

This is the window after I run the above code (look at the Level indicator, it's still there even if the displayed volume is zero):
image.png.a6ef165a1be6a19e11cb4f366e93446c.png

 

And finally this is the expected result (now the Level indicator is right and the volume is zero for real):


image.png.6463f4f3cc0811ceeaaa9b83263c3532.png

I hope this helps you guys understand my problem :)

Edited by b9k

Share this post


Link to post
Share on other sites

Figure out the value when the slider is maxed.

I think you can GetPos.  You're still going to need to somehow figure out the Max.  1, 100, 128, 255 are guesses.

Is the max 1?

Max / GetPos = Val?

Something like that, I hate math.

Edit this is where I came up with that idea.

 

Edited by Xandy

Share this post


Link to post
Share on other sites

Yeah I visited that thread: it was very useful since it gave me the idea to use the TBM_SETPOS message.

In this particular case I don't need to use TBM_GETPOS because the position I am trying to set is a known value: the 65535 in my code.
It will be eventually replaced by a variable holding the correct position based on the volume (the volume value too is in the 0-65535 range so no math needed). 


Now, I only need to be able to set that slider position correctly.

Edited by b9k

Share this post


Link to post
Share on other sites

I understand now my solution wasn't valid.

I'm not sure how to handle this.  I'll keep thinking about it.

Need to set value of the slider as well as the position.  I'll look for a command and give it a go later if I have time.  You've looked for a GetVal I imagine. :)

Edited by Xandy

Share this post


Link to post
Share on other sites

You can also check the attachment in the first post if you want it portable (not tested tough). 
Thanks for the help

Edited by b9k

Share this post


Link to post
Share on other sites

@b9k

#include <GuiSlider.au3>

$hCtrl = ControlGetHandle("SoundWire Server", "", "msctls_trackbar324")
$aRange = _GUICtrlSlider_GetRange($hCtrl)
ConsoleWrite($aRange[0] & ":" & $aRange[1] & @CRLF)

_GUICtrlSlider_SetPos($hCtrl, $aRange[1] * 0.5) ; 50%
ControlSend("SoundWire Server", "", $hCtrl, "{up}")
MsgBox(0, "", "50%")

_GUICtrlSlider_SetPos($hCtrl, $aRange[1]) ; min
ControlSend("SoundWire Server", "", $hCtrl, "{up}")
MsgBox(0, "", "min")

_GUICtrlSlider_SetPos($hCtrl, $aRange[1] * 0.3) ; 70%
ControlSend("SoundWire Server", "", $hCtrl, "{up}")
MsgBox(0, "", "70%")

_GUICtrlSlider_SetPos($hCtrl, $aRange[0]) ; max
ControlSend("SoundWire Server", "", $hCtrl, "{up}")
MsgBox(0, "", "max")

 

Share this post


Link to post
Share on other sites
2 hours ago, InnI said:

@b9k

#include <GuiSlider.au3>

$hCtrl = ControlGetHandle("SoundWire Server", "", "msctls_trackbar324")
$aRange = _GUICtrlSlider_GetRange($hCtrl)
ConsoleWrite($aRange[0] & ":" & $aRange[1] & @CRLF)

_GUICtrlSlider_SetPos($hCtrl, $aRange[1] * 0.5) ; 50%
ControlSend("SoundWire Server", "", $hCtrl, "{up}")
MsgBox(0, "", "50%")

_GUICtrlSlider_SetPos($hCtrl, $aRange[1]) ; min
ControlSend("SoundWire Server", "", $hCtrl, "{up}")
MsgBox(0, "", "min")

_GUICtrlSlider_SetPos($hCtrl, $aRange[1] * 0.3) ; 70%
ControlSend("SoundWire Server", "", $hCtrl, "{up}")
MsgBox(0, "", "70%")

_GUICtrlSlider_SetPos($hCtrl, $aRange[0]) ; max
ControlSend("SoundWire Server", "", $hCtrl, "{up}")
MsgBox(0, "", "max")

 

Thanks, this is very clever indeed! So I needed to "stimulate" a refresh on the app side by sending bogus input: it works flawlessly because in this particular app the {up} and {down} keys do not change the value. But as a thought exercise, what could I have done if they did? I'm wondering... basically I got lucky this time.

I will use this trick in my code, since it works, but I'm still open to other solutions.

Share this post


Link to post
Share on other sites
4 hours ago, b9k said:

other solution

#include <GuiSlider.au3>
#include <SendMessage.au3>
#include <WindowsConstants.au3>

$iPercent = 30 ; volume % (0-100)

$hWnd = WinGetHandle("SoundWire Server")
$hCtrl = ControlGetHandle($hWnd, "", "msctls_trackbar324")
_GUICtrlSlider_SetPos($hCtrl, (100 - $iPercent) * 655.35)
_SendMessage($hWnd, $WM_VSCROLL, 0, $hCtrl)

 

Share this post


Link to post
Share on other sites
19 hours ago, InnI said:
#include <GuiSlider.au3>
#include <SendMessage.au3>
#include <WindowsConstants.au3>

$iPercent = 30 ; volume % (0-100)

$hWnd = WinGetHandle("SoundWire Server")
$hCtrl = ControlGetHandle($hWnd, "", "msctls_trackbar324")
_GUICtrlSlider_SetPos($hCtrl, (100 - $iPercent) * 655.35)
_SendMessage($hWnd, $WM_VSCROLL, 0, $hCtrl)

 

Yo, that was what I was thinking when I posted here: a more general approach! Thank you all for your help!

Edited by b9k

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
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Luigi
      Greetings,
       
      Someone can help-me to translate this Python's code to AutoIt?
       
      Python (source: https://repl.it/repls/InstructiveDarkslategreyJackrabbit)
      str = 'age=12,name=bob,hobbies="games,reading",phrase="I\'m cool!"' key = "" val = "" dict = {} parse_string = False parse_key = True # parse_val = False for c in str: print(c) if c == '"' and not parse_string: parse_string = True continue elif c == '"' and parse_string: parse_string = False continue if parse_string: val += c continue if c == ',': # terminate entry dict[key] = val #add to dict key = "" val = "" parse_key = True continue elif c == '=' and parse_key: parse_key = False elif parse_key: key += c else: val+=c dict[key] = val print(dict.items()) Python's output:
      [('phrase', "I'm cool!"), ('age', '12'), ('name', 'bob'), ('hobbies', 'games,reading')] AutoIt
      #include-once #include <Array.au3> #include <StringConstants.au3> Global $opt $opt = "estado = """" , cep = """", idade=32, nome = ""Luismar"", campo=""campo = campo""" $opt = "age=12,name=bob,hobbies=""games,reading"",phrase=""I\'m cool!""" ConsoleWrite($opt & @LF) Local $arr = StringSplit($opt, "", $STR_CHRSPLIT) Local $key = "" Local $val = "" Local $dict = ObjCreate("Scripting.Dictionary") Local $parse_string = False Local $parse_key = True Local $c For $ii = 1 To $arr[0] $c = $arr[$ii] If $c == '"' And Not $parse_string Then $parse_string = True ContinueLoop ElseIf $c == """" And $parse_string Then $parse_string = False ContinueLoop EndIf If $parse_string Then $val &= $c ContinueLoop EndIf If $c = "," Then $dict.Add($key, $val) $key = "" $val = "" $parse_key = True ContinueLoop ElseIf $c == "=" And $parse_key Then $parse_key = False ElseIf $parse_key Then $key &= $c Else $val &= $c EndIf Next $dict.Add($key, $val) ; missing this line... For $each In $dict ConsoleWrite($each & " = " & $dict.Item($each) & @LF) Next AutoIt's output
      age=12,name=bob,hobbies="games,reading",phrase="I\'m cool!" age = 12 name = bob hobbies = games,reading  
      Best regards.
       
    • By Schuster
      Hey there,
      i need your help guys. I am working in the QA department of my company. A little part of or software produces hints (like little popups) which needs to be tested every release. I wrote scripts to trigger those hints and i also implemented the imagesearch.dll to find those hints on the screen. My goal now is it to let the machine work over night, so when i come back to work i only get a report which says 130/140 hints were found successfully. This already works, aslong as my pc is not locked, but i want/need to lock my pc because of security concerns.
      My general question. Is it possible to run my scripts on my locked PC and still find an image that i provide which will open sooner or later in the background?
       
      Thanks in advance
    • By nooneclose
      Good morning, I have been thinking about trying to make my Autoit script run in the background. I found out today that it is impossible due to the UIA and mouseclick functions that I use. However, while reading other posts about running Autoit scripts in the background I saw a reply mentioning how a script like mine might be able to run on a VM while still giving me the ability to work on my Host OS. Can someone confirm this? 
      Here is a link to the thread where I saw VM mentioned. 
      the person who mentioned it was @ViciousXUSMC 
    • By DigiBox
      Hello!
      Please help me with this small problem I've encountered while learning to make GUI.
      I'm not able to get the set slider values out of sliders and I can't figure out why.
      The slider value in the example is preset to 1, but whatever I set the slider to, it returns the value 3 when I click Apply and I havn't set any value to 3.
      Where is that 3 coming from?
       
      #include <SliderConstants.au3> #include <MsgBoxConstants.au3> #include <GUIConstantsEx.au3> Global $LRSlider Opt("GUIOnEventMode", 1) Global $Form1 = GUICreate("test slider", 200, 200, -1, -1) Global $LRSlider = GUICtrlCreateSlider(50, 50, 100, 20, $TBS_TOOLTIPS) GUICtrlSetLimit($LRSlider, 50, 1) GUICtrlSetData($LRSlider, 1) GUISetOnEvent($GUI_EVENT_CLOSE, "Exit1") Global $ApplyButton = GUICtrlCreateButton("APPLY", 100, 150, 89, 17) GUICtrlSetOnEvent($ApplyButton, "Apply") GUISetState(@SW_SHOW) Func Apply() GUICtrlRead($LRSlider) MsgBox(0, 0, $LRSlider) GUICtrlSetData($LRSlider, $LRSlider) EndFunc ;==>Apply Func Exit1() Exit EndFunc ;==>Exit1 While 1 Sleep(200) WEnd  
    • By AndyS01
      I want to create a slider that has values representing colors, like the slider on the _ChooseColor() GUI in the Misc.au3 UDF, but the max value for a slider is 32767.  
      Here is my test code:
      #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <SliderConstants.au3> #include <Misc.au3> $hGUI = GUICreate("Test", 100, 560) $BtnID = GUICtrlCreateButton("Choose", 10, 10, 50, 25) ;~ GUICtrlSetOnEvent($BtnID, "handle_choose_btn") $flags = BitOR($TBS_AUTOTICKS, $TBS_VERT) $iSliderID = GUICtrlCreateSlider(10, 50, 40, 420, $flags) $hSlider_hWnd = GUICtrlGetHandle($iSliderID) $iMaxVal = 32767 GUICtrlSetLimit($iSliderID, $iMaxVal, 0) ; change min/max value GUISetState() GUIRegisterMsg($WM_VSCROLL, "WM_V_Slider") While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit Case $GUI_EVENT_PRIMARYUP ToolTip("") case $BtnID handle_choose_btn() EndSwitch WEnd ; React to a slider movement Func WM_V_Slider($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam If $lParam = $hSlider_hWnd Then $iValue = GUICtrlRead($iSliderID) ConsoleWrite("+++: $iValue = " & $iValue & @CRLF) ToolTip(getRGB($iValue)) EndIf Return $GUI_RUNDEFMSG EndFunc ;==>WM_V_Slider ; Extract the RGB components from the color value Func getRGB($iColorVal) Local $hexstr, $b, $g, $r, $rgb $hexstr = StringFormat("%06X", $iColorVal) $r = StringMid($hexstr, 1, 2) $g = StringMid($hexstr, 3, 2) $b = StringMid($hexstr, 5, 2) $rgb = StringFormat("" & $iColorVal & " - rgb: %02s %02s %02s", $r, $g, $b) Return ($rgb) EndFunc ;==>getRGB Func handle_choose_btn() $color = _ChooseColor(2, 255, 0, $hGUI) ConsoleWrite("+++: $color = " & Hex($color, 8) & @CRLF) EndFunc ;==>handle_choose_btn  
×
×
  • Create New...