#!/usr/bin/env bash
set -euo pipefail

usage() {
  cat <<'USAGE'
Usage: ./set-pipewire-latency.sh COMMAND [QUANTUM] [RATE]

Commands:
  status          Show current PipeWire clock/quantum settings.
  on [Q] [RATE]   Force a low-latency graph quantum. Defaults: Q=128 RATE=48000.
  off             Clear forced quantum/rate and return to normal PipeWire behavior.

Useful quantum values at 48 kHz:
  256  about 5.3 ms per block, safer
  128  about 2.7 ms per block, good stage starting point
   64  about 1.3 ms per block, lower latency but higher dropout risk
USAGE
}

metadata() {
  pw-metadata -n settings "$@"
}

status() {
  local output
  output="$(pw-metadata -n settings)"
  printf '%s\n' "$output" | grep -E "clock\\.(rate|quantum|min-quantum|max-quantum|force-quantum|force-rate)" || true

  local rate quantum forced_quantum
  rate="$(printf '%s\n' "$output" | awk -F"'" '/clock.rate/ { print $4; exit }')"
  quantum="$(printf '%s\n' "$output" | awk -F"'" '/clock.quantum/ { print $4; exit }')"
  forced_quantum="$(printf '%s\n' "$output" | awk -F"'" '/clock.force-quantum/ { print $4; exit }')"

  if [[ -n "$rate" && -n "$quantum" ]]; then
    awk -v q="$quantum" -v r="$rate" 'BEGIN { printf "\nCurrent block latency: %.2f ms at %s Hz\n", (q / r) * 1000, r }'
  fi

  if [[ "${forced_quantum:-0}" != "0" ]]; then
    printf 'Low-latency override: ON\n'
  else
    printf 'Low-latency override: OFF\n'
  fi
}

set_low_latency() {
  local quantum="${1:-128}"
  local rate="${2:-48000}"

  if ! [[ "$quantum" =~ ^[0-9]+$ && "$rate" =~ ^[0-9]+$ ]]; then
    printf 'Quantum and rate must be numeric.\n' >&2
    exit 2
  fi

  metadata 0 clock.force-rate "$rate" >/dev/null
  metadata 0 clock.force-quantum "$quantum" >/dev/null
  awk -v q="$quantum" -v r="$rate" 'BEGIN { printf "Forced PipeWire quantum %s at %s Hz, about %.2f ms per block\n", q, r, (q / r) * 1000 }'
}

clear_low_latency() {
  metadata 0 clock.force-quantum 0 >/dev/null
  metadata 0 clock.force-rate 0 >/dev/null
  printf 'Cleared PipeWire forced quantum/rate.\n'
}

case "${1:-}" in
  status)
    status
    ;;
  on)
    set_low_latency "${2:-128}" "${3:-48000}"
    ;;
  off)
    clear_low_latency
    ;;
  -h|--help|help|'')
    usage
    ;;
  *)
    usage >&2
    exit 2
    ;;
esac
