#!/usr/bin/env bash
# Volume / mic control with a dunst OSD.  usage: volume up|down|mute|micmute|set <n>
set -uo pipefail

STEP="${VOLUME_STEP:-5}"
MAX="${VOLUME_MAX:-100}"
SINK="@DEFAULT_AUDIO_SINK@"
SOURCE="@DEFAULT_AUDIO_SOURCE@"
ID=2593   # fixed notification id => the OSD replaces itself instead of stacking

have() { command -v "$1" >/dev/null 2>&1; }
have wpctl || { echo "wpctl (wireplumber) not found" >&2; exit 1; }

get_volume() {
  wpctl get-volume "$SINK" | awk '{printf "%d", $2 * 100}'
}
is_muted() {
  wpctl get-volume "$SINK" | grep -q MUTED
}

osd() {
  have dunstify || return 0
  local icon="$1" text="$2" value="$3"
  dunstify -a osd -u low -r "$ID" -h "int:value:$value" -i "$icon" "$text"
}

case "${1:-}" in
  up)
    wpctl set-mute "$SINK" 0
    wpctl set-volume -l "$(awk "BEGIN{print $MAX/100}")" "$SINK" "${STEP}%+"
    ;;
  down)
    wpctl set-mute "$SINK" 0
    wpctl set-volume "$SINK" "${STEP}%-"
    ;;
  set)
    wpctl set-volume -l "$(awk "BEGIN{print $MAX/100}")" "$SINK" "${2:?need a percentage}%"
    ;;
  mute)
    wpctl set-mute "$SINK" toggle
    ;;
  micmute)
    wpctl set-mute "$SOURCE" toggle
    if wpctl get-volume "$SOURCE" | grep -q MUTED; then
      osd microphone-sensitivity-muted "Microphone muted" 0
    else
      osd microphone-sensitivity-high "Microphone live" 100
    fi
    exit 0
    ;;
  ""|-h|--help)
    echo "usage: volume up|down|mute|micmute|set <percent>"; exit 0 ;;
  *)
    echo "unknown action: $1" >&2; exit 2 ;;
esac

vol="$(get_volume)"
if is_muted; then
  osd audio-volume-muted "Muted" 0
elif   (( vol >= 66 )); then osd audio-volume-high   "Volume  ${vol}%" "$vol"
elif   (( vol >= 33 )); then osd audio-volume-medium "Volume  ${vol}%" "$vol"
else                         osd audio-volume-low    "Volume  ${vol}%" "$vol"
fi

# Nudge polybar so the bar updates instantly rather than on its 5s poll
pkill -RTMIN+1 polybar 2>/dev/null || true
