You are not logged in.
I run Awesome as my WM, and I've created a script for managing my audio devices with shortcut keys.
I'm running into a small annoyance, however, in that the reported volume lags behind the actual volume. The script changes the volume of my speakers in 5% increments, however the reported volume (via notify-send) is the volume BEFORE the change. So obviously the variable contents (of SPK_VOL specifically) are being executed before the function that it's called from. And now that I think about it, the same could be said of IS_MUTED_SPK and IS_MUTED_MIC, as I have to reverse their readings in the later if statement.
I can force it to work correctly by moving the variable into the respective function, after the line where the volume is changed, but this results in code duplication, and I think there has to be a cleaner way of doing it than that.
#!/bin/bash
set +x
#trap read debug
# Interfaces
MIC_FACE="alsa_input.pci-0000_00_1b.0.analog-stereo"
#SPK_FACE="alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1" # PG279Q
SPK_FACE="alsa_output.pci-0000_01_00.1.hdmi-stereo-extra2" # B326HK
# Functions
MUTE_MIC() ( pactl set-source-mute $MIC_FACE toggle;
if [ $IS_MUTED_MIC = no ]
then
notify-send "Microphone" "Muted"
else
notify-send "Microphone" "Unmuted"
fi )
FIX_MIC() ( pactl set-source-volume $MIC_FACE 6554;
notify-send "Microphone" "Volume set to $VOL_MIC" )
LOWR_SPK() ( pactl set-sink-volume $SPK_FACE -5%;
sleep 0.5;
notify-send "Monitor Speakers" "Volume set to $VOL_SPK" )
RISE_SPK() ( pactl set-sink-volume $SPK_FACE +5%;
notify-send "Monitor Speakers" "Volume set to $VOL_SPK" )
MUTE_SPK() ( pactl set-sink-mute $SPK_FACE toggle;
if [ $IS_MUTED_SPK = no ]
then
notify-send "Monitor Speakers" "MUTED"
else
notify-send "Monitor Speakers" "UNMUTED"
fi )
# Mute tests
# grep -A 6 $***_FACE
IS_MUTED_MIC=`pactl list sources|sed -n '/'$MIC_FACE'/,/Mute/p' -|grep Mute|awk '{print $2}' -`
IS_MUTED_SPK=`pactl list sinks|sed -n '/'$SPK_FACE'/,/Mute/p' -|head -10|grep Mute|awk '{print $2}' -`
# Volume tests
VOL_MIC=`pactl list sources|sed -n '/'$MIC_FACE'/,/Base Volume/p' -|grep "Base Volume"|awk '{print $5}' -`
VOL_SPK=`pactl list sinks|sed -n '/'$SPK_FACE'/,/Base Volume/p' -|grep -m1 "Volume"|awk '{print $5}' -`
# Process input commands
case $1 in
micmute)MUTE_MIC;;
miclkvl)FIX_MIC;;
spkmute)MUTE_SPK;;
spkvlup)RISE_SPK;;
spkvldn)LOWR_SPK;;
*)echo "No valid command specified";
notify-send "Audio Control: Error" "No valid command specified";;
esac
Last edited by RankoKohime (2016-04-10 04:26:55)
Offline
So obviously the variable contents (of SPK_VOL specifically) are being executed before the function that it's called from.
Yes, they are. That's how variables work. VOL_SPK for example is set only once on line 40. When the script is run, all the functions are read (but not executed) the variables are set (around line 40) then you call a function and use the values previously asigned to the variable.
What it looks like you want to do is save that command line on line 40 to a vaiable, then "eval" that variable. This would work - though there is a much better approach - but as an example, the following would do what you intended:
RISE_SPK() {
pactl set-sink-volume $SPK_FACE +5%;
notify-send "Monitor Speakers" "Volume set to $(eval $VOL_SPK)"
}
...
VOL_SPK="pactl list sinks|sed -n '/'$SPK_FACE'/,/Base Volume/p' -|grep -m1 "Volume"|awk '{print $5}' -"
...
although some escaping would likely need to be done to the quotes on the VOL_SPK variable. I have not tested this specific code as this really isn't the best way to do this. It's better to use another function:
VOL_SPK() { pactl list sinks|sed -n '/'$SPK_FACE'/,/Base Volume/p' -|grep -m1 "Volume"|awk '{print $5}' - }
RISE_SPK() {
pactl set-sink-volume $SPK_FACE +5%;
notify-send "Monitor Speakers" "Volume set to $(VOL_SPK)"
}
There are also many other approaches - look around at the scripting threads, many people have written efficient volume control scripts.
Also, sed + grep + awk = awk. I don't have pactl to test, but that command line on line 40 should be equivalent to the following:
pactl list sinks | awk '/'$SPK_FACE'/{while (!match($0,"Base Volume")) getline; print $5; exit;}'
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
There are also many other approaches - look around at the scripting threads, many people have written efficient volume control scripts.
Also, sed + grep + awk = awk. I don't have pactl to test, but that command line on line 40 should be equivalent to the following:
pactl list sinks | awk '/'$SPK_FACE'/{while (!match($0,"Base Volume")) getline; print $5; exit;}'
This has definitely given me a few ideas, and some insight into awk, (which I still haven't studied up on nearly as much I'd like, apparently), however, notify-send being the picky little prat it is, doesn't pick up on either the function call, or the eval. It doesn't give an error, either, it just ignores it entirely.
Last edited by RankoKohime (2016-04-03 00:39:22)
Offline
notify-send can be as picky as it wants, it has no influence on this. Notify-send doesn't interpet those variables, the shell does. It notify send isn't showing anything there then something is wrong elsewhere. You can replace the notify send command with "echo" and just run the script from the command line for some testing.
I'd do some testing, but I don't use pulse-audio.
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
notify-send can be as picky as it wants, it has no influence on this. Notify-send doesn't interpet those variables, the shell does. It notify send isn't showing anything there then something is wrong elsewhere. You can replace the notify send command with "echo" and just run the script from the command line for some testing.
I'd do some testing, but I don't use pulse-audio.
Well, it picks up the variable, $SPK_VOL, but doesn't pick up the function call, $(SPK_VOL) or the eval $(eval $SPK_VOL). It simply doesn't output anything where the percentage should be.
I've tested to make sure the variable/function does give output, and it does, both before (with sed|grep|awk) and after (just awk).
Last edited by RankoKohime (2016-04-04 05:51:23)
Offline
You could try something like this with the function then:
RISE_SPK() {
pactl set-sink-volume $SPK_FACE +5%;
VOL="$(VOL_SPK)"
echo $VOL
notify-send "Monitor Speakers" "Volume set to $VOL"
}
The echo $VOL is there just to test whether VOL is actually set to anything.
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
You could try something like this with the function then:
RISE_SPK() { pactl set-sink-volume $SPK_FACE +5%; VOL="$(VOL_SPK)" echo $VOL notify-send "Monitor Speakers" "Volume set to $VOL" }
The echo $VOL is there just to test whether VOL is actually set to anything.
Several rounds of editing later, and after incorporating the change you mentioned, I've got my script working.
#!/bin/bash
set +x
#trap read debug
# v 1.0, built for yggdrasil-3
# This script handles a variety of different audio configurations, as requested by the window manager (Awesome)
# Interfaces
# These functions should automatically adjust the interface variable if the interface changes.
# This is especially a problem with SPK_FACE is it will change when the monitor is swapped.
MIC_FACE=alsa_input.pci-0000_00_1b.0.`pactl list cards|awk -F ":" '/alsa_card.pci-0000_00_1b.0/{while (!match($0,"Active Profile")) getline;print $4;exit;}'`
SPK_FACE=alsa_output.pci-0000_01_00.1.`pactl list cards|awk -F ":" '/alsa_card.pci-0000_01_00.1/{while (!match($0,"Active Profile")) getline;print $3;exit;}'`
# Functions
MUTE_MIC()
(
pactl set-source-mute $MIC_FACE toggle;
if [ $IS_MUTED_MIC = no ]
then
notify-send "Microphone" "Is Muted"
else
notify-send "Microphone" "Is Unmuted"
fi
)
FIX_MIC()
(
pactl set-source-volume $MIC_FACE 6554;
notify-send "Microphone" "Volume set to $(VOL_MIC)"
)
SWAP_SPK()
(
pactl # In progress
notify-send "Monitor Speakers" "Switched output to: $SPK_FACE"
)
LOWR_SPK()
(
pactl set-sink-volume $SPK_FACE -5%;
notify-send "Monitor Speakers" "Volume set to $(VOL_SPK)"
)
RISE_SPK()
(
pactl set-sink-volume $SPK_FACE +5%;
notify-send "Monitor Speakers" "Volume set to $(VOL_SPK)"
)
MUTE_SPK()
(
pactl set-sink-mute $SPK_FACE toggle;
if [ $IS_MUTED_SPK = no ]
then
notify-send "Monitor Speakers" "MUTED"
else
notify-send "Monitor Speakers" "UNMUTED"
fi
)
# Mute tests
IS_MUTED_MIC=`pactl list sources|awk '/'$MIC_FACE'/{while (!match($0,"Mute")) getline;print $2;exit;}'`
IS_MUTED_SPK=`pactl list sinks|awk '/'$SPK_FACE'/{while (!match($0,"Mute")) getline;print $2;exit;}'`
# Volume tests
VOL_MIC()
(
pactl list sources|awk '/'$MIC_FACE'/{while (!match($0,"Volume")) getline; print $5; exit; }'
)
VOL_SPK()
(
pactl list sinks|awk '/'$SPK_FACE'/{while (!match($0,"Volume")) getline; print $5; exit; }'
)
# Process input commands
case $1 in
micmute)MUTE_MIC;;
miclkvl)FIX_MIC;;
spkmute)MUTE_SPK;;
spkvlup)RISE_SPK;;
spkvldn)LOWR_SPK;;
spkswap)SWAP_SPK;;
*)echo "No valid command specified";
notify-send "Audio Control: Error" "No valid command specified";;
esac
Offline