Pattern mute and so on

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

View File

@@ -323,6 +323,8 @@ fn render_vu_meter(frame: &mut Frame, app: &App, area: Rect) {
}
fn render_active_patterns(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, area: Rect) {
use crate::widgets::MuteStatus;
let theme = theme::get();
let block = Block::default()
.borders(Borders::ALL)
@@ -336,11 +338,27 @@ fn render_active_patterns(frame: &mut Frame, app: &App, snapshot: &SequencerSnap
.map(|p| (p.bank, p.pattern, p.iter))
.collect();
let mute_status: Vec<MuteStatus> = snapshot
.active_patterns
.iter()
.map(|p| {
if app.mute.is_soloed(p.bank, p.pattern) {
MuteStatus::Soloed
} else if app.mute.is_muted(p.bank, p.pattern) {
MuteStatus::Muted
} else if app.mute.is_effectively_muted(p.bank, p.pattern) {
MuteStatus::EffectivelyMuted
} else {
MuteStatus::Normal
}
})
.collect();
let step_info = snapshot
.get_step(app.editor_ctx.bank, app.editor_ctx.pattern)
.map(|step| (step, app.current_edit_pattern().length));
let mut widget = ActivePatterns::new(&patterns);
let mut widget = ActivePatterns::new(&patterns).with_mute_status(&mute_status);
if let Some((step, total)) = step_info {
widget = widget.with_step(step, total);
}

View File

@@ -91,13 +91,41 @@ fn render_banks(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, area
let is_playing = banks_with_playback.contains(&idx);
let is_staged = banks_with_staged.contains(&idx);
let (bg, fg, prefix) = match (is_cursor, is_playing, is_staged) {
(true, _, _) => (theme.selection.cursor, theme.selection.cursor_fg, ""),
(false, true, _) => (theme.list.playing_bg, theme.list.playing_fg, "> "),
(false, false, true) => (theme.list.staged_play_bg, theme.list.staged_play_fg, "+ "),
(false, false, false) if is_selected => (theme.list.hover_bg, theme.list.hover_fg, ""),
(false, false, false) if is_edit => (theme.list.edit_bg, theme.list.edit_fg, ""),
(false, false, false) => (theme.ui.bg, theme.ui.text_muted, ""),
// Check if any pattern in this bank is muted/soloed (applied)
let has_muted = (0..MAX_PATTERNS).any(|p| app.mute.is_muted(idx, p));
let has_soloed = (0..MAX_PATTERNS).any(|p| app.mute.is_soloed(idx, p));
// Check if any pattern in this bank has staged mute/solo
let has_staged_mute = (0..MAX_PATTERNS).any(|p| app.playback.has_staged_mute(idx, p));
let has_staged_solo = (0..MAX_PATTERNS).any(|p| app.playback.has_staged_solo(idx, p));
let has_staged_mute_solo = has_staged_mute || has_staged_solo;
let (bg, fg, prefix) = if is_cursor {
(theme.selection.cursor, theme.selection.cursor_fg, "")
} else if is_playing {
if has_staged_mute_solo {
(theme.list.staged_play_bg, theme.list.staged_play_fg, ">*")
} else if has_soloed {
(theme.list.soloed_bg, theme.list.soloed_fg, ">S")
} else if has_muted {
(theme.list.muted_bg, theme.list.muted_fg, ">M")
} else {
(theme.list.playing_bg, theme.list.playing_fg, "> ")
}
} else if is_staged {
(theme.list.staged_play_bg, theme.list.staged_play_fg, "+ ")
} else if has_staged_mute_solo {
(theme.list.staged_play_bg, theme.list.staged_play_fg, " *")
} else if has_soloed && is_selected {
(theme.list.soloed_bg, theme.list.soloed_fg, " S")
} else if has_muted && is_selected {
(theme.list.muted_bg, theme.list.muted_fg, " M")
} else if is_selected {
(theme.list.hover_bg, theme.list.hover_fg, "")
} else if is_edit {
(theme.list.edit_bg, theme.list.edit_fg, "")
} else {
(theme.ui.bg, theme.ui.text_muted, "")
};
let name = app.project_state.project.banks[idx]
@@ -250,14 +278,74 @@ fn render_patterns(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, a
let is_staged_play = staged_to_play.contains(&idx);
let is_staged_stop = staged_to_stop.contains(&idx);
let (bg, fg, prefix) = match (is_cursor, is_playing, is_staged_play, is_staged_stop) {
(true, _, _, _) => (theme.selection.cursor, theme.selection.cursor_fg, ""),
(false, true, _, true) => (theme.list.staged_stop_bg, theme.list.staged_stop_fg, "- "),
(false, true, _, false) => (theme.list.playing_bg, theme.list.playing_fg, "> "),
(false, false, true, _) => (theme.list.staged_play_bg, theme.list.staged_play_fg, "+ "),
(false, false, false, _) if is_selected => (theme.list.hover_bg, theme.list.hover_fg, ""),
(false, false, false, _) if is_edit => (theme.list.edit_bg, theme.list.edit_fg, ""),
(false, false, false, _) => (theme.ui.bg, theme.ui.text_muted, ""),
// Current applied mute/solo state
let is_muted = app.mute.is_muted(bank, idx);
let is_soloed = app.mute.is_soloed(bank, idx);
// Staged mute/solo (will toggle on commit)
let has_staged_mute = app.playback.has_staged_mute(bank, idx);
let has_staged_solo = app.playback.has_staged_solo(bank, idx);
// Preview state (what it will be after commit)
let preview_muted = is_muted ^ has_staged_mute;
let preview_soloed = is_soloed ^ has_staged_solo;
let is_effectively_muted = app.mute.is_effectively_muted(bank, idx);
let (bg, fg, prefix) = if is_cursor {
(theme.selection.cursor, theme.selection.cursor_fg, "")
} else if is_playing {
// Playing patterns
if is_staged_stop {
(theme.list.staged_stop_bg, theme.list.staged_stop_fg, "- ")
} else if has_staged_solo {
// Staged solo toggle on playing pattern
if preview_soloed {
(theme.list.soloed_bg, theme.list.soloed_fg, "+S")
} else {
(theme.list.playing_bg, theme.list.playing_fg, "-S")
}
} else if has_staged_mute {
// Staged mute toggle on playing pattern
if preview_muted {
(theme.list.muted_bg, theme.list.muted_fg, "+M")
} else {
(theme.list.playing_bg, theme.list.playing_fg, "-M")
}
} else if is_soloed {
(theme.list.soloed_bg, theme.list.soloed_fg, ">S")
} else if is_muted {
(theme.list.muted_bg, theme.list.muted_fg, ">M")
} else if is_effectively_muted {
(theme.list.muted_bg, theme.list.muted_fg, "> ")
} else {
(theme.list.playing_bg, theme.list.playing_fg, "> ")
}
} else if is_staged_play {
(theme.list.staged_play_bg, theme.list.staged_play_fg, "+ ")
} else if has_staged_solo {
// Staged solo on non-playing pattern
if preview_soloed {
(theme.list.soloed_bg, theme.list.soloed_fg, "+S")
} else {
(theme.ui.bg, theme.ui.text_muted, "-S")
}
} else if has_staged_mute {
// Staged mute on non-playing pattern
if preview_muted {
(theme.list.muted_bg, theme.list.muted_fg, "+M")
} else {
(theme.ui.bg, theme.ui.text_muted, "-M")
}
} else if is_soloed {
(theme.list.soloed_bg, theme.list.soloed_fg, " S")
} else if is_muted {
(theme.list.muted_bg, theme.list.muted_fg, " M")
} else if is_selected {
(theme.list.hover_bg, theme.list.hover_fg, "")
} else if is_edit {
(theme.list.edit_bg, theme.list.edit_fg, "")
} else {
(theme.ui.bg, theme.ui.text_muted, "")
};
let pattern = &app.project_state.project.banks[bank].patterns[idx];