change volume, mute, etc windows audio mixer via an external app

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
thrive4
Posts: 70
Joined: Jun 25, 2021 15:32

change volume, mute, etc windows audio mixer via an external app

Post by thrive4 »

Is essence change, the master channel aka 'Speakers'
or a specific channel (per app) as well 'system sounds',
volume or mute state with a helper app svcl created by
Nirsoft.

Pre requisite:
download svcl.exe:
https://www.nirsoft.net/utils/sound_vol ... _line.html
and place svcl.exe in the same folder as the compiled app

Create a batchfile 'svcl.bat' in the same dir as
the compiled code with:

Code: Select all

':: current dir %cd%
'%cd%\svcl.exe /scomma > %cd%\mixer.tmp
The batch file is actually only needed to get the state
of the mixer and the active channels.

Code: Select all

' manipulate windows mixer
' using svcl.exe by nirsoft download @
' https://www.nirsoft.net/utils/sound_volume_command_line.html 
' for fb by thrive4 2022

' create a svcl.bat with content:
':: current dir %cd%
'%cd%\svcl.exe /scomma > %cd%\mixer.tmp

#include "windows.bi"

dim filename    as string
dim filearg     as string
dim dummy       as string
dim needle      as string
Dim f           As integer
dim cnt         as integer
dim fieldnr     as integer

' use createprocess to hide console
function launchapp(filename as string, filearg as string) as boolean
    dim as integer res
    dim as string  tfn
    dim as PROCESS_INFORMATION pi
    dim as STARTUPINFO si
    si.cb=Len(si)
    tfn  = chr(34) & filename & chr(34)
        tfn += " " & filearg
        res=CreateProcess(_
                NULL,_
                tfn,_ 
                NULL,_
                NULL,_
                NULL,_
                NORMAL_PRIORITY_CLASS or CREATE_NO_WINDOW,_
                NULL,_
                NULL,_
                @si,_
                @pi)
        res=WaitForSingleObject(pi.hProcess,5000)
        if pi.hProcess <> null then
            closehandle(pi.hProcess)
            closehandle(pi.hThread)
        end if
    return true
end function

' create mixer.tmp via bat
' note > (pipe) in file argument causes issues 
launchapp(exepath + "\svcl.bat", exepath)
' alternative
'Exec(exepath + "\svcl.bat", "")

' parse mixer.tmp for sepecific channel / app
filename    = "mixer.tmp"
needle      = "xmplay.exe"
cnt         = 1
fieldnr     = 1
dummy       = ""
f           = FreeFile

Open filename For input As #f
do until eof(f)
    line input #f, dummy
    if instr(dummy, needle) > 0 then
        do
            if instr(fieldnr, dummy, ",") > 0 then                
                cnt += 1
                fieldnr = instr(fieldnr + 1, dummy, ",") 
            end if
        loop until cnt > 10
        dummy = mid(dummy, fieldnr + 1)
        dummy = mid(dummy, 1, instr(dummy, "%") - 1)
        print dummy
    end if
loop
if fieldnr = 1 then
    print needle + " not found!"
else
    ' example mute specific channel
    print "mute " + needle
    launchapp(exepath + "\svcl.exe", "/mute " + chr$(34) + needle + chr$(34))
end if


' alter master volume
dim mute as boolean  = false
' todo get inital mute state for now force to false
Exec(exepath + "\svcl.exe", "/Unmute Speakers")
Do
	Dim As String key = UCase(Inkey)
    ' ascii interface
	Locate 1, 1
    ' basic interaction
    Print "open windows volume mixer for visual feedback"
    Print "press m     to mute and unmute master volume"
    Print "press -     to reduce   volume"
    Print "press +     to increase volume"
    Print "press esc   to quit"
    Print

	Select Case key
        Case "M"
            ' mute / unmute
            if mute then
                Exec(exepath + "\svcl.exe", "/Unmute Speakers")
                mute = false
                print "unmute            "
            else
                Exec(exepath + "\svcl.exe", "/Mute Speakers")
                mute = true
                print "mute              "
            end if
        Case "-"
            ' decrease volume
            Exec(exepath + "\svcl.exe", "/ChangeVolume Speakers -5")
            print "decrease master volume"
        Case "+"
            ' increase volume
            Exec(exepath + "\svcl.exe", "/ChangeVolume Speakers 5")
            print "increase master volume"
        Case Chr(27)
            Exit Do
	End Select
	Sleep(30)
Loop

' mute / unmute
'svcl.exe /Unmute "Speakers" 
'svcl.exe /Mute "Speakers" 
' set specific volume
'svcl.exe /SetVolume "chrome.exe" 50 
'svcl.exe /Switch "vlc.exe" (toggles mute)

sleep
end
usage compile and run to alter
volume or mute state master volume / 'speakers' channel
and / or alter:
needle = "xmplay.exe"
to a specific app to mute the channel of the app.

notes:
A more formal route would be
https://docs.microsoft.com/en-us/window ... audio-apis
examples:
viewtopic.php?p=154061&hilit=MixerGetNumDevs#p154061
https://www.qsl.net/i2phd/mixer/index.html
I gave it a whirl but setting it up is well above my pay grade...

a relatively close unix version to svcl is:
https://www.systutorials.com/docs/linux/man/1-amixer/
ALSA amixer

If you want svcl in a specific dir, other then the compiled app
alter the batch to:
%1\svcl.exe /scomma > %1\mixer.tmp

and alter the code to pass the folder for example like this:
launchapp(exepath + "\tools\svcl.bat", exepath + "\tools)
or where the batch file is not needed
'Exec(exepath + "\tools\svcl.exe", "/Unmute " + chr$(34) + channel + chr$(34))
Last edited by thrive4 on Jun 19, 2022 9:12, edited 2 times in total.
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: change volume, mute, etc windows audio mixer

Post by D.J.Peters »

Or you can use the mixer API: viewtopic.php?f=7&t=10579 but be aware this code is old and must be changed if the build target is 64-bit !

Joshy
Post Reply