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
This commit is contained in:
Executable
+159
@@ -0,0 +1,159 @@
|
||||
#!/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
|
||||
Reference in New Issue
Block a user