#!/usr/bin/env bash
# Default sink / source volume for the popup.  Refreshes on PipeWire events
# (pactl subscribe on the pipewire-pulse socket) and every 30 s.
#
#   volume                 status loop (deflisten)
#   volume setvol SINK|SOURCE PERCENT
#   volume mute   SINK|SOURCE

icons=("󰕿" "󰖀" "󰕾")

level() { # prints "<percent> <muted>"
  wpctl get-volume "@DEFAULT_AUDIO_$1@" 2>/dev/null \
    | awk '{ printf "%d %s\n", $2 * 100 + 0.5, ($0 ~ /MUTED/) ? "true" : "false" }'
}

sink_name() {
  wpctl inspect @DEFAULT_AUDIO_SINK@ 2>/dev/null \
    | awk -F'"' '/node\.nick/ { n = $2 } /node\.description/ { d = $2 } END { print (n != "" ? n : d) }'
}

state() {
  local vol muted mic mic_muted icon mic_icon lvl
  read -r vol muted < <(level SINK)
  read -r mic mic_muted < <(level SOURCE)
  vol=${vol:-0} muted=${muted:-false} mic=${mic:-0} mic_muted=${mic_muted:-false}
  lvl=$((vol >= 67 ? 2 : vol >= 34 ? 1 : 0))
  if [[ $muted == true ]]; then icon="󰝟"; else icon=${icons[$lvl]}; fi
  if [[ $mic_muted == true ]]; then mic_icon="󰍭"; else mic_icon="󰍬"; fi
  printf '{"icon":"%s","percent":%d,"sink_muted":%s,"mic_icon":"%s","microphone":%d,"source_muted":%s,"sink":"%s"}' \
    "$icon" "$vol" "$muted" "$mic_icon" "$mic" "$mic_muted" "$(jstr "$(sink_name)")"
}

refresh() { emit "$(state)"; }
_pw_events() { pactl subscribe 2>/dev/null | grep --line-buffered -E "on (sink|source|server) "; }

case ${1:-} in
  mute) wpctl set-mute "@DEFAULT_AUDIO_$2@" toggle ;;
  setvol) wpctl set-volume -l 1.0 "@DEFAULT_AUDIO_$2@" "${3%.*}%" ;;
  *)
    refresh
    mux_init
    mux_add _pw_events
    mux_tick 30
    mux_loop refresh
    ;;
esac
