You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
201 lines
5.5 KiB
201 lines
5.5 KiB
3 years ago
|
#!/bin/bash -eu
|
||
|
|
||
|
# ---------------------------------------------------------
|
||
|
# Lazy Variables
|
||
|
__save() {
|
||
|
local name=$1
|
||
|
shift
|
||
|
declare -g $name="$*"
|
||
|
}
|
||
|
|
||
|
require() {
|
||
|
for name in $@; do
|
||
|
if [ -z "${!name+x}" ]; then
|
||
|
get_$name "__save $name" "require_for $name"
|
||
|
fi
|
||
|
done
|
||
|
}
|
||
|
|
||
|
shopt -s expand_aliases
|
||
|
alias greq='$2 '
|
||
|
alias gsave='$1 '
|
||
|
|
||
|
typeset -gA require_depends=()
|
||
|
|
||
|
invalidate() {
|
||
|
for name in $@; do
|
||
|
unset -v $name
|
||
|
if [ -n "${require_depends[$name]:-""}" ]; then
|
||
|
local tmp="${require_depends[$name]}"
|
||
|
unset -v require_depends[$name]
|
||
|
invalidate $tmp
|
||
|
fi
|
||
|
done
|
||
|
}
|
||
|
|
||
|
require_for() {
|
||
|
local self_name=$1
|
||
|
shift
|
||
|
require $@
|
||
|
for name in $@; do
|
||
|
require_depends[$name]="${require_depends[$name]-""} $self_name"
|
||
|
done
|
||
|
}
|
||
|
|
||
|
# ---------------------------------------------------------
|
||
|
# Lazy variables
|
||
|
get_ponymix_prog() {
|
||
|
gsave $(which ponymix 2>/dev/null)
|
||
|
}
|
||
|
|
||
|
get_pacmd_prog() {
|
||
|
# May be unavailable if only pulse clients installed
|
||
|
gsave $(which pacmd 2>/dev/null)
|
||
|
}
|
||
|
|
||
|
get_default_sink() {
|
||
|
gsave $(pactl info | grep 'Default Sink' | cut -d: -f2)
|
||
|
}
|
||
|
|
||
|
# There doesn't seem to be a better way to get a sink volume right now
|
||
|
get_pacmd_dump() {
|
||
|
greq pacmd_prog
|
||
|
[ -n "$pacmd_prog" ] || { echo "ERROR: \$pacmd_dump requires available pacmd which is part of the pulseaudio server package"; exit 44; }
|
||
|
gsave "$(pacmd dump)"
|
||
|
}
|
||
|
|
||
|
get_pacmd_default_sink_config() {
|
||
|
greq pacmd_dump default_sink
|
||
|
gsave "$(echo "$pacmd_dump" | grep "$default_sink")"
|
||
|
}
|
||
|
|
||
|
get_pacmd_default_volume() {
|
||
|
greq pacmd_default_sink_config
|
||
|
gsave $[$(echo "$pacmd_default_sink_config" | grep "set-sink-volume" | cut -d' ' -f3)]
|
||
|
}
|
||
|
|
||
|
get_default_volume_percent() {
|
||
|
greq ponymix_prog
|
||
|
if [ -n "$ponymix_prog" ]; then
|
||
|
gsave $($ponymix_prog get-volume)
|
||
|
else
|
||
|
greq pacmd_default_volume
|
||
|
gsave $[(100*$pacmd_default_volume+32768)/65535]
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
get_default_mute() {
|
||
|
greq ponymix_prog
|
||
|
if [ -n "$ponymix_prog" ]; then
|
||
|
$ponymix_prog is-muted && gsave yes || gsave no
|
||
|
else
|
||
|
greq pacmd_default_sink_config
|
||
|
gsave $(echo "$pacmd_default_sink_config" | grep "set-sink-mute" | cut -d' ' -f3)
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
# ---------------------------------------------------------
|
||
|
# Operations
|
||
|
do_vol() {
|
||
|
# Set default sink volume
|
||
|
require default_sink
|
||
|
local offset
|
||
|
case "$1" in
|
||
|
m|mute)
|
||
|
pactl set-sink-mute $default_sink true
|
||
|
;;
|
||
|
u|unmute)
|
||
|
pactl set-sink-mute $default_sink false
|
||
|
;;
|
||
|
t|toggle|toggle-mute)
|
||
|
pactl set-sink-mute $default_sink toggle
|
||
|
;;
|
||
|
\+) : ${offset:=+5%};&
|
||
|
\-) : ${offset:=-5%};&
|
||
|
*) : ${offset:=$1}
|
||
|
pactl set-sink-mute $default_sink false
|
||
|
pactl set-sink-volume $default_sink $offset
|
||
|
;;
|
||
|
esac
|
||
|
invalidate pacmd_dump default_volume_percent default_mute
|
||
|
}
|
||
|
|
||
|
do_notify() {
|
||
|
# Notification
|
||
|
if which dunstify >/dev/null 2>&1 && [ -n "`pgrep --ns $$ -u $(id -u) dunst`" ]; then
|
||
|
require default_sink default_volume_percent default_mute
|
||
|
dunst_id=6533319
|
||
|
if [ $default_mute = yes ]; then
|
||
|
icon=audio-volume-muted
|
||
|
text="Volume muted"
|
||
|
else
|
||
|
text="Volume $default_volume_percent%"
|
||
|
if [ $default_volume_percent -lt 35 ]; then
|
||
|
icon=audio-volume-low
|
||
|
elif [ $default_volume_percent -lt 75 ]; then
|
||
|
icon=audio-volume-medium
|
||
|
else
|
||
|
icon=audio-volume-high
|
||
|
fi
|
||
|
fi
|
||
|
if echo $default_sink | grep -q bluez; then
|
||
|
text="Bluetooth $text"
|
||
|
fi
|
||
|
bar_size=20
|
||
|
filled=$[(($bar_size * $default_volume_percent) + (100 / (2 * $bar_size)))/100]
|
||
|
bar=
|
||
|
if [ $filled -gt 0 ]; then
|
||
|
bar="`printf %.s● $(seq $filled)`"
|
||
|
fi
|
||
|
if [ $filled -lt $bar_size ]; then
|
||
|
bar="$bar`printf %.s○ $(seq $[$bar_size-$filled])`"
|
||
|
fi
|
||
|
dunstify -a "PA Volume" -u low -i $icon -r $dunst_id "$text" "$bar"
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
do_print() {
|
||
|
require default_sink default_volume_percent default_mute
|
||
|
[ $default_mute = yes ] && muted=muted || muted=unmuted
|
||
|
echo "$default_sink $default_volume_percent% $muted"
|
||
|
}
|
||
|
|
||
|
# ---------------------------------------------------------
|
||
|
# Main
|
||
|
|
||
|
while [ $# -gt 0 ]; do
|
||
|
verb=$1; shift
|
||
|
|
||
|
case $verb in
|
||
|
v|vol|volume)
|
||
|
do_vol "$1"; shift
|
||
|
do_notify
|
||
|
do_print
|
||
|
;;
|
||
|
set-volume)
|
||
|
do_vol "$1"; shift
|
||
|
;;
|
||
|
n|notify)
|
||
|
do_notify
|
||
|
;;
|
||
|
p|print)
|
||
|
do_print
|
||
|
;;
|
||
|
get-default-sink)
|
||
|
require default_sink
|
||
|
echo $default_sink
|
||
|
;;
|
||
|
*)
|
||
|
echo "Available verbs:"
|
||
|
echo " set-volume <[+-]n%|mute|unmute|toggle> Change default sink volume"
|
||
|
echo " notify Display a notification with current default sink volume"
|
||
|
echo " print Print the default sink and it's volume"
|
||
|
echo " volume <see set-volume> Short for \"set-volume <...> notify print\""
|
||
|
echo " get-default-sink Print default sink name"
|
||
|
echo
|
||
|
echo " verbs can be chained by separating them with space. Note that some have additional arguments"
|
||
|
exit 1
|
||
|
;;
|
||
|
esac
|
||
|
done
|