From 242c74236f91bf3126e875ecfebaee2d95e11201 Mon Sep 17 00:00:00 2001 From: David Gwilliam Date: Wed, 24 Jun 2026 01:36:36 -0700 Subject: [PATCH] systemd services: midi-bridge, pd-synth-onboard, led-matrix-viz + install script --- install.sh | 39 ++++++++++++++------------- justfile | 48 ++++++++++++++++++++------------- system/pd-synth-onboard.service | 19 +++++++++++++ 3 files changed, 70 insertions(+), 36 deletions(-) create mode 100644 system/pd-synth-onboard.service diff --git a/install.sh b/install.sh index cb025b7..4ac7540 100755 --- a/install.sh +++ b/install.sh @@ -1,27 +1,30 @@ #!/bin/bash -# install.sh — Install system dependencies on the Uno Q -# Run this on the board: ssh arduino@uno-q.local 'bash -s' < install.sh - +# install-services.sh — Deploy systemd services to board set -euo pipefail -echo "[INSTALL] Updating packages..." -sudo apt update -qq +REPO="/home/arduino/uno-q-audio-synth" +SERVICES=(midi-bridge pd-synth-onboard led-matrix-viz) -echo "[INSTALL] Installing Pure Data..." -sudo apt install -y -qq puredata alsa-utils +for svc in "${SERVICES[@]}"; do + sudo cp "$REPO/system/$svc.service" /etc/systemd/system/ +done -echo "[INSTALL] Installing USB gadget config..." -sudo cp system/configure-usb-audio.sh /usr/local/bin/ -sudo chmod +x /usr/local/bin/configure-usb-audio.sh -sudo cp system/asound.conf /etc/asound.conf +# Fix UCM bug (must survive OS updates) +FILE=/usr/share/alsa/ucm2/codecs/qcom-lpass/rx-macro/HeadphoneEnableSeq.conf +if grep -q "RX HPH Mode" "$FILE" 2>/dev/null; then + sudo sed -i '/RX HPH Mode/d' "$FILE" + echo "[OK] UCM HeadphoneEnableSeq patched" +fi -echo "[INSTALL] Installing systemd services..." -sudo cp system/usb-gadget-audio.service /etc/systemd/system/ -sudo cp system/pd-synth.service /etc/systemd/system/ sudo systemctl daemon-reload -echo "[INSTALL] Enabling services..." -sudo systemctl enable usb-gadget-audio -sudo systemctl enable pd-synth +# Stop/mask old conflicting services +sudo systemctl stop pd-synth pd-synth-auto pd-synth-i2s 2>/dev/null || true +sudo systemctl disable pd-synth pd-synth-auto pd-synth-i2s 2>/dev/null || true +sudo systemctl mask pd-synth pd-synth-auto pd-synth-i2s 2>/dev/null || true -echo "[INSTALL] Done. Reboot with: sudo reboot" +for svc in "${SERVICES[@]}"; do + sudo systemctl enable "$svc" +done + +echo "[OK] Services installed and enabled" diff --git a/justfile b/justfile index 3db2e43..742cf38 100644 --- a/justfile +++ b/justfile @@ -91,27 +91,46 @@ install: @ssh {{SSH_OPTS}} "{{BOARD_USER}}@{{BOARD_HOST}}" "\ rm -rf {{REPO_DIR}} 2>/dev/null; \ git clone {{REPO_URL}} {{REPO_DIR}} && \ - echo '[OK] Repo cloned to {{REPO_DIR}}'" - @echo "[OK] Repo installed. Run: just deploy" + echo '[OK] Repo cloned' && \ + chmod +x {{REPO_DIR}}/scripts/*.py {{REPO_DIR}}/scripts/*.sh && \ + bash {{REPO_DIR}}/install.sh && \ + echo '[OK] Services installed'" + @echo "[OK] Run: just deploy" -# Deploy: push local commits + git pull on board +# Deploy + reload services after git pull deploy: @git push origin HEAD 2>&1 @ssh {{SSH_OPTS}} "{{BOARD_USER}}@{{BOARD_HOST}}" "\ - cd {{REPO_DIR}} && git pull && echo '[OK] Deployed'" + cd {{REPO_DIR}} && git pull && \ + chmod +x scripts/*.py scripts/*.sh 2>/dev/null; \ + echo '{{BOARD_PASS}}' | sudo -S systemctl daemon-reload && \ + echo '{{BOARD_PASS}}' | sudo -S systemctl restart midi-bridge pd-synth-onboard led-matrix-viz && \ + echo '[OK] Deployed + restarted'" # Start synth (onboard audio) synth-onboard: - @ssh {{SSH_OPTS}} "{{BOARD_USER}}@{{BOARD_HOST}}" "\ - sudo killall pd 2>/dev/null; sleep 0.5; \ - echo '{{BOARD_PASS}}' | sudo -S sed -i '/RX HPH Mode/d' /usr/share/alsa/ucm2/codecs/qcom-lpass/rx-macro/HeadphoneEnableSeq.conf 2>/dev/null; \ - nohup {{REPO_DIR}}/scripts/start-synth.sh --onboard > /tmp/synth.log 2>&1 & \ - sleep 2; \ - pgrep -x pd >/dev/null && echo '[OK] Synth running (onboard)' || echo '[FAIL] Check /tmp/synth.log'" + @ssh {{SSH_OPTS}} "{{BOARD_USER}}@{{BOARD_HOST}}" "sudo systemctl start pd-synth-onboard && echo '[OK] Synth started'" # Stop synth synth-stop: - @ssh {{SSH_OPTS}} "{{BOARD_USER}}@{{BOARD_HOST}}" "sudo killall pd 2>/dev/null; echo '[OK] Stopped'" + @ssh {{SSH_OPTS}} "{{BOARD_USER}}@{{BOARD_HOST}}" "sudo systemctl stop pd-synth-onboard && echo '[OK] Stopped'" + +# Restart all services +synth-restart: + @ssh {{SSH_OPTS}} "{{BOARD_USER}}@{{BOARD_HOST}}" "\ + sudo systemctl restart midi-bridge pd-synth-onboard led-matrix-viz && \ + echo '[OK] All services restarted'" + +# Show service status +status: + @ssh {{SSH_OPTS}} "{{BOARD_USER}}@{{BOARD_HOST}}" "\ + echo '=== Pd ==='; pgrep -a pd | grep -v watchdog | grep -v kswapd || echo '(not running)'; \ + echo '=== Services ==='; \ + for svc in midi-bridge pd-synth-onboard led-matrix-viz; do \ + echo -n \" \$svc: \"; systemctl is-active \$svc 2>/dev/null || echo 'inactive'; \ + done; \ + echo '=== Audio ==='; cat /proc/asound/cards; \ + echo '=== Git ==='; cd {{REPO_DIR}} && git log --oneline -1" # Enable midi-bridge service enable-midi-bridge: @@ -165,13 +184,6 @@ diag-led: deploy-diag: @scp {{SSH_OPTS}} scripts/diag.sh "{{BOARD_USER}}@{{BOARD_HOST}}:{{SYSTEM_DIR}}/bin/diag.sh" -# Show system status (quick) -status: - @ssh {{SSH_OPTS}} "{{BOARD_USER}}@{{BOARD_HOST}}" "\ - cd {{REPO_DIR}} && git log --oneline -1; \ - echo '---'; pgrep -a pd 2>/dev/null || echo 'Pd: not running'; \ - echo '---'; cat /proc/asound/cards" - # Full deploy + restart synth cycle: deploy synth-stop synth-onboard diff --git a/system/pd-synth-onboard.service b/system/pd-synth-onboard.service new file mode 100644 index 0000000..65916da --- /dev/null +++ b/system/pd-synth-onboard.service @@ -0,0 +1,19 @@ +[Unit] +Description=Pure Data Synth (Onboard PMIC Audio) +After=multi-user.target +Wants=midi-bridge.service + +[Service] +Type=simple +User=arduino +ExecStartPre=/bin/sh -c 'systemctl --user stop pipewire.socket pipewire.service wireplumber 2>/dev/null; sleep 0.5' +ExecStart=/home/arduino/uno-q-audio-synth/scripts/start-synth.sh --onboard +ExecStop=/usr/bin/killall pd +WorkingDirectory=/home/arduino/uno-q-audio-synth +Restart=on-failure +RestartSec=3 +StandardOutput=journal +StandardError=journal + +[Install] +WantedBy=multi-user.target