c38a7b0fd8
New files:
main.py - PedalApp: boots all subsystems in order,
wires MIDI/footswitch callbacks, graceful
teardown reverses boot order
src/system/config.py - YAML config loader with deep-merge
(separated to avoid hardware deps)
src/system/services.py - systemd unit generator for pedal.service
+ multi-fx-pedal.target
scripts/install_service.sh - copies project, creates venv, installs
+ enables service units
tests/test_integration.py - 41 tests: boot, routing, display sync,
teardown, systemd content, CLI, edge cases
Modified:
tests/conftest.py - add project root to sys.path
166 lines
6.3 KiB
Bash
Executable File
166 lines
6.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# ────────────────────────────────────────────────────────────────────
|
|
# Pi Multi-FX Pedal — systemd service installer
|
|
#
|
|
# Installs pi-multifx-pedal.service + multi-fx-pedal.target and
|
|
# enables them for auto-start on boot.
|
|
#
|
|
# Usage:
|
|
# sudo ./install_service.sh [install_dir]
|
|
#
|
|
# install_dir Path to the pedal installation (default: /opt/pi-multifx-pedal)
|
|
# ────────────────────────────────────────────────────────────────────
|
|
|
|
set -euo pipefail
|
|
|
|
INSTALL_DIR="${1:-/opt/pi-multifx-pedal}"
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
|
|
|
# ── Colour helpers ─────────────────────────────────────────────────
|
|
info() { printf "\e[34m[INFO] %s\e[0m\n" "$*"; }
|
|
ok() { printf "\e[32m[ OK ] %s\e[0m\n" "$*"; }
|
|
warn() { printf "\e[33m[WARN] %s\e[0m\n" "$*"; }
|
|
err() { printf "\e[31m[FAIL] %s\e[0m\n" "$*"; }
|
|
|
|
# ── Root check ─────────────────────────────────────────────────────
|
|
if [[ $EUID -ne 0 ]]; then
|
|
err "This script must be run as root (sudo ./install_service.sh)"
|
|
exit 1
|
|
fi
|
|
|
|
# ── Architecture check (must be RPi) ───────────────────────────────
|
|
ARCH="$(uname -m)"
|
|
if [[ "$ARCH" != "aarch64" && "$ARCH" != "armv7l" ]]; then
|
|
warn "Not a Raspberry Pi (detected: $ARCH) — service files will be written"
|
|
warn "but will not be enabled (no systemctl available in containers)."
|
|
NO_SYSTEMCTL=true
|
|
fi
|
|
|
|
info "========== Pi Multi-FX Pedal — Service Installer =========="
|
|
info "Install dir: $INSTALL_DIR"
|
|
info "Project dir: $PROJECT_DIR"
|
|
echo ""
|
|
|
|
# ── Step 1: Create install directory ───────────────────────────────
|
|
info "Step 1: Creating install directory..."
|
|
mkdir -p "$INSTALL_DIR"
|
|
ok "Install directory ready: $INSTALL_DIR"
|
|
|
|
# ── Step 2: Copy project files ─────────────────────────────────────
|
|
info "Step 2: Copying project files..."
|
|
|
|
# Copy everything except .venv, __pycache__, .git, etc.
|
|
rsync -a --delete \
|
|
--exclude='.git' \
|
|
--exclude='__pycache__' \
|
|
--exclude='*.pyc' \
|
|
--exclude='.venv' \
|
|
--exclude='venv' \
|
|
--exclude='.scone' \
|
|
--exclude='systemd/' \
|
|
--exclude='*.so' \
|
|
--exclude='*.nam' \
|
|
--exclude='*.wav' \
|
|
--exclude='*.aiff' \
|
|
"$PROJECT_DIR/" "$INSTALL_DIR/"
|
|
|
|
ok "Project files copied to $INSTALL_DIR"
|
|
|
|
# ── Step 3: Create Python virtual environment ──────────────────────
|
|
info "Step 3: Setting up Python virtual environment..."
|
|
|
|
if [[ ! -d "$INSTALL_DIR/.venv" ]]; then
|
|
python3 -m venv "$INSTALL_DIR/.venv"
|
|
ok "Virtual environment created at $INSTALL_DIR/.venv"
|
|
else
|
|
info "Virtual environment already exists"
|
|
fi
|
|
|
|
# Install/update dependencies
|
|
"$INSTALL_DIR/.venv/bin/pip" install --quiet --upgrade pip
|
|
"$INSTALL_DIR/.venv/bin/pip" install --quiet -r "$INSTALL_DIR/requirements.txt" 2>&1 | tail -1
|
|
ok "Python dependencies installed"
|
|
|
|
# ── Step 4: Generate service files from Python module ──────────────
|
|
info "Step 4: Generating systemd service units..."
|
|
|
|
PYTHON_BIN="$INSTALL_DIR/.venv/bin/python3"
|
|
SERVICES_MODULE="src.system.services"
|
|
|
|
# Generate pi-multifx-pedal.service
|
|
$PYTHON_BIN -c "
|
|
import sys
|
|
sys.path.insert(0, '$INSTALL_DIR')
|
|
from src.system.services import pedal_service_content
|
|
print(pedal_service_content(install_dir='$INSTALL_DIR'))
|
|
" > /etc/systemd/system/pi-multifx-pedal.service
|
|
ok "Generated /etc/systemd/system/pi-multifx-pedal.service"
|
|
|
|
# Generate multi-fx-pedal.target
|
|
$PYTHON_BIN -c "
|
|
import sys
|
|
sys.path.insert(0, '$INSTALL_DIR')
|
|
from src.system.services import pedal_target_content
|
|
print(pedal_target_content())
|
|
" > /etc/systemd/system/multi-fx-pedal.target
|
|
ok "Generated /etc/systemd/system/multi-fx-pedal.target"
|
|
|
|
# ── Step 5: Reload and enable ──────────────────────────────────────
|
|
info "Step 5: Reloading systemd and enabling services..."
|
|
|
|
if [[ "${NO_SYSTEMCTL:-false}" != true ]]; then
|
|
systemctl daemon-reload
|
|
systemctl enable pi-multifx-pedal.service
|
|
systemctl enable multi-fx-pedal.target
|
|
ok "Services enabled: pi-multifx-pedal.service + multi-fx-pedal.target"
|
|
else
|
|
info "Skipping systemctl enable (non-RPi environment)"
|
|
fi
|
|
|
|
# ── Step 6: Add 'pi' user to audio group ───────────────────────────
|
|
if groups pi | grep -q '\baudio\b' 2>/dev/null; then
|
|
ok "User 'pi' already in audio group"
|
|
else
|
|
usermod -a -G audio pi 2>/dev/null || true
|
|
info "Added 'pi' to audio group (will take effect on next login)"
|
|
fi
|
|
|
|
# ── Optional: Set up log rotation ──────────────────────────────────
|
|
LOGROTATE_FILE="/etc/logrotate.d/pi-multifx-pedal"
|
|
if [[ ! -f "$LOGROTATE_FILE" ]]; then
|
|
cat > "$LOGROTATE_FILE" <<'LOGROTATE'
|
|
/var/log/pi-multifx-pedal/*.log {
|
|
daily
|
|
rotate 7
|
|
compress
|
|
delaycompress
|
|
missingok
|
|
notifempty
|
|
copytruncate
|
|
}
|
|
LOGROTATE
|
|
ok "Log rotation configured at $LOGROTATE_FILE"
|
|
fi
|
|
|
|
# ── Summary ────────────────────────────────────────────────────────
|
|
echo ""
|
|
info "========== Installation Complete =========="
|
|
echo ""
|
|
echo " Service: pi-multifx-pedal.service"
|
|
echo " Target: multi-fx-pedal.target"
|
|
echo " Install: $INSTALL_DIR"
|
|
echo " Config: ~/.pedal/config.yaml"
|
|
echo " Presets: ~/.pedal/presets/"
|
|
echo ""
|
|
info "Start now:"
|
|
echo " sudo systemctl start multi-fx-pedal.target"
|
|
echo ""
|
|
info "Check status:"
|
|
echo " sudo systemctl status pi-multifx-pedal.service"
|
|
echo ""
|
|
info "Tail logs:"
|
|
echo " journalctl -fu pi-multifx-pedal.service"
|
|
echo ""
|
|
info "Stop the pedal:"
|
|
echo " sudo systemctl stop multi-fx-pedal.target" |