feat(audio): multitrack stem recording — Stage 3 (Recording settings UI)

Adds the "Recording" category to the Settings page so the recording mode is
selectable from the UI (config + core wiring already existed from Stage 2).

- AppMessage::RecordingModeSelected → persists config + sends SetRecordingMode
  (takes effect on the next recording start). recording_mode_hint copy.
- iced 0.14 pick_list can't host per-option tooltips, so the three modes are
  RADIO BUTTONS each wrapped in a `tooltip` (hover explains that mode) — chosen
  over a dropdown so each option is self-documenting. Placed after Microphone,
  using the shared section_header; output-dir note below.
- +1 config test (recording_mode round-trip + is_multitrack classification).

User-verified live (Both mode writes the expected WAVs; radios + tooltips
approved). Senior-written — Gemini's unsanctioned Stage 3 attempt was discarded.
179 tests (169 lib +1 ign, 6 reconnect, 4 transport), clippy --all-targets clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-14 02:04:07 -04:00
co-authored by Claude Opus 4.8
parent 729f5ed6a5
commit d3e831d5e7
3 changed files with 65 additions and 5 deletions
+18
View File
@@ -362,6 +362,24 @@ mod tests {
assert_eq!(back.window_y, Some(-50));
}
#[test]
fn test_recording_mode_field() {
// Default is Mixed (back-compat with pre-feature configs).
assert_eq!(AppConfig::default().recording_mode, RecordingMode::Mixed);
// A chosen mode round-trips through JSON.
let cfg = AppConfig {
recording_mode: RecordingMode::Both,
..AppConfig::default()
};
let back: AppConfig =
serde_json::from_str(&serde_json::to_string(&cfg).unwrap()).unwrap();
assert_eq!(back.recording_mode, RecordingMode::Both);
// is_multitrack() classifies correctly.
assert!(!RecordingMode::Mixed.is_multitrack());
assert!(RecordingMode::Multitrack.is_multitrack());
assert!(RecordingMode::Both.is_multitrack());
}
#[test]
fn test_theme_field() {
// Default theme is Mocha (the original look).