Skip to content

Feature/panel minimize dual synth - #2

Merged
illobo merged 17 commits into
mainfrom
feature/panel-minimize-dual-synth
Mar 11, 2026
Merged

Feature/panel minimize dual synth#2
illobo merged 17 commits into
mainfrom
feature/panel-minimize-dual-synth

Conversation

@illobo

@illobo illobo commented Mar 11, 2026

Copy link
Copy Markdown
Owner

No description provided.

lobo and others added 17 commits March 11, 2026 21:54
Add PanelVisibility struct to control visibility of individual UI panels
(synth_a_knobs, synth_a_grid, synth_b_knobs, synth_b_grid, drum_grid,
drum_knobs, waveform). Synth B panels default to collapsed.

This is the first task in a 17-task plan to add per-panel minimize
toggles and dual synth support. Later tasks will use this struct for
layout computation, rendering, and input handling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add SynthId enum (A, B) to messages.rs
- Parameterize UiToAudio: SetSynthPattern, TriggerSynth, ReleaseSynth now take SynthId
- Update AudioToUi::PlaybackPosition: synth_triggered -> synth_a_triggered, add synth_b_triggered/synth_b_step
- Route all synth messages to SynthId::A (dual synth wiring in later tasks)
- Update message handlers in audio/engine.rs, app.rs, keys.rs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add SynthUiState struct bundling per-synth UI state (playback_step,
  cursor_step, ctrl_field, flash, octave, active_pattern, queued_pattern,
  active_kit)
- Replace individual synth_* fields in UiState with synth_a and synth_b
- Rename FocusSection::SynthGrid -> SynthAGrid, SynthControls -> SynthAControls
- Add SynthBGrid and SynthBControls variants
- Make FocusSection::next()/prev() visibility-aware via PanelVisibility
- Replace App::synth_pattern with synth_a_pattern + synth_b_pattern
- Fix all references across keys.rs, mouse.rs, ui/*.rs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Rename LoopConfig.synth_length → synth_a_length (for synth A)
- Add LoopConfig.synth_b_length with default of 16 steps
- Add serde derives to LoopConfig for serialization
- Use #[serde(alias = "synth_length")] for backward compatibility
- Update all references: keys.rs, engine.rs, transport_bar.rs, app.rs, mouse.rs, synth_grid.rs
- For now, all code paths use synth_a_length (dual synth routing comes in later tasks)
- Tests pass: 23 tests, all green

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bundle all per-synth state (voice, pattern, gate, LFO, saturator, reverb,
delay) into SynthInstance struct. Replace individual synth fields with
synth_a and synth_b instances. Rename shared reverb/delay to drum_reverb/
drum_delay for the drum FX bus. Only synth A processing is active; synth B
will be wired in Task 6.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Duplicate the synth processing pipeline for synth B alongside synth A:
- Independent loop lengths from LoopConfig (synth_a_length, synth_b_length)
- Independent step triggering with multi-step note length support
- Independent gate management (gate_samples countdown + release)
- Independent LFO modulation per synth instance
- Independent FX chains (saturator, reverb, delay) per synth instance
- Both synths mixed mono/centered into stereo output
- PlaybackPosition now reports real synth_b_step and synth_b_triggered

Synth B is silent by default (empty pattern) until the user programs it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ystem

Add DualSynthLayout struct and compute_dual_layout() function that serves
as the single source of truth for the dual-synth panel layout. Each of 7
collapsible panels (synth A knobs/grid, synth B knobs/grid, drum grid,
drum knobs, waveform) gets either its expanded height or COLLAPSED_PANEL_HEIGHT
(2 lines). Reclaimed vertical space from collapsed panels is distributed to
growable panels (drum grid). Includes 5 unit tests. Legacy compute_layout()
is preserved for existing callers until Tasks 8/10 migrate them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace compute_layout() with compute_dual_layout() in the render
function. Each panel (Synth A knobs/grid, Synth B knobs/grid, drum
grid, drum knobs, waveform) now renders expanded or as a collapsed
bar based on PanelVisibility. Collapsed bars show "[.] PANEL NAME"
with focus-aware styling. Help overlay renders as a centered overlay
instead of a layout slot. Synth B panels render as collapsed bars
for now (Task 9 will parameterize rendering by SynthId).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Both render_synth_knobs() and render_synth_grid() now accept a SynthId
parameter to render either Synth A or Synth B. Updated function signatures
to dynamically route pattern data and UI state based on synth_id.

Changes:
- synth_knobs.rs: Added synth_id parameter, routes to synth_a/synth_b
  pattern and UI state, updates title to show "SYNTH A" or "SYNTH B"
- synth_grid.rs: Same parameterization pattern, routes pattern/ui_state/
  focus_section/loop_length based on synth_id
- ui/mod.rs: Updated call sites to pass SynthId::A or SynthId::B, removed
  placeholder collapsed bars for Synth B expanded state

Both synth sections now render correctly when expanded.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… synth

- Replace compute_layout() with compute_dual_layout() in mouse handler
- Add panel toggle click handling ([X] to collapse, click collapsed bar to expand)
- Route synth interactions to A or B based on which DualSynthLayout rect was hit
- Add SynthId field to SynthDrag and SynthNoteDrag for correct drag routing
- Add send_synth_b_pattern() helper to App
- Update scroll, click, and drag handlers for dual synth support

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Increased TRANSPORT_HEIGHT from 6 to 7 to accommodate 3 status lines
- Replaced verbose machine_selector_line with compact status_line format
- Each line shows: Label (SA/SB/DR), Pat[N], Kit[N], Loop[N]
- Focused section's status line is highlighted in cyan/amber
- Pattern queuing shown as Pat[N→M] when queued
- Loop indicator shows actual length or "--" when disabled
- Updated layout test to reflect new transport height

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All keyboard handlers that previously hardcoded Synth A now route to the
focused synth (A or B) via a new focused_synth() helper. This covers:
- F2: bulk toggle all synth panels via panel_vis
- Pattern selection (Q-P), prev/next ([]{})
- Kit selection (1-8)
- Loop length cycle (Shift+L)
- Synth note triggers (ZXCVBNM,)
- Synth grid cursor/pitch navigation
- Synth control knob navigation and value adjustment
- Tube saturator (Shift+T)

Added App helper methods: switch_synth_pattern_for, queue_synth_pattern_for,
switch_synth_kit_for for synth-id-parameterized operations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Route synth_b_step to app.ui.synth_b.playback_step
- Add flash animation for synth B triggers
- Use actual field names instead of aliases for clarity
- Update comment to reflect synth A specific logic

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Consolidate synth helper methods to support dual synth architecture:

- Replace send_synth_pattern() and send_synth_b_pattern() with unified send_synth_pattern(synth_id: SynthId)
- Update apply_synth_preset() and apply_synth_pattern_preset() to accept SynthId parameter
- Update all call sites in keys.rs, mouse.rs, and app.rs internal methods
- Simplify send_synth() helper in keys.rs to use new unified API

Old single-synth methods (switch_synth_pattern, queue_synth_pattern, switch_synth_kit) remain for legacy compatibility but updated to use new API internally. New _for() variants with SynthId parameter are preferred for dual synth operations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Added Synth B fields to ProjectFile struct for persisting dual synth state:
- synth_b_kits: Vec<SynthKitData>
- active_synth_b_kit: usize
- synth_b_patterns: Vec<SynthPatternData>
- active_synth_b_pattern: usize

All fields use #[serde(default)] for backward compatibility with old project files.

Added save/load methods:
- save_synth_b_pattern() / load_synth_b_pattern()
- save_synth_b_kit() / load_synth_b_kit()

Updated normalize() to ensure Synth B arrays are properly initialized.

Updated Default impl and demo_project() to initialize Synth B data.

Added tests:
- test_project_roundtrip_dual_synth: verifies Synth B data survives serialization
- test_old_project_loads_with_synth_b_defaults: verifies backward compatibility

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tion

Removed unused legacy components that were replaced by the dual synth
panel system:

- Removed `ComputedLayout` struct and `compute_layout()` function from
  layout.rs (replaced by `DualSynthLayout` and `compute_dual_layout()`)
- Removed unused constants: `SYNTH_SECTION_HEIGHT`,
  `SYNTH_COLLAPSED_HEIGHT`, `FADER_WIDTH`, `SEPARATOR_HEIGHT`
- Removed `synth_collapsed` field from `UiState` (replaced by
  `PanelVisibility` panel management)
- Removed dead helper functions from ui/mod.rs: `render_separator()`,
  `render_synth_collapsed()`, `render_volume_fader()`
- Fixed unused imports warning in layout.rs

All 30 tests pass. Build warnings reduced from 24 to 17 (remaining
warnings are for intentionally unused utility functions).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@illobo
illobo force-pushed the feature/panel-minimize-dual-synth branch from 2559ffb to 227b444 Compare March 11, 2026 20:57
@illobo
illobo merged commit 4008d07 into main Mar 11, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant