Files
shawn c38a7b0fd8 Add main entry point + systemd services + integration tests
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
2026-06-07 23:39:50 -04:00

159 lines
5.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# ──────────────────────────────────────────────────────────────────────────────
# download_presets.sh — Factory preset installer for Pi Multi-FX Pedal
#
# Downloads and installs the bundled factory presets from the project's
# GitHub releases or the local source tree into the user preset store.
#
# Usage:
# ./scripts/download_presets.sh # Install from bundled local presets
# ./scripts/download_presets.sh --overwrite # Overwrite existing presets
# ./scripts/download_presets.sh --source <url> # Download from a fallback URL
# ./scripts/download_presets.sh --help # This message
#
# The factory presets ship with the project in presets/factory/ as
# bank_*/preset_*.json files. This script copies them to ~/.pedal/presets/
# (or PEDAL_CONFIG_DIR if set).
# ──────────────────────────────────────────────────────────────────────────────
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
# Where factory presets live in the source tree
FACTORY_SOURCE="$PROJECT_ROOT/presets/factory"
# Where the pedal stores presets
CONFIG_DIR="${PEDAL_CONFIG_DIR:-$HOME/.pedal}"
PRESET_DIR="$CONFIG_DIR/presets"
OVERWRITE=false
FALLBACK_URL=""
# ── Parse arguments ─────────────────────────────────────────────────────────
while [[ $# -gt 0 ]]; do
case "$1" in
--overwrite)
OVERWRITE=true
shift
;;
--source)
if [[ -z "${2:-}" ]]; then
echo "ERROR: --source requires a URL argument" >&2
exit 1
fi
FALLBACK_URL="$2"
shift 2
;;
--help|-h)
sed -n '2,/^$/{ /^$/!p }' "$0"
exit 0
;;
*)
echo "ERROR: Unknown option: $1" >&2
echo "Usage: $0 [--overwrite] [--source <url>]" >&2
exit 1
;;
esac
done
# ── Helper: install a single factory preset file ────────────────────────────
install_preset() {
local src="$1"
local dest_dir="$2"
local overwrite="$3"
# Derive target path: presets/factory/bank_0/preset_1.json → bank_0/preset_1.json
local rel_path="${src#$FACTORY_SOURCE/}"
local dest="$dest_dir/$rel_path"
if [[ -f "$dest" && "$overwrite" != "true" ]]; then
echo " SKIP $(basename "$(dirname "$dest")")/$(basename "$dest") (exists)"
return 1
fi
mkdir -p "$(dirname "$dest")"
cp "$src" "$dest"
echo " INSTALL $(basename "$(dirname "$dest")")/$(basename "$dest")"
return 0
}
# ── Main ────────────────────────────────────────────────────────────────────
echo "Pi Multi-FX Pedal — Factory Preset Installer"
echo "============================================="
echo ""
# Option 1: Install from bundled local presets
if [[ -d "$FACTORY_SOURCE" ]]; then
echo "Found bundled factory presets at: $FACTORY_SOURCE"
echo "Installing to: $PRESET_DIR"
echo ""
count=0
skipped=0
while IFS= read -r -d '' preset_file; do
if install_preset "$preset_file" "$PRESET_DIR" "$OVERWRITE"; then
count=$((count + 1))
else
skipped=$((skipped + 1))
fi
done < <(find "$FACTORY_SOURCE" -name 'preset_*.json' -print0)
echo ""
echo "Done: $count installed, $skipped skipped"
exit 0
# Option 2: Download from fallback URL
elif [[ -n "$FALLBACK_URL" ]]; then
echo "Local factory presets not found at: $FACTORY_SOURCE"
echo "Downloading from: $FALLBACK_URL"
echo ""
TMP_ZIP=$(mktemp /tmp/pedal-presets-XXXXXX.zip)
trap 'rm -f "$TMP_ZIP"' EXIT
if command -v curl &>/dev/null; then
curl -fsSL "$FALLBACK_URL" -o "$TMP_ZIP"
elif command -v wget &>/dev/null; then
wget -q "$FALLBACK_URL" -O "$TMP_ZIP"
else
echo "ERROR: Neither curl nor wget found" >&2
exit 1
fi
TMP_DIR=$(mktemp -d /tmp/pedal-presets-XXXXXX)
trap 'rm -rf "$TMP_DIR" "$TMP_ZIP"' EXIT
unzip -q "$TMP_ZIP" -d "$TMP_DIR"
count=0
while IFS= read -r -d '' preset_file; do
rel_path="${preset_file#$TMP_DIR/}"
dest="$PRESET_DIR/$rel_path"
if [[ -f "$dest" && "$OVERWRITE" != "true" ]]; then
echo " SKIP $(basename "$(dirname "$dest")")/$(basename "$dest")"
continue
fi
mkdir -p "$(dirname "$dest")"
cp "$preset_file" "$dest"
count=$((count + 1))
echo " INSTALL $(basename "$(dirname "$dest")")/$(basename "$dest")"
done < <(find "$TMP_DIR" -name 'preset_*.json' -print0)
echo ""
echo "Done: $count installed from remote source"
exit 0
else
echo "ERROR: No factory presets found at '$FACTORY_SOURCE'"
echo ""
echo "The project ships factory presets in presets/factory/."
echo "If you're running from a cloned repo, run from the project root:"
echo " ./scripts/download_presets.sh"
echo ""
echo "Alternatively, pass --source <url> to download a preset archive."
exit 1
fi