use crate::engine::{PatternChange, SequencerSnapshot}; use crate::state::StagedChange; use super::App; impl App { pub fn stage_pattern_toggle( &mut self, bank: usize, pattern: usize, snapshot: &SequencerSnapshot, ) { let is_playing = snapshot.is_playing(bank, pattern); let pattern_data = self.project_state.project.pattern_at(bank, pattern); let existing = self.playback.staged_changes.iter().position(|c| { c.change.pattern_id().bank == bank && c.change.pattern_id().pattern == pattern }); if let Some(idx) = existing { self.playback.staged_changes.remove(idx); self.ui .set_status(format!("B{:02}:P{:02} unstaged", bank + 1, pattern + 1)); } else if is_playing { self.playback.staged_changes.push(StagedChange { change: PatternChange::Stop { bank, pattern }, quantization: pattern_data.quantization, sync_mode: pattern_data.sync_mode, }); self.ui.set_status(format!( "B{:02}:P{:02} staged to stop", bank + 1, pattern + 1 )); } else { self.playback.staged_changes.push(StagedChange { change: PatternChange::Start { bank, pattern }, quantization: pattern_data.quantization, sync_mode: pattern_data.sync_mode, }); self.ui.set_status(format!( "B{:02}:P{:02} staged to play", bank + 1, pattern + 1 )); } } /// Commits staged pattern, mute/solo, and prop 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(); let prop_count = self.playback.staged_prop_changes.len(); if pattern_count == 0 && mute_count == 0 && prop_count == 0 { self.ui.set_status("No changes to commit".to_string()); return false; } if pattern_count > 0 { self.playback .queued_changes .append(&mut self.playback.staged_changes); } 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); } } } for ((bank, pattern), props) in self.playback.staged_prop_changes.drain() { let pat = self.project_state.project.pattern_at_mut(bank, pattern); pat.name = props.name; if let Some(len) = props.length { pat.set_length(len); } pat.speed = props.speed; pat.quantization = props.quantization; pat.sync_mode = props.sync_mode; self.project_state.mark_dirty(bank, pattern); } let total = pattern_count + mute_count + prop_count; let status = format!("Committed {total} changes"); self.ui.set_status(status); mute_changed } pub fn clear_staged_changes(&mut self) { let pattern_count = self.playback.staged_changes.len(); let mute_count = self.playback.staged_mute_changes.len(); let prop_count = self.playback.staged_prop_changes.len(); if pattern_count == 0 && mute_count == 0 && prop_count == 0 { return; } self.playback.staged_changes.clear(); self.playback.staged_mute_changes.clear(); self.playback.staged_prop_changes.clear(); let total = pattern_count + mute_count + prop_count; let status = format!("Cleared {total} staged changes"); self.ui.set_status(status); } }