Add MixerEngine creation and wiring after model.Load() in main.cpp.
The mixer engine now gets created with current audio settings (sample rate,
buffer size from JackServerSettings), activated, and attached to the model.
This enables WebSocket mixer commands (mixerGetState, mixerAddChannel,
mixerAddBus, etc.) to work through /pipedal endpoint.
Missing initialization was the root cause of 'Invalid format' errors when
sending mixer commands via WebSocket.
- PipeWireDriver.hpp/cpp: new AudioDriver implementation using pw_filter API
- Full-duplex I/O via pw_filter (capture + playback in one RT callback)
- Dynamic channel count support (tested: 1-8 channels, extensible beyond)
- Uses SPA_AUDIO_FORMAT_F32 for zero-copy-compatible float processing
- Channel position mapping: MONO, stereo, 5.1, 7.1, plus Aux for N>8
- Follows the same buffer management pattern as AlsaDriverImpl
- Channel routing: main/aux input/output mapping with mix ops
- CLI flag: --driver pipewire|alsa (default: alsa)
- AudioHost: conditional driver selection based on driverType_
- PiPedalModel: stores and passes driver type to AudioHost
- CMakeLists.txt: added PipeWireDriver source files
- useMixerWS: WebSocket hook connecting to ws://192.168.0.245:8080/ws
with PiPedalSocket-compatible protocol (request/reply via replyTo)
and auto-reconnect with exponential backoff.
- ChannelStrip: per-input channel control with volume fader, pan,
mute, solo, and channel label/type display.
- MasterBus: master/subgroup/aux bus strip with volume fader and mute.
- MixerPage: full mixer console view with horizontal strip layout,
real-time state polling (2s), and connection status indicator.
- AppThemed: added 'Mixer Console' drawer item + conditional rendering.
Build verified: tsc clean, vite build passes (1760 modules, 2.63s).
- Implement saveScene: captures full mixer state via getStateJson(),
stores in ~/op-pedal/default_config/scenes.json with auto-incrementing ID
- Implement loadScene: manual JSON walk to restore channel/bus state
from saved scene JSON, routes skipped for safety
- Implement listScenes: returns JSON array of {id, name}
- Implement deleteScene: remove by ID from scenes file
- Add WS handlers: mixerSaveScene, mixerLoadScene, mixerGetScenes
registered in PiPedalSocket.cpp message dispatcher
- Uses project's JSON_MAP/raw_json_string for file persistence
- Compiles cleanly against existing build
New files:
- MixerApi.hpp/cpp: Model-level API bridging WebSocket messages to
MixerEngine control (channel volume/pan/mute/solo/hpf, bus control,
routing, state queries)
- 15 new WebSocket message handlers in PiPedalSocket.cpp for full
mixer control surface
Integration:
- MixerEngine member added to PiPedalModel with Get/Set accessors
- SetMixerEngine propagates to AudioHost rt processing pipeline
- Socket handler auto-wires MixerEngine to MixerApi on connect
Messages implemented:
mixerSetChannelVolume, mixerSetChannelPan, mixerSetChannelMute,
mixerSetChannelSolo, mixerSetChannelLabel, mixerSetChannelHpf,
mixerGetState, mixerAddChannel, mixerRemoveChannel,
mixerSetBusVolume, mixerSetBusMute, mixerAddBus, mixerRemoveBus,
mixerRouteChannelToBus
When SetMixerEngine() is called with a MixerEngine instance, the
audio processing thread routes all device input/output channels
through the mixer (channel strips → buses → master) instead of
the legacy Lv2Pedalboard. Falls back when no mixer engine is set.
- Thread-safe via mutex + realtime raw pointer swap (same pattern
as existing SetPedalboard)
- Preserves existing pedalboard processing — both modes coexist
- New ProcessLv2Pedalboard() path when realtimeActiveMixerEngine
is non-null uses device buffers directly for multi-channel I/O
MixerEngine architecture:
- MixerChannelStrip: per-input FX chain (Lv2Pedalboard reuse),
volume, pan, mute, solo, HPF, aux sends, VU metering
- MixerBus: accumulation bus with volume, mute, VU. Supports
master, subgroup, aux, and FX-return bus types
- MixerEngine: orchestrator managing channel→bus routing graph,
bus→bus routing, solo override, and the full real-time audio
processing cycle
All new code compiles cleanly with the existing C++20 build and
follows the existing PiPedal codebase conventions (namespaces,
error handling, buffer patterns). CPU-efficient real-time thread
processing with atomic control surface interaction.
- Horizontal lockup: OP Labs icon + 'OP' (silver) + 'PEDAL' (blue)
- Square stack: icon above 'OP PEDAL' text
- Place in artifacts/ and vite/public/img/ for UI use
- OP Labs icon SVG as default app icon + favicon (SVG + ICO fallback)
- 192x192 and 512x512 PWA icons generated from OP Labs logo
- Updated manifest.json with SVG favicon + maskable icon support
- Updated index.html with SVG favicon link
- Replaced old ic_logo.svg with OP Labs icon mark
- Stored OP Labs logo assets (icon, horizontal, square) in artifacts/
- Removed old PiPedal20Thumb.jpg
Reset midiEventMemoryIndex in AlsaDriver.cpp when starting MIDI processing and when clearing midiEventCount to avoid stale index/state issues while using expression pedals.