#!/bin/bash set -euo pipefail REPO_DIR="/home/arduino/uno-q-audio-synth" PD_DIR="$REPO_DIR/pd" PATCH="$PD_DIR/synth.pd" MODE="usb" VERBOSE=false # Fallback to legacy path if REPO_DIR not cloned [ -d "$PD_DIR" ] || PD_DIR="/home/arduino/pd" PATCH="$PD_DIR/synth.pd" die() { echo "[ERROR] $*" >&2; exit 1; } info() { echo "[INFO] $*"; } while [ $# -gt 0 ]; do case "$1" in -a|--auto) MODE="auto"; shift ;; -o|--onboard) MODE="onboard"; shift ;; -i|--i2s) MODE="i2s"; shift ;; -l|--loopback) MODE="loopback"; shift ;; -v|--verbose) VERBOSE=true; shift ;; -k|--kill) pkill -x pd 2>/dev/null && info "Pd stopped" || info "Pd not running"; exit 0 ;; *) die "Unknown option: $1" ;; esac done if ! command -v pd &>/dev/null; then die "Pure Data not found. Install: apt install puredata" fi MIN_PD_VERSION="0.54.0" PD_VERSION=$(pd --version 2>&1 | grep -oP '[\d]+\.[\d]+-?[\d]*' | head -1 || echo "0.0.0") if printf '%s\n' "$MIN_PD_VERSION" "$PD_VERSION" | sort -V | head -1 | grep -q "^$MIN_PD_VERSION$"; then info "Pd version $PD_VERSION (>= $MIN_PD_VERSION)" else die "Pd version $PD_VERSION is too old. Need >= $MIN_PD_VERSION" fi if [ ! -f "$PATCH" ]; then die "Patch not found: $PATCH" fi # --- Auto-detect mode --- if [ "$MODE" = "auto" ]; then MODE="onboard" fi # --- Configure per-mode options --- AUDIO_OPTS=() if [ "$MODE" = "usb" ]; then info "Mode: USB gadget (UAC1 audio + gmidi MIDI)" AUDIO_OPTS=(-audiooutdev 2 -audioindev 2) if aplay -l 2>/dev/null | grep -q "UAC1Gadget"; then info " USB gadget: OK" # MIDI handled by midi-bridge.service → UDP → Pd netreceive else info " USB gadget: NOT DETECTED (kernel modules needed)" fi fi if [ "$MODE" = "onboard" ] || [ "$MODE" = "i2s" ]; then info "Mode: Onboard audio (PMIC headphone / line out on JMISC)" AUDIO_OPTS=(-audiooutdev 0 -inchannels 0 -outchannels 1) fi if [ "$MODE" = "loopback" ]; then info "Mode: ALSA loopback (testing)" AUDIO_OPTS=(-audiodev 2) fi PD_ARGS=( -nogui -alsa -send "pd dsp 1" "${AUDIO_OPTS[@]}" -audiobuf 20 -blocksize 64 -r 48000 -channels 1 -inchannels 0 -outchannels 1 -path "$PD_DIR" "$PATCH" ) if [ "$VERBOSE" = true ]; then pd "${PD_ARGS[@]}" & else pd "${PD_ARGS[@]}" > /dev/null 2>&1 & fi PID=$! info "Pd started (PID: $PID)" info " Stop: kill $PID" wait $PID info "Pd exited (code: $?)"