As I started to use the i3 window manager I wanted to have a visual feedback on sound volume change events. Usually it's done by a daemon that binds to specific keyboard combinations to adjust volume and to send notifications to a notify daemon. In xfce this is done by the xfce4-volumed. I should also point here to other lightweight volume daemons like volnoti or pa-applet. Without a dedicated daemon it is also pretty much simple to handle sound volume keys by a simple bash script which is bind to specific keyboard combinations.
I've seen several examples of such a script the only problem with them was that notify-send command used to send notifications still does not return an id of a notification shown which results in several notification popups floating at the same time. As it's described here one could patch notify-send command so that it will return an id if asked but I came up with an easier solution using python-notify lib. Until patched notify-send is available in an official repository one could use this pynotify workaround. Here is an example of pynotify usage in a script to adjust sound volume:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | $ cat bin /volume_notify .sh #!/bin/bash # $0 - icon_name, $2 - volume, $3 - id print_cmd() { cat <<HEREDOC import pynotify pynotify.init( "volume_notif.py" ) notif=pynotify.Notification( "Volume" , "" , "$1" ) notif.set_hint_int32( "value" ,$2) notif.set_property( "id" , $3) notif.show() print notif.get_property( "id" ) HEREDOC } step=5 id_file= "/tmp/notify_volume.id" icon_high= "/usr/share/icons/elementary-xfce/notifications/48/audio-volume-high.png" icon_low= "/usr/share/icons/elementary-xfce/notifications/48/audio-volume-low.png" icon_medium= "/usr/share/icons/elementary-xfce/notifications/48/audio-volume-medium.png" icon_muted= "/usr/share/icons/elementary-xfce/notifications/48/audio-volume-muted.png" icon_off= "/usr/share/icons/elementary-xfce/notifications/48/audio-volume-off.png" case $1 in up) amixer -q set Master $step+ ;; down) amixer -q set Master $step- ;; toggle) #pactl list sinks|grep -q Mute:.yes;pactl set-sink-mute 0 ${PIPESTATUS[1]} ;; # amixer needs -D pulse switch as a workaround for the pulseaudio # check http://goo.gl/4z4U6R amixer -q -D pulse set Master toggle ;; *) echo "Usage: $0 up/down/toggle" exit 1 ;; esac muted=$(amixer get Master | tail -n1 | sed -nr 's/.*\[([a-z]+)\].*/\1/p' ) volume=$(amixer get Master | tail -n1 | sed -nr 's/[^\[]*.([^%]*).*/\1/p' ) if ((volume==0)); then icon=$icon_off elif ((volume<34)); then icon=$icon_low elif ((volume<67)); then icon=$icon_medium else icon=$icon_high fi if [[ $muted == "off" ]]; then icon=$icon_muted fi id =$( cat $id_file 2> /dev/null ); id =${ id :-0} idn=$(python -c "$(print_cmd $icon $volume $id)" ) (($idn != $ id )) && echo "$idn" > "$id_file" exit 0 |
ps: lines 42-43 could be optimized to this:
1 2 3 | val=$(amixer get Master | tail -n1 | sed -nr 'h;s/[^\[]*.([^%]*).*/\1/p;g;s/.*\[([a-z]+)\].*/\1/p' ) muted=${val #*$'\n'} volume=${val%$ '\n' *} |
Edit 2020.11:
The script above uses older python lib which isn't available any longer. Additionally it controls amixer but pulseaudio should be used instead. Here is an updated version:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | $ cat bin /volume_notify_pa .sh #!/bin/bash # this script requires python3-notify2 lib to be installed first STEP= '5%' # some sound cards could have different MIN/MAX values # this isn't implemented yet as I can't test it MIN_VOLUME=0 MAX_VOLUME=65536 # file where notification ids are stored ID_FILE= "/tmp/notify_volume.id" # $1 - icon_name, $2 - volume, $3 - id print_cmd() { cat <<HEREDOC import notify2 notify2.init( "volume_notify.py" ) notif=notify2.Notification( "Volume" , "" , "$1" ) notif.set_hint_int32( "value" ,$2) notif. id = $3 notif.show() print(notif. id ) HEREDOC } # input parameters are: $1 - volume, $3 - muted status send_notification() { local icon id idn local volume_raw=$1 local muted=$2 local volume=$(( (100*(volume_raw-MIN_VOLUME))/(MAX_VOLUME-MIN_VOLUME) )) if ((volume==0)); then icon=$icon_off elif ((volume<34)); then icon=$icon_low elif ((volume<67)); then icon=$icon_medium else icon=$icon_high fi if [[ "$muted" == "yes" ]]; then icon=$icon_muted fi id =$( cat $ID_FILE 2> /dev/null ); id =${ id :-0} idn=$(python3 -c "$(print_cmd " $icon " " $volume " " $ id ")" ) (( "$idn" != "$id" )) && echo "$idn" > "$ID_FILE" } get_volume() { local VOLHEX=$(pacmd dump | awk '/^set-sink-volume/{printf("%s", $3)}' ) [ -n "$VOLHEX" ] || { echo "$MIN_VOLUME" return } printf '%d' $VOLHEX } # returns 'yes' or 'no' get_muted() { MUTED=$(pacmd dump | awk '/set-sink-mute/{print $3}' ) printf "%s" "$MUTED" } icon_high= "audio-volume-high" icon_low= "audio-volume-low" icon_medium= "audio-volume-medium" icon_muted= "audio-volume-muted" icon_off= "audio-volume-off" SINK=$(pactl info | awk '/Default Sink/{print $3}' ) [ -n "$SINK" ] || exit 1 case $1 in up) pactl set -sink-volume "$SINK" "+$STEP" [ "$(get_volume)" -gt $MAX_VOLUME ] && pactl set -sink-volume "$SINK" "$MAX_VOLUME" ;; down) pactl set -sink-volume "$SINK" "-$STEP" [ "$(get_volume)" - le $MIN_VOLUME ] && pactl set -sink-volume "$SINK" "$MIN_VOLUME" ;; toggle) MUTED=$(pacmd dump | awk '/set-sink-mute/{print $3}' ) if [ "yes" = "$MUTED" ]; then pactl set -sink-mute "$SINK" 0 else pactl set -sink-mute "$SINK" 1 fi ;; *) echo "Usage: $0 up/down/toggle" exit 1 ;; esac send_notification "$(get_volume)" "$(get_muted)" exit 0 |
1 comment:
Thank you!!
Here is a modded version that worked for me..
$ cat volume.sh
#!/bin/bash
# $0 - icon_name, $2 - volume, $3 - id
print_cmd()
{
cat </dev/null);id=${id:-0}
idn=$(python2 -c "$(print_cmd $icon $volume $id)")
(($idn != $id)) && echo "$idn" > "$id_file"
exit 0
Post a Comment