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
192 lines
10 KiB
Bash
Executable File
192 lines
10 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
mkdir -p "$PROJECT_ROOT/presets/factory/bank_0"
|
|
mkdir -p "$PROJECT_ROOT/presets/factory/bank_1"
|
|
|
|
cat > "$PROJECT_ROOT/presets/factory/bank_0/bank.json" << 'BANKMETA'
|
|
{
|
|
"number": 0,
|
|
"name": "Clean & Edge",
|
|
"preset_count": 4
|
|
}
|
|
BANKMETA
|
|
|
|
cat > "$PROJECT_ROOT/presets/factory/bank_0/preset_0.json" << 'PRESET'
|
|
{
|
|
"name": "Clean Jazz",
|
|
"bank": 0,
|
|
"program": 0,
|
|
"master_volume": 0.8,
|
|
"tuner_enabled": false,
|
|
"chain": [
|
|
{"fx_type": "noise_gate", "enabled": true, "bypass": false, "params": {"threshold": 0.01}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "compressor", "enabled": true, "bypass": false, "params": {"threshold": 0.3, "ratio": 4.0, "gain": 0.8}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "nam_amp", "enabled": true, "bypass": false, "params": {}, "nam_model_path": "factory/clean_fender.nam", "ir_file_path": ""},
|
|
{"fx_type": "ir_cab", "enabled": true, "bypass": false, "params": {}, "nam_model_path": "", "ir_file_path": "factory/twin_reverb.wav"},
|
|
{"fx_type": "reverb", "enabled": true, "bypass": false, "params": {"decay": 0.3, "mix": 0.2}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "volume", "enabled": true, "bypass": false, "params": {"level": 0.85}, "nam_model_path": "", "ir_file_path": ""}
|
|
],
|
|
"midi_mappings": {
|
|
"reverb_mix": {"cc_number": 15, "channel": 0, "min_val": 0.0, "max_val": 1.0}
|
|
}
|
|
}
|
|
PRESET
|
|
|
|
cat > "$PROJECT_ROOT/presets/factory/bank_0/preset_1.json" << 'PRESET'
|
|
{
|
|
"name": "Edge of Breakup",
|
|
"bank": 0,
|
|
"program": 1,
|
|
"master_volume": 0.75,
|
|
"tuner_enabled": false,
|
|
"chain": [
|
|
{"fx_type": "noise_gate", "enabled": true, "bypass": false, "params": {"threshold": 0.008}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "overdrive", "enabled": true, "bypass": false, "params": {"drive": 0.3, "gain": 0.9}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "nam_amp", "enabled": true, "bypass": false, "params": {}, "nam_model_path": "factory/vox_ac30.nam", "ir_file_path": ""},
|
|
{"fx_type": "ir_cab", "enabled": true, "bypass": false, "params": {}, "nam_model_path": "", "ir_file_path": "factory/alnico_blue.wav"},
|
|
{"fx_type": "delay", "enabled": true, "bypass": false, "params": {"time": 350.0, "feedback": 0.25, "mix": 0.2}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "volume", "enabled": true, "bypass": false, "params": {"level": 0.8}, "nam_model_path": "", "ir_file_path": ""}
|
|
],
|
|
"midi_mappings": {}
|
|
}
|
|
PRESET
|
|
|
|
cat > "$PROJECT_ROOT/presets/factory/bank_0/preset_2.json" << 'PRESET'
|
|
{
|
|
"name": "Clean with Chorus",
|
|
"bank": 0,
|
|
"program": 2,
|
|
"master_volume": 0.78,
|
|
"tuner_enabled": false,
|
|
"chain": [
|
|
{"fx_type": "noise_gate", "enabled": true, "bypass": false, "params": {"threshold": 0.01}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "nam_amp", "enabled": true, "bypass": false, "params": {}, "nam_model_path": "factory/roland_jc120.nam", "ir_file_path": ""},
|
|
{"fx_type": "ir_cab", "enabled": true, "bypass": false, "params": {}, "nam_model_path": "", "ir_file_path": "factory/jc120_ir.wav"},
|
|
{"fx_type": "chorus", "enabled": true, "bypass": false, "params": {"rate": 0.35, "depth": 0.5, "mix": 0.4}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "reverb", "enabled": true, "bypass": false, "params": {"decay": 0.4, "mix": 0.25}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "volume", "enabled": true, "bypass": false, "params": {"level": 0.82}, "nam_model_path": "", "ir_file_path": ""}
|
|
],
|
|
"midi_mappings": {}
|
|
}
|
|
PRESET
|
|
|
|
cat > "$PROJECT_ROOT/presets/factory/bank_0/preset_3.json" << 'PRESET'
|
|
{
|
|
"name": "Dynamic Fingerstyle",
|
|
"bank": 0,
|
|
"program": 3,
|
|
"master_volume": 0.72,
|
|
"tuner_enabled": false,
|
|
"chain": [
|
|
{"fx_type": "compressor", "enabled": true, "bypass": false, "params": {"threshold": 0.25, "ratio": 6.0, "gain": 0.7}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "boost", "enabled": true, "bypass": false, "params": {"gain_db": 3.0}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "nam_amp", "enabled": true, "bypass": false, "params": {}, "nam_model_path": "factory/fender_twin.nam", "ir_file_path": ""},
|
|
{"fx_type": "ir_cab", "enabled": true, "bypass": false, "params": {}, "nam_model_path": "", "ir_file_path": "factory/american_2x12.wav"},
|
|
{"fx_type": "reverb", "enabled": true, "bypass": false, "params": {"decay": 0.5, "mix": 0.3}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "volume", "enabled": true, "bypass": false, "params": {"level": 0.78}, "nam_model_path": "", "ir_file_path": ""}
|
|
],
|
|
"midi_mappings": {}
|
|
}
|
|
PRESET
|
|
|
|
cat > "$PROJECT_ROOT/presets/factory/bank_1/bank.json" << 'BANKMETA'
|
|
{
|
|
"number": 1,
|
|
"name": "Drive & Lead",
|
|
"preset_count": 4
|
|
}
|
|
BANKMETA
|
|
|
|
cat > "$PROJECT_ROOT/presets/factory/bank_1/preset_0.json" << 'PRESET'
|
|
{
|
|
"name": "Classic Rock",
|
|
"bank": 1,
|
|
"program": 0,
|
|
"master_volume": 0.7,
|
|
"tuner_enabled": false,
|
|
"chain": [
|
|
{"fx_type": "noise_gate", "enabled": true, "bypass": false, "params": {"threshold": 0.015}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "overdrive", "enabled": true, "bypass": false, "params": {"drive": 0.55, "gain": 0.8}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "nam_amp", "enabled": true, "bypass": false, "params": {}, "nam_model_path": "factory/marshall_plexi.nam", "ir_file_path": ""},
|
|
{"fx_type": "ir_cab", "enabled": true, "bypass": false, "params": {}, "nam_model_path": "", "ir_file_path": "factory/greenback_4x12.wav"},
|
|
{"fx_type": "delay", "enabled": true, "bypass": false, "params": {"time": 380.0, "feedback": 0.3, "mix": 0.25}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "volume", "enabled": true, "bypass": false, "params": {"level": 0.75}, "nam_model_path": "", "ir_file_path": ""}
|
|
],
|
|
"midi_mappings": {
|
|
"drive": {"cc_number": 14, "channel": 0, "min_val": 0.0, "max_val": 1.0}
|
|
}
|
|
}
|
|
PRESET
|
|
|
|
cat > "$PROJECT_ROOT/presets/factory/bank_1/preset_1.json" << 'PRESET'
|
|
{
|
|
"name": "Lead Solo",
|
|
"bank": 1,
|
|
"program": 1,
|
|
"master_volume": 0.85,
|
|
"tuner_enabled": false,
|
|
"chain": [
|
|
{"fx_type": "noise_gate", "enabled": true, "bypass": false, "params": {"threshold": 0.02}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "compressor", "enabled": true, "bypass": false, "params": {"threshold": 0.4, "ratio": 3.0, "gain": 1.2}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "overdrive", "enabled": true, "bypass": false, "params": {"drive": 0.7, "gain": 0.7}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "distortion", "enabled": true, "bypass": false, "params": {"drive": 0.6, "gain": 0.6}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "nam_amp", "enabled": true, "bypass": false, "params": {}, "nam_model_path": "factory/5150_stealth.nam", "ir_file_path": ""},
|
|
{"fx_type": "ir_cab", "enabled": true, "bypass": false, "params": {}, "nam_model_path": "", "ir_file_path": "factory/v30_4x12.wav"},
|
|
{"fx_type": "delay", "enabled": true, "bypass": false, "params": {"time": 450.0, "feedback": 0.35, "mix": 0.35}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "reverb", "enabled": true, "bypass": false, "params": {"decay": 0.6, "mix": 0.3}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "volume", "enabled": true, "bypass": false, "params": {"level": 0.9}, "nam_model_path": "", "ir_file_path": ""}
|
|
],
|
|
"midi_mappings": {
|
|
"delay_feedback": {"cc_number": 18, "channel": 1, "min_val": 0.0, "max_val": 1.0}
|
|
}
|
|
}
|
|
PRESET
|
|
|
|
cat > "$PROJECT_ROOT/presets/factory/bank_1/preset_2.json" << 'PRESET'
|
|
{
|
|
"name": "Metal Rhythm",
|
|
"bank": 1,
|
|
"program": 2,
|
|
"master_volume": 0.65,
|
|
"tuner_enabled": false,
|
|
"chain": [
|
|
{"fx_type": "noise_gate", "enabled": true, "bypass": false, "params": {"threshold": 0.03}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "boost", "enabled": true, "bypass": false, "params": {"gain_db": 8.0}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "distortion", "enabled": true, "bypass": false, "params": {"drive": 0.8, "gain": 0.5}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "nam_amp", "enabled": true, "bypass": false, "params": {}, "nam_model_path": "factory/peavey_6505.nam", "ir_file_path": ""},
|
|
{"fx_type": "ir_cab", "enabled": true, "bypass": false, "params": {}, "nam_model_path": "", "ir_file_path": "factory/v30_4x12.wav"},
|
|
{"fx_type": "eq", "enabled": true, "bypass": false, "params": {"bass": 0.6, "mid": 0.3, "treble": 0.7}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "volume", "enabled": true, "bypass": false, "params": {"level": 0.7}, "nam_model_path": "", "ir_file_path": ""}
|
|
],
|
|
"midi_mappings": {}
|
|
}
|
|
PRESET
|
|
|
|
cat > "$PROJECT_ROOT/presets/factory/bank_1/preset_3.json" << 'PRESET'
|
|
{
|
|
"name": "Ambient Wash",
|
|
"bank": 1,
|
|
"program": 3,
|
|
"master_volume": 0.72,
|
|
"tuner_enabled": false,
|
|
"chain": [
|
|
{"fx_type": "compressor", "enabled": true, "bypass": false, "params": {"threshold": 0.3, "ratio": 4.0, "gain": 0.9}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "nam_amp", "enabled": true, "bypass": false, "params": {}, "nam_model_path": "factory/fender_twin.nam", "ir_file_path": ""},
|
|
{"fx_type": "ir_cab", "enabled": true, "bypass": false, "params": {}, "nam_model_path": "", "ir_file_path": "factory/american_2x12.wav"},
|
|
{"fx_type": "phaser", "enabled": true, "bypass": false, "params": {"rate": 0.2, "depth": 0.6, "feedback": 0.4}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "chorus", "enabled": true, "bypass": false, "params": {"rate": 0.3, "depth": 0.7, "mix": 0.5}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "delay", "enabled": true, "bypass": false, "params": {"time": 500.0, "feedback": 0.4, "mix": 0.35}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "reverb", "enabled": true, "bypass": false, "params": {"decay": 0.8, "mix": 0.4}, "nam_model_path": "", "ir_file_path": ""},
|
|
{"fx_type": "volume", "enabled": true, "bypass": false, "params": {"level": 0.78}, "nam_model_path": "", "ir_file_path": ""}
|
|
],
|
|
"midi_mappings": {}
|
|
}
|
|
PRESET
|
|
|
|
echo "Factory presets generated:"
|
|
find "$PROJECT_ROOT/presets/factory" -name '*.json' | sort
|
|
echo ""
|
|
echo "Total: $(find "$PROJECT_ROOT/presets/factory" -name 'preset_*.json' | wc -l) presets across $(find "$PROJECT_ROOT/presets/factory" -name 'bank.json' | wc -l) banks" |