new status bar enhancements

This commit is contained in:
🪞👃🪞 2025-01-03 15:45:51 +01:00
parent a4e61c087a
commit f359768ba2
6 changed files with 36 additions and 27 deletions

View file

@ -18,10 +18,10 @@ impl Groovebox {
} }
fn selector_view (&self) -> impl Content<Tui> + use<'_> { fn selector_view (&self) -> impl Content<Tui> + use<'_> {
row!( row!(
MidiEditClip(&self.editor),
MidiEditStatus(&self.editor),
ClipSelected::play_phrase(&self.player), ClipSelected::play_phrase(&self.player),
ClipSelected::next_phrase(&self.player), ClipSelected::next_phrase(&self.player),
MidiEditClip(&self.editor),
MidiEditStatus(&self.editor),
) )
} }
fn sample_view (&self) -> impl Content<Tui> + use<'_> { fn sample_view (&self) -> impl Content<Tui> + use<'_> {

View file

@ -73,7 +73,7 @@ impl TimePoint for MidiEditor {
fn set_time_point (&self, x: usize) { self.mode.set_time_point(x) } fn set_time_point (&self, x: usize) { self.mode.set_time_point(x) }
} }
impl MidiViewMode for MidiEditor { impl MidiViewer for MidiEditor {
fn buffer_size (&self, phrase: &MidiClip) -> (usize, usize) { fn buffer_size (&self, phrase: &MidiClip) -> (usize, usize) {
self.mode.buffer_size(phrase) self.mode.buffer_size(phrase)
} }

View file

@ -8,8 +8,7 @@ render!(Tui: (self: MidiEditClip<'a>) => {
(ItemPalette::from(TuiTheme::g(64)), String::new(), 0, false) (ItemPalette::from(TuiTheme::g(64)), String::new(), 0, false)
}; };
row!( row!(
FieldV(color, "Edit", name.to_string()), FieldV(color, "Edit", format!("{name} ({length})")),
FieldV(color, "Length", length.to_string()),
FieldV(color, "Loop", looped.to_string()) FieldV(color, "Loop", looped.to_string())
) )
}); });

View file

@ -1,6 +1,6 @@
use crate::*; use crate::*;
pub trait MidiViewMode: HasSize<Tui> + MidiRange + MidiPoint + Debug + Send + Sync { pub trait MidiViewer: HasSize<Tui> + MidiRange + MidiPoint + Debug + Send + Sync {
fn buffer_size (&self, phrase: &MidiClip) -> (usize, usize); fn buffer_size (&self, phrase: &MidiClip) -> (usize, usize);
fn redraw (&self); fn redraw (&self);
fn phrase (&self) -> &Option<Arc<RwLock<MidiClip>>>; fn phrase (&self) -> &Option<Arc<RwLock<MidiClip>>>;

View file

@ -104,7 +104,7 @@ impl TimePoint for PianoHorizontal {
fn time_point (&self) -> usize { self.point.time_point() } fn time_point (&self) -> usize { self.point.time_point() }
fn set_time_point (&self, x: usize) { self.point.set_time_point(x) } fn set_time_point (&self, x: usize) { self.point.set_time_point(x) }
} }
impl MidiViewMode for PianoHorizontal { impl MidiViewer for PianoHorizontal {
fn phrase (&self) -> &Option<Arc<RwLock<MidiClip>>> { fn phrase (&self) -> &Option<Arc<RwLock<MidiClip>>> {
&self.phrase &self.phrase
} }

View file

@ -12,27 +12,34 @@ render!(Tui: (self: ClipSelected) =>
impl ClipSelected { impl ClipSelected {
// beats elapsed /// Shows currently playing phrase with beats elapsed
pub fn play_phrase <T: HasPlayPhrase + HasClock> (state: &T) -> Self { pub fn play_phrase <T: HasPlayPhrase + HasClock> (state: &T) -> Self {
let (name, color) = if let Some((_, Some(phrase))) = state.play_phrase() { let (name, color) = if let Some((_, Some(phrase))) = state.play_phrase() {
let MidiClip { ref name, color, .. } = *phrase.read().unwrap(); let MidiClip { ref name, color, .. } = *phrase.read().unwrap();
(name.clone(), color) (name.clone(), color)
} else { } else {
("".to_string(), ItemPalette::from(TuiTheme::g(64))) ("".to_string(), TuiTheme::g(64).into())
}; };
let time = if let Some(elapsed) = state.pulses_since_start_looped() { Self {
format!("+{:>}", state.clock().timebase.format_beats_0(elapsed)) title: "Now",
} else { name,
String::from(" ") color,
}; time: state.pulses_since_start_looped()
Self { title: "Now", time, name, color, } .map(|elapsed|format!("+{:>}", state.clock().timebase.format_beats_0(elapsed)))
.unwrap_or_else(||String::from(" "))
}
} }
// beats until switchover /// Shows next phrase with beats remaining until switchover
pub fn next_phrase <T: HasPlayPhrase> (state: &T) -> Self { pub fn next_phrase <T: HasPlayPhrase> (state: &T) -> Self {
let (time, name, color) = if let Some((t, Some(phrase))) = state.next_phrase() { let mut time = String::from("--.-.--");
let MidiClip { ref name, color, .. } = *phrase.read().unwrap(); let mut name = String::from("");
let time = { let mut color = ItemPalette::from(TuiTheme::g(64));
if let Some((t, Some(phrase))) = state.next_phrase() {
let phrase = phrase.read().unwrap();
name = phrase.name.clone();
color = phrase.color.clone();
time = {
let target = t.pulse.get(); let target = t.pulse.get();
let current = state.clock().playhead.pulse.get(); let current = state.clock().playhead.pulse.get();
if target > current { if target > current {
@ -41,17 +48,20 @@ impl ClipSelected {
} else { } else {
String::new() String::new()
} }
}; }
(time, name.clone(), color) } else if let Some((t, Some(phrase))) = state.play_phrase() {
} else if let Some((_, Some(phrase))) = state.play_phrase() {
let phrase = phrase.read().unwrap(); let phrase = phrase.read().unwrap();
if phrase.looped { if phrase.looped {
(" ".into(), phrase.name.clone(), phrase.color) name = phrase.name.clone();
} else { color = phrase.color.clone();
(" ".into(), " ".into(), TuiTheme::g(64).into()) let target = t.pulse.get() + phrase.length as f64;
let current = state.clock().playhead.pulse.get();
if target > current {
time = format!("-{:>}", state.clock().timebase.format_beats_0(target - current))
} }
} else { } else {
(" ".into(), " ".into(), TuiTheme::g(64).into()) name = "Stop".to_string();
}
}; };
Self { title: "Next", time, name, color, } Self { title: "Next", time, name, color, }
} }