Commit Graph

14 Commits

Author SHA1 Message Date
shawn b6dff3c0f3 feat: Snapshots — 8 per preset save/recall
Adds snapshot system to Helix Stadium:

Backend:
- Snapshot data model (8 slots per preset, captures block bypass
  + params + master volume)
- Snapshot API endpoints: list, save, recall, rename, delete
- Integrated into preset serialization/deserialization
- Tracks current_snapshot in state / WebSocket broadcasts

Frontend:
- Camera icon in header bar with current snapshot number
- SnapshotPanel as slide-up overlay
- 8 snapshot slots in a horizontal row
- Tap to recall filled snapshot, tap empty slot to save
- Press-and-hold (600ms) to save current state
- Inline name editing on tap
- Discard Edits toggle
- Green flash indicator on save
- Delete button for active snapshot
2026-06-12 19:20:56 -04:00
shawn a1f35a56e3 feat: new preset, looper recorder, IR display improvements
- New Preset button: finds first empty slot, saves with default name
- Looper/Recorder tab: Record/Stop via arecord backend, list captures, play back
- Rig: shows loaded IR name more clearly + quick-link buttons to browse IRs/Models
- Backend: capture/start, capture/stop, captures API endpoints with file serve
2026-06-12 17:24:14 -04:00
shawn 2a30592ab3 fix: all dummy data replaced with real API data
- Status bar: CPU load + sample rate from /api/state, TUNER badge shown immediately
- Rig: optimistic toggle updates (bypass/tuner respond instantly), prominent tuner card
- FX Chain: loads real block params from /api/block-params/{fx_type}, Add Block picker with all FX types
- Record: replaced fake multitrack with real Signal Monitor (live I/O VU, clip detect, level history)
- Backend: added _gather_system_stats() returning cpu_percent and sample_rate
2026-06-12 17:16:03 -04:00
shawn 7498ad55fc fix: real VU meter levels from pipeline instead of random animation
- Added input_level and output_level to /api/state (scaled 0-100)
- React RigScreen now reads real levels from state instead of random walk
- When no audio flows, VU meters show flat (0) instead of fake animation
2026-06-12 17:09:49 -04:00
shawn 32690c293e feat: comprehensive React SPA replacing Jinja2 UI
- New dark UI with 7 tabs: Rig, FX Chain, Models, IRs, Presets, Settings, Record
- All screens wired to live API endpoints
- Real-time state via WebSocket + polling fallback
- Models screen: list/load/unload/upload NAM files + Tone3000 search/install
- IRs screen: list/load/unload/upload IR files + Tone3000 search/install
- Presets screen: browse banks, activate, save, delete
- Settings screen: WiFi scan/connect/hotspot, Bluetooth/MIDI, 4CM routing
- Rig screen: live state, volume, bypass, tuner, signal chain
- FX Chain screen: block params, per-block bypass
- Serves at / instead of /ui
- Built with Vite, ~71KB gzipped
2026-06-12 15:30:03 -04:00
shawn 737b123994 R2: Add escapeHtml to app.js for models/irs pages 2026-06-12 14:17:24 -04:00
shawn 77a757cee6 R1: Dashboard 500 fix, Phase 2/7 uncommitted changes
- Fix dashboard 500 when deps disconnected — _gather_state() now returns
  full defaults instead of bare {'connected': False}
- Phase 2: FX param schemas aligned with DSP implementations
- Phase 7: Pipeline routing, preset manager improvements
- Factory presets: cleanup and normalization

Fixes dashboard crash on disconnected state (dogfood issue #1)
2026-06-12 14:02:13 -04:00
shawn 9a8d42e1b6 P2: Fix FX param schemas to match DSP implementations
- EQ: Renamed low_gain/mid_gain/high_gain to bass/mid/treble + added
  bass_freq/mid_freq/treble_freq/q params matching _apply_eq()
- Chorus: Added 'delay' param matching _apply_chorus()
- Flanger: Added 'delay' param matching _apply_flanger()
- Phaser: Added 'stages' and 'mix' params matching _apply_phaser()
- Tremolo: Added 'shape' param matching _apply_tremolo()
- Delay: Added 'tap_tempo' param matching _apply_delay()
- Reverb: Added 'predelay' param matching _apply_reverb()
- Added missing nam_amp + ir_cab param schemas

Verified: 49/49 FX DSP blocks pass, 227 tests pass
2026-06-12 12:57:40 -04:00
shawn e890a4aad3 Wire React UI dist mount at /ui/
Add UI_DIST_DIR auto-detection and /ui static mount in the
FastAPI server so the built React frontend is served alongside
the main dashboard.

- UI_DIST_DIR env var override
- Auto-detect common project layouts (frontend-react/dist,
  pi-multifx-pedal-ui/dist)
- Mount with html=True for SPA client-side routing
2026-06-12 03:08:07 -04:00
shawn a31342b478 feat(tonedownload): Tone3000 NAM + IR browser, real anon key, tests
- Tonedownload.py: Tone3000 API client with search/download/cache/enrich
- Server.py: 4 endpoints (search models, search IRs, install model, install IR)
- Models.html + irs.html: Browse Tone3000 tab with search, trending, offline
- Models.js + irs.js: Tone3000 search UI with install tracking via localStorage
- Style.css: Card layout for search results with thumbnail, meta, install btn
- Tests: 47 tests covering data classes, cache, API, search, download, enrichment
- Anon key: Updated from placeholder to real Supabase anon key (verified: API works)
2026-06-09 01:39:12 -04:00
shawn b4237f2f1d Add Network + Bluetooth config in Web UI
- src/system/network.py: WiFi scan/connect/hotspot via nmcli + iwlist fallback
- src/system/bluetooth.py: BT scan/pair/connect/MIDI via bluetoothctl
- REST endpoints: /api/wifi/* and /api/bluetooth/* (16 endpoints)
- Web UI: tabbed settings with Network + Bluetooth panels
- network.js: WiFi scan, connect modal, saved nets, hotspot
- bluetooth.js: BT scan, pair/unpair, connect, MIDI service
- style.css: tabs, network list, BT device list, signal indicators
- scripts/setup-bt-midi.sh: BT MIDI systemd bridge service
- tests/test_network.py: 22 tests (nmcli/iwlist, fallback, hotspot)
- tests/test_bt.py: 24 tests (status, scan, pair, MIDI, edge cases)
- _gather_state includes wifi + bluetooth sub-objects
- All 93 tests pass
2026-06-09 01:14:41 -04:00
shawn c8d7541065 feat: full FX palette expansion — 32 new effects
Adds all 27 new DSP implementations plus tests and parameter schemas:

Pitch & Frequency (5): octaver, pitch_shifter, harmonizer, whammy, detune
Modulation (7): ring_modulator, auto_wah, envelope_filter, rotary_speaker,
  uni_vibe, auto_pan, stereo_widener
Drive & Saturation (3): bitcrusher, wavefolder, rectifier
Dynamics (4): expander, de_esser, transient_shaper, sidechain_compressor
Filters & EQ (6): parametric_eq, high_pass_filter, low_pass_filter,
  band_pass_filter, notch_filter, formant_filter
Time-Based (6): ping_pong_delay, multi_tap_delay, reverse_delay, tape_echo,
  shimmer_reverb, looper
Ambience (1): early_reflections

Each effect has: DSP function (5-30 lines numpy), case dispatch entry,
parameter schema in _FX_PARAM_SCHEMAS, and tests for critical effects.
CPU-heavy effects (pitch_shifter, shimmer_reverb) tagged as BETA.
All 79 tests pass.
2026-06-08 18:04:02 -04:00
shawn 8ff584cea9 4CM split routing: stereo pipeline + breakpoint + Web UI
Pipeline:
- process() dispatches to _process_mono() or _process_4cm() based on routing_mode
- _process_4cm() splits chain at routing_breakpoint: pre blocks on ch0, post on ch1
- _process_single_block() extracted for reuse in both mono and 4cm paths
- routing_mode/routing_breakpoint load from preset via load_preset()
- set_routing() for runtime configuration
- Properties: routing_mode (mono|4cm), routing_breakpoint with validation

Web server:
- GET /api/routing — current routing mode and breakpoint
- POST /api/routing — set routing mode/breakpoint, persist to current preset, WS broadcast
- _gather_state() includes routing_mode and routing_breakpoint

Web UI:
- Settings page: 4CM toggle + breakpoint slider with routing description
- Dashboard: routing badge (4CM/Mono) with breakpoint info
- app.js: WebSocket handler, updateRoutingUI(), toggle4cm(), set4cmBreakpoint()
- style.css: .badge, .badge-4cm, .badge-mono, .routing-status, .routing-desc

Tests: mock pipeline fixture updated with routing_mode/routing_breakpoint
2026-06-08 10:57:47 -04:00
shawn 1c5b728e8b Build: Web UI + mDNS (pedal.local)
FastAPI web server with REST + WebSocket, 5 Jinja2 HTML pages,
mobile-friendly dark theme CSS, page-specific JS controllers,
and Avahi mDNS service advertisement for pedal.local.

Files:
  src/web/server.py          — FastAPI app with 17 REST endpoints + /ws WebSocket
  src/web/__init__.py         — Package init with WebServer, WebServerDeps exports
  src/web/templates/*.html    — Dashboard, Presets, Models, IRs, Settings (base)
  src/web/static/style.css    — Dark mobile-first CSS (80-82% max-width)
  src/web/static/websocket.js — Auto-reconnecting WebSocket manager
  src/web/static/app.js       — Dashboard live updates + REST helpers
  src/web/static/presets.js   — Bank/preset CRUD modal UI
  src/web/static/models.js    — NAM model list/load/upload
  src/web/static/irs.js       — IR file list/load/upload
  etc/avahi/pi-multifx-pedal.service — Avahi service advertisement
  scripts/setup-mdns.sh       — One-shot mDNS setup (avahi, hostname, restart)
  main.py                     — Wire WebServer into boot/shutdown
  requirements.txt            — Add fastapi, uvicorn, jinja2, python-multipart
  tests/test_web.py           — 36 tests (pages, REST, WebSocket, errors)

All 36 tests pass.
2026-06-08 00:57:26 -04:00