From 774af02e5ee9634ff0389511533b95de91e38358 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Fri, 27 Dec 2024 22:22:08 +0100 Subject: [PATCH] updating phrase selector layout --- crates/tek/src/pool.rs | 68 +++----------------------- crates/tek/src/pool/phrase_selector.rs | 65 ++++++++++++++++++++++++ crates/tek/src/sequencer.rs | 7 +-- crates/tek/src/transport.rs | 4 +- crates/tek/src/tui/piano_h.rs | 9 ++-- 5 files changed, 83 insertions(+), 70 deletions(-) create mode 100644 crates/tek/src/pool/phrase_selector.rs diff --git a/crates/tek/src/pool.rs b/crates/tek/src/pool.rs index 5aa85a5d..0ab0e060 100644 --- a/crates/tek/src/pool.rs +++ b/crates/tek/src/pool.rs @@ -1,7 +1,13 @@ use super::*; -mod phrase_length; pub(crate) use phrase_length::*; -mod phrase_rename; pub(crate) use phrase_rename::*; +pub mod phrase_length; +pub(crate) use phrase_length::*; + +pub mod phrase_rename; +pub(crate) use phrase_rename::*; + +pub mod phrase_selector; +pub(crate) use phrase_selector::*; #[derive(Debug)] pub struct PoolModel { @@ -244,64 +250,6 @@ render!(|self: PoolView<'a>|{ add(&self.0.size) })) }); -pub struct PhraseSelector { - pub(crate) title: &'static str, - pub(crate) name: String, - pub(crate) color: ItemPalette, - pub(crate) time: String, -} -// TODO: Display phrases always in order of appearance -render!(|self: PhraseSelector|Fixed::wh(24, 1, row!([ - Tui::fg(self.color.lightest.rgb, Tui::bold(true, &self.title)), - Tui::fg_bg(self.color.lighter.rgb, self.color.base.rgb, row!([ - format!("{:8}", &self.name[0..8.min(self.name.len())]), - Tui::bg(self.color.dark.rgb, &self.time), - ])), -]))); -impl PhraseSelector { - // beats elapsed - pub fn play_phrase (state: &T) -> Self { - let (name, color) = if let Some((_, Some(phrase))) = state.play_phrase() { - let MidiClip { ref name, color, .. } = *phrase.read().unwrap(); - (name.clone(), color) - } else { - ("".to_string(), ItemPalette::from(TuiTheme::g(64))) - }; - let time = if let Some(elapsed) = state.pulses_since_start_looped() { - format!("+{:>}", state.clock().timebase.format_beats_0(elapsed)) - } else { - String::from(" ") - }; - Self { title: " Now|", time, name, color, } - } - // beats until switchover - pub fn next_phrase (state: &T) -> Self { - let (time, name, color) = if let Some((t, Some(phrase))) = state.next_phrase() { - let MidiClip { ref name, color, .. } = *phrase.read().unwrap(); - let time = { - let target = t.pulse.get(); - let current = state.clock().playhead.pulse.get(); - if target > current { - let remaining = target - current; - format!("-{:>}", state.clock().timebase.format_beats_0(remaining)) - } else { - String::new() - } - }; - (time, name.clone(), color) - } else if let Some((_, Some(phrase))) = state.play_phrase() { - let phrase = phrase.read().unwrap(); - if phrase.looped { - (" ".into(), phrase.name.clone(), phrase.color) - } else { - (" ".into(), " ".into(), TuiTheme::g(64).into()) - } - } else { - (" ".into(), " ".into(), TuiTheme::g(64).into()) - }; - Self { title: " Next|", time, name, color, } - } -} command!(|self: FileBrowserCommand, state: PoolModel|{ use PoolMode::*; use FileBrowserCommand::*; diff --git a/crates/tek/src/pool/phrase_selector.rs b/crates/tek/src/pool/phrase_selector.rs new file mode 100644 index 00000000..855a870b --- /dev/null +++ b/crates/tek/src/pool/phrase_selector.rs @@ -0,0 +1,65 @@ +use crate::*; + +pub struct PhraseSelector { + pub(crate) title: &'static str, + pub(crate) name: String, + pub(crate) color: ItemPalette, + pub(crate) time: String, +} + +// TODO: Display phrases always in order of appearance +render!(|self: PhraseSelector|Fixed::wh(24, 1, row!([ + Tui::fg(self.color.lightest.rgb, Tui::bold(true, &self.title)), + Tui::fg_bg(self.color.lighter.rgb, self.color.base.rgb, row!([ + format!("{:8}", &self.name[0..8.min(self.name.len())]), + Tui::bg(self.color.dark.rgb, &self.time), + ])), +]))); + +impl PhraseSelector { + + // beats elapsed + pub fn play_phrase (state: &T) -> Self { + let (name, color) = if let Some((_, Some(phrase))) = state.play_phrase() { + let MidiClip { ref name, color, .. } = *phrase.read().unwrap(); + (name.clone(), color) + } else { + ("".to_string(), ItemPalette::from(TuiTheme::g(64))) + }; + let time = if let Some(elapsed) = state.pulses_since_start_looped() { + format!("+{:>}", state.clock().timebase.format_beats_0(elapsed)) + } else { + String::from(" ") + }; + Self { title: "Now:|", time, name, color, } + } + + // beats until switchover + pub fn next_phrase (state: &T) -> Self { + let (time, name, color) = if let Some((t, Some(phrase))) = state.next_phrase() { + let MidiClip { ref name, color, .. } = *phrase.read().unwrap(); + let time = { + let target = t.pulse.get(); + let current = state.clock().playhead.pulse.get(); + if target > current { + let remaining = target - current; + format!("-{:>}", state.clock().timebase.format_beats_0(remaining)) + } else { + String::new() + } + }; + (time, name.clone(), color) + } else if let Some((_, Some(phrase))) = state.play_phrase() { + let phrase = phrase.read().unwrap(); + if phrase.looped { + (" ".into(), phrase.name.clone(), phrase.color) + } else { + (" ".into(), " ".into(), TuiTheme::g(64).into()) + } + } else { + (" ".into(), " ".into(), TuiTheme::g(64).into()) + }; + Self { title: " Next|", time, name, color, } + } + +} diff --git a/crates/tek/src/sequencer.rs b/crates/tek/src/sequencer.rs index 9b86fd2d..2613ffdc 100644 --- a/crates/tek/src/sequencer.rs +++ b/crates/tek/src/sequencer.rs @@ -52,11 +52,12 @@ render!(|self: SequencerTui|{ ).flatten().clone(); let play = Fixed::wh(5, 2, PlayPause(self.clock.is_rolling())); let transport = Fixed::h(2, TransportView::from((self, color, true))); - let toolbar = row!([play, col!([ + let toolbar = row!([play, transport]); + let play_queue = row!([ PhraseSelector::play_phrase(&self.player), PhraseSelector::next_phrase(&self.player), - ]), transport]); - Tui::min_y(15, with_size(with_status(col!([ toolbar, editor, ])))) + ]); + Tui::min_y(15, with_size(with_status(col!([ toolbar, play_queue, editor, ])))) }); audio!(|self:SequencerTui, client, scope|{ // Start profiling cycle diff --git a/crates/tek/src/transport.rs b/crates/tek/src/transport.rs index 980d091a..32d64d66 100644 --- a/crates/tek/src/transport.rs +++ b/crates/tek/src/transport.rs @@ -99,10 +99,10 @@ render!(|self: TransportView|{ //PlayPause(self.started), " ", col!([ Field(" Beat", self.beat.as_str(), &color), - Field(" BPM", self.bpm.as_str(), &color), + Field(" Time", format!("{:.1}s", self.current_second).as_str(), &color), ]), col!([ - Field(" Time", format!("{:.1}s", self.current_second).as_str(), &color), + Field(" BPM", self.bpm.as_str(), &color), //Field(" Smpl", format!("{:.1}k", self.current_sample).as_str(), &color), Field(" Rate", format!("{}", self.sr).as_str(), &color), //Field(" CPU%", format!("{:.1}ms", self.perf).as_str(), &color), diff --git a/crates/tek/src/tui/piano_h.rs b/crates/tek/src/tui/piano_h.rs index c7be69ac..78ff8645 100644 --- a/crates/tek/src/tui/piano_h.rs +++ b/crates/tek/src/tui/piano_h.rs @@ -61,7 +61,6 @@ render!(|self: PianoHorizontal|{ let field = move|x, y|row!([ Tui::fg_bg(color.lighter.rgb, color.darker.rgb, Tui::bold(true, x)), - Tui::fg_bg(color.light.rgb, color.darker.rgb, Tui::bold(true, "│")), Tui::fg_bg(color.lighter.rgb, color.dark.rgb, &y), ]); @@ -79,10 +78,10 @@ render!(|self: PianoHorizontal|{ with_border(lay!([ Tui::push_x(0, row!(![ - " ", - field(" Edit", name.to_string()), - field(" Length", length.to_string()), - field(" Loop", looped.to_string()) + //" ", + field("Edit:", name.to_string()), " ", + field("Length:", length.to_string()), " ", + field("Loop:", looped.to_string()) ])), Tui::inset_xy(0, 1, Fill::wh(Bsp::s( Fixed::h(1, Bsp::e(