Jump to content
b9k

Automating SoundWire Server's Master Volume slider

Recommended Posts

b9k
Posted (edited)

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
b9k

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
Xandy
Posted (edited)

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
b9k
Posted (edited)

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
b9k
Posted (edited)

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
Earthshine

I don't see your code posted anywhere


My resources are limited. You must ask the right questions

 

Share this post


Link to post
Share on other sites
b9k
Posted (edited)

@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
Xandy
Posted (edited)

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
b9k
Posted (edited)

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
Xandy
Posted (edited)

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
b9k
Posted (edited)

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
InnI

@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")

 

  • Like 1

Share this post


Link to post
Share on other sites
b9k
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
b9k
Posted (edited)
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

  • Similar Content

    • nacerbaaziz
      By nacerbaaziz
      Hi guys
      I have a question about the slider  controle
      There is a problem with screen readers, wen we Using a screen reader We usually move between GUI controls using the tab key.
      But when you create a slider , beside to it there are  buttons and check boxes or any other controls, When I move between the GUI controls using the tab key I can not find the slider.
      But if it were alone in the window, I would find it normally.
      Is there a solution to Solve this problem please?
      This is the code i tried
      #include <GUIConstantsEx.au3>
      #include <WindowsConstants.au3>
      #include <MsgBoxConstants.au3>
      #include <SliderConstants.au3>
      main()
      Func main()
          GUICreate("slider", 200, 200, -1, -1)
      GUICtrlCreateGroup("slider", 10, 10, 240, 50)
          Local $idSlider1 = GUICtrlCreateSlider(50, 30, 200, 20, BitOr($TBS_DOWNISLEFT, $TBS_BOTH))
          GUICtrlSetLimit(-1, 100, 0)
      ;GUIStartGroup("")
          Local $idButton = GUICtrlCreatebutton("Value?", 75, 70, 70, 20)
          GUISetState(@SW_SHOW)
          GUICtrlSetData($idSlider1, 10)
      while 1
      switch GUIGetMsg()
      case $GUI_EVENT_CLOSE
      exit
      case $idButton
                  MsgBox($MB_SYSTEMMODAL, "slider1", GUICtrlRead($idSlider1))
      endSwitch
      Wend
      EndFunc
      [Click and drag to move]
       
       
    • lenclstr746
      By lenclstr746
      HELLO GUYS
      I'm a work on a background see and click bot project 
      I can complete it if your help me
      (using imagesearch , gdi+ and  fastfind)
    • TheAutomator
      By TheAutomator
      Is this better to check a variable before you assign it to a value that could be the same?
      for example:
      local $EmptyLog = false func WriteLog($text) _guictrledit_appendtext($log, ($EmptyLog ? @CRLF : $empty) & $text) If $EmptyLog Then $EmptyLog = False endfunc or does AutoIt behind the scenes already check this?
      i guess overwriting memory with the same value over and over again is not good if you can prevent this with a check?
    • xEviiLx
      By xEviiLx
      I'm trying to read value of a base pointer + offset.
      With only address I can easily the value but with base addres (pointer) I really don't know how I can do that.
       
    • ur
      By ur
      When we run our exe from any service or through any background process, it won't interact with the applications running in the foreground, I mean launched when the user is logged in or in GUI mode.
       
      Let's say, the onedrive sync app can't be detected from the exe we created and running it in background.

      I tried both options below.

       
      Any Idea how to interact with foreground processes using AuotIT code.

      Other than telling to launch the exe also in foreground.
×