#!/bin/sh default_sink_name() { pactl info | sed -ne 's/^Default Sink: //p' } die() { printf 'Error: %s\n' "$1" >&2 exit 1 } sink=$(default_sink_name) || die "could not determine default sink" set_volume() # uses $sink { pactl set-sink-volume "$sink" "$1"% } mute() # uses $sink { case "$1" in toggle|'') pactl set-sink-mute "$sink" toggle ;; on|1) pactl set-sink-mute "$sink" 1 ;; off|0) pactl set-sink-mute "$sink" 0 ;; esac } show_volume_line() { show_sink_line Volume; } show_mute_line() { show_sink_line Mute; } show_sink_line() # uses $sink { local wanted_line="$1" want_next= pactl list sinks | while read line; do case "$line" in "Name: $sink") want_next=1 ;; 'Name: '*) want_next= ;; "${wanted_line}: "*) [ "$want_next" ] || continue echo "$line" break ;; esac done } show_volume_number() # uses $sink { set -- $(show_volume_line) local total=0 num=0 p for p; do case "$p" in *%) total=$((total + ${p%%%})) num=$((num + 1)) ;; esac done if [ "$num" -gt 0 ]; then echo $(( total / num )) fi } show_mute_bool() { set -- $(show_mute_line) echo "$2" } show_status() { volume=$(show_volume_number) case "$(show_mute_bool)" in "yes") printf '%s (muted)\n' "$volume" ;; "no") echo "$volume" ;; esac } case "$1" in [0-9]*) set_volume "$1" ;; [-+*/][0-9]*) set_volume $(( $(show_volume_number) $1 )) ;; '') show_status ;; --mute=*) mute "${1#--mute=}" ;; --mute) mute "$2" ;; *) die 'usage' ;; esac