#!/usr/bin/env bash volicons=("󰕿" "󰖀" "󰕾") vol() { wpctl get-volume @DEFAULT_AUDIO_"$1"@ | awk '{print int($2*100)}'; } ismuted() { wpctl get-volume @DEFAULT_AUDIO_"$1"@ | rg -qi muted; echo -n $?; } setvol() { wpctl set-volume @DEFAULT_AUDIO_"$1"@ "$(awk -v n="$2" 'BEGIN{print n/100}')"; } setmute() { wpctl set-mute @DEFAULT_AUDIO_"$1"@ toggle; } gen_output() { percent=$(vol "SINK") lvl=$(awk -v n="$percent" 'BEGIN{print int(n/34)}') sink_muted=$(ismuted "SINK") source_muted=$(ismuted "SOURCE") sink=$(wpctl inspect @DEFAULT_AUDIO_SINK@ 2>/dev/null | grep -m1 'node\.nick' | sed 's/.*= "\(.*\)"/\1/') [ "$sink_muted" = 0 ] && icon="󰝟" || icon="${volicons[$lvl]}" [ "$source_muted" = 0 ] && mic_icon="󰍭" || mic_icon="󰍬" printf '{"icon":"%s","percent":%s,"sink_muted":%s,"mic_icon":"%s","microphone":%s,"source_muted":%s,"sink":"%s"}\n' \ "$icon" "$percent" "$([ "$sink_muted" = 0 ] && echo true || echo false)" \ "$mic_icon" "$(vol SOURCE)" "$([ "$source_muted" = 0 ] && echo true || echo false)" "$sink" } case "$1" in mute) setmute "$2" ;; setvol) setvol "$2" "$3" ;; *) gen_output tmp=$(mktemp -d) pipe="$tmp/vol-events" mkfifo "$pipe" trap 'rm -rf "$tmp"; kill 0 2>/dev/null' EXIT INT TERM # 2s polling fallback (while true; do sleep 2; echo poll; done) > "$pipe" & # PipeWire property-change events (fires on mute/volume change) (pw-cli -m 2>/dev/null | grep --line-buffered "changed") > "$pipe" & while IFS= read -r _ < "$pipe"; do gen_output done ;; esac