Pattern mute and so on

This commit is contained in:
2026-02-02 16:27:11 +01:00
parent c9ab7a4f0b
commit a67d982fcd
29 changed files with 518 additions and 58 deletions

View File

@@ -17,8 +17,8 @@ use crate::services::pattern_editor;
use crate::settings::Settings;
use crate::state::{
AudioSettings, CyclicEnum, DictFocus, EditorContext, FlashKind, LiveKeyState, Metrics, Modal,
OptionsState, PanelState, PatternField, PatternPropsField, PatternsNav, PlaybackState,
ProjectState, StagedChange, UiState,
MuteState, OptionsState, PanelState, PatternField, PatternPropsField, PatternsNav,
PlaybackState, ProjectState, StagedChange, UiState,
};
use crate::views::{dict_view, help_view};
@@ -28,6 +28,7 @@ pub struct App {
pub project_state: ProjectState,
pub ui: UiState,
pub playback: PlaybackState,
pub mute: MuteState,
pub page: Page,
pub editor_ctx: EditorContext,
@@ -69,6 +70,7 @@ impl App {
project_state: ProjectState::default(),
ui: UiState::default(),
playback: PlaybackState::default(),
mute: MuteState::default(),
page: Page::default(),
editor_ctx: EditorContext::default(),
@@ -494,26 +496,64 @@ impl App {
}
}
pub fn commit_staged_changes(&mut self) {
if self.playback.staged_changes.is_empty() {
/// Commits staged pattern and mute/solo changes.
/// Returns true if mute state changed (caller should send to sequencer).
pub fn commit_staged_changes(&mut self) -> bool {
let pattern_count = self.playback.staged_changes.len();
let mute_count = self.playback.staged_mute_changes.len();
if pattern_count == 0 && mute_count == 0 {
self.ui.set_status("No changes to commit".to_string());
return;
return false;
}
let count = self.playback.staged_changes.len();
self.playback
.queued_changes
.append(&mut self.playback.staged_changes);
self.ui.set_status(format!("Committed {count} changes"));
// Commit pattern changes (queued for quantization)
if pattern_count > 0 {
self.playback
.queued_changes
.append(&mut self.playback.staged_changes);
}
// Apply mute/solo changes immediately
let mute_changed = mute_count > 0;
for change in self.playback.staged_mute_changes.drain() {
match change {
crate::state::StagedMuteChange::ToggleMute { bank, pattern } => {
self.mute.toggle_mute(bank, pattern);
}
crate::state::StagedMuteChange::ToggleSolo { bank, pattern } => {
self.mute.toggle_solo(bank, pattern);
}
}
}
let status = match (pattern_count, mute_count) {
(0, m) => format!("Applied {m} mute/solo changes"),
(p, 0) => format!("Committed {p} pattern changes"),
(p, m) => format!("Committed {p} pattern + {m} mute/solo changes"),
};
self.ui.set_status(status);
mute_changed
}
pub fn clear_staged_changes(&mut self) {
if self.playback.staged_changes.is_empty() {
let pattern_count = self.playback.staged_changes.len();
let mute_count = self.playback.staged_mute_changes.len();
if pattern_count == 0 && mute_count == 0 {
return;
}
let count = self.playback.staged_changes.len();
self.playback.staged_changes.clear();
self.ui
.set_status(format!("Cleared {count} staged changes"));
self.playback.staged_mute_changes.clear();
let status = match (pattern_count, mute_count) {
(0, m) => format!("Cleared {m} staged mute/solo"),
(p, 0) => format!("Cleared {p} staged patterns"),
(p, m) => format!("Cleared {p} patterns + {m} mute/solo"),
};
self.ui.set_status(status);
}
pub fn select_edit_pattern(&mut self, pattern: usize) {
@@ -1094,9 +1134,6 @@ impl App {
AppCommand::DuplicateSteps => self.duplicate_steps(link),
// Pattern playback (staging)
AppCommand::CommitStagedChanges => {
self.commit_staged_changes();
}
AppCommand::ClearStagedChanges => {
self.clear_staged_changes();
}
@@ -1300,6 +1337,22 @@ impl App {
self.stage_pattern_toggle(bank, pattern, snapshot);
}
// Mute/Solo (staged)
AppCommand::StageMute { bank, pattern } => {
self.playback.stage_mute(bank, pattern);
}
AppCommand::StageSolo { bank, pattern } => {
self.playback.stage_solo(bank, pattern);
}
AppCommand::ClearMutes => {
self.playback.clear_staged_mutes();
self.mute.clear_mute();
}
AppCommand::ClearSolos => {
self.playback.clear_staged_solos();
self.mute.clear_solo();
}
// UI state
AppCommand::ClearMinimap => {
self.ui.minimap_until = None;
@@ -1522,6 +1575,13 @@ impl App {
}
}
pub fn send_mute_state(&self, cmd_tx: &Sender<SeqCommand>) {
let _ = cmd_tx.send(SeqCommand::SetMuteState {
muted: self.mute.muted.clone(),
soloed: self.mute.soloed.clone(),
});
}
pub fn flush_dirty_patterns(&mut self, cmd_tx: &Sender<SeqCommand>) {
for (bank, pattern) in self.project_state.take_dirty() {
let pat = self.project_state.project.pattern_at(bank, pattern);