#!/bin/bash
# Select and diagnose the MCom03R PipeWire output without relying on node IDs.
set -euo pipefail

PATH=/usr/local/bin:/usr/bin:/bin
export PATH

mode=${1:-status}
AUDIO_PLAY=${MCOM03_AUDIO_PLAY:-/usr/local/libexec/mcom03-audio-play}

# Software volume on the HDMI sink is not free: that card exposes no hardware
# mixer, so any value other than 1.0 makes PipeWire scale and round every sample.
# Stage 3 originally set 0.80 and the operator reports audible noise at that
# setting which is absent at 1.0, so attenuate elsewhere, not here.
SINK_VOLUME=${MCOM03_SINK_VOLUME:-1.0}

usage() {
    cat <<'EOF'
Usage: mcom03-audioctl status|auto|hdmi|analog|test-tone RATE [SECONDS]|test-aac FILE RATE [SECONDS]

  status     Show detected ALSA cards and PipeWire sinks.
  auto       Select HDMI when connected, otherwise select analog.
  hdmi       Select the HDMI PipeWire sink.
  analog     Select the analog PipeWire sink.
  test-tone  Play a PipeWire-generated sine tone at 44100 or 48000 Hz.
  test-aac   Decode AAC and submit 44100 or 48000 Hz stereo PCM to PipeWire.
EOF
}

case "$mode" in
    -h|--help) usage; exit 0 ;;
esac

command -v wpctl >/dev/null 2>&1 || {
    echo "wpctl is required; start the user's PipeWire/WirePlumber session" >&2
    exit 1
}

sink_id() {
    pattern=$1
    wpctl status -n | awk -v pattern="$pattern" '
        /Sinks:/ { in_sinks = 1; next }
        /Sources:/ { in_sinks = 0 }
        in_sinks && index($0, pattern) {
            line = $0
            sub(/^.*[[:space:]]/, "", line)
            # Extract the first numeric token from the original status line.
            if (match($0, /[0-9]+\./)) {
                id = substr($0, RSTART, RLENGTH - 1)
                print id
                exit
            }
        }
    '
}

select_sink() {
    name=$1
    id=$(sink_id "$name")
    [ -n "$id" ] || {
        echo "PipeWire sink is unavailable: $name" >&2
        return 1
    }
    wpctl set-default "$id"
    wpctl set-mute "$id" 0
    wpctl set-volume "$id" "$SINK_VOLUME"
    echo "selected_sink=$name"
    echo "selected_id=$id"
}

require_pipewire_playback_tools() {
    [ -x "$AUDIO_PLAY" ] || {
        echo "PipeWire audio generator is absent: $AUDIO_PLAY" >&2
        return 1
    }
}

play_tone() {
    local rate=$1 seconds=${2:-10}

    case $rate:$seconds in
        44100:*|48000:*) ;;
        *) echo "Tone rate must be 44100 or 48000 Hz." >&2; return 64 ;;
    esac
    [[ $seconds =~ ^[1-9][0-9]*$ ]] || {
        echo "Tone duration must be a positive integer." >&2
        return 64
    }
    require_pipewire_playback_tools
    select_sink alsa_output.platform-hdmi-sound.stereo-fallback
    "$AUDIO_PLAY" tone --rate "$rate" --seconds "$seconds"
    echo "hdmi_pipewire_tone=confirmed"
    echo "source_rate=$rate"
    echo "sink_rate=48000"
}

play_aac() {
    local input=$1 rate=$2 seconds=${3:-0}

    [ -r "$input" ] || { echo "AAC input is unreadable: $input" >&2; return 1; }
    case $rate in 44100|48000) ;; *) echo "AAC rate must be 44100 or 48000 Hz." >&2; return 64 ;; esac
    [[ $seconds =~ ^[0-9]+$ ]] || {
        echo "AAC duration must be a non-negative integer." >&2
        return 64
    }
    require_pipewire_playback_tools
    select_sink alsa_output.platform-hdmi-sound.stereo-fallback
    [ "$seconds" -gt 0 ] || seconds=10
    "$AUDIO_PLAY" aac --rate "$rate" --seconds "$seconds" --input "$input"
    echo "hdmi_pipewire_aac=confirmed"
    echo "source_rate=$rate"
}

hdmi_connected() {
    for status in /sys/class/drm/card*-HDMI-A-*/status; do
        [ -r "$status" ] || continue
        [ "$(cat "$status")" = connected ] && return 0
    done
    return 1
}

case "$mode" in
    status)
        cat /proc/asound/cards 2>/dev/null || true
        echo
        wpctl status -n
        ;;
    auto)
        if hdmi_connected && \
                select_sink alsa_output.platform-hdmi-sound.stereo-fallback; then
            echo 'selection_reason=hdmi-connected'
        else
            select_sink alsa_output.platform-elvsmarccb_asound.stereo-fallback
            echo 'selection_reason=analog-fallback'
        fi
        ;;
    hdmi)
        select_sink alsa_output.platform-hdmi-sound.stereo-fallback
        ;;
    analog)
        select_sink alsa_output.platform-elvsmarccb_asound.stereo-fallback
        ;;
    test-tone)
        [ "$#" -ge 2 ] && [ "$#" -le 3 ] || { usage >&2; exit 64; }
        play_tone "$2" "${3:-10}"
        ;;
    test-aac)
        [ "$#" -ge 3 ] && [ "$#" -le 4 ] || { usage >&2; exit 64; }
        play_aac "$2" "$3" "${4:-0}"
        ;;
    *)
        echo "Unknown mode: $mode" >&2
        usage >&2
        exit 64
        ;;
esac
