diff --git a/crates/tek/src/tui/app_sequencer.rs b/crates/tek/src/tui/app_sequencer.rs index c4a881b1..2be7c65a 100644 --- a/crates/tek/src/tui/app_sequencer.rs +++ b/crates/tek/src/tui/app_sequencer.rs @@ -173,10 +173,10 @@ audio!(|self:SequencerTui,client,scope|{ Control::Continue }); -render!(|self: SequencerTui|lay!([self.size, Tui::split_n(false, 3, +render!(|self: SequencerTui|lay!([self.size, Tui::split_n(false, 4, Tui::fill_xy(col!([ PhraseEditStatus(&self.editor), - SequencerStatusBar::from(self) + SequencerStatusBar::from(self), ])), Tui::split_e(false, if self.size.w() > 60 { 20 @@ -326,12 +326,11 @@ impl Handle for SequencerTui { /// Status bar for sequencer app #[derive(Clone)] pub struct SequencerStatusBar { - pub(crate) width: usize, - pub(crate) cpu: Option, - pub(crate) size: String, - pub(crate) res: String, - pub(crate) mode: &'static str, - pub(crate) help: &'static [(&'static str, &'static str, &'static str)] + pub(crate) width: usize, + pub(crate) cpu: Option, + pub(crate) size: String, + pub(crate) res: String, + pub(crate) playing: bool, } impl StatusBar for SequencerStatusBar { @@ -352,91 +351,47 @@ impl From<&SequencerTui> for SequencerStatusBar { let width = state.size.w(); Self { width, + playing: state.clock.is_rolling(), cpu: state.perf.percentage().map(|cpu|format!("│{cpu:.01}%")), size: format!("{}x{}│", width, state.size.h()), res: format!("│{}s│{:.1}kHz│{:.1}ms│", samples, rate / 1000., buffer * 1000.), - mode: " SEQUENCER ", - help: &[ - ("", "SPACE", " play/pause"), - ("", "✣", " cursor"), - ("", "Ctrl-✣", " scroll"), - ("", ".,", " length"), - ("", "><", " triplet"), - ("", "[]", " phrase"), - ("", "{}", " order"), - ("en", "q", "ueue"), - ("", "e", "dit"), - ("", "a", "dd note"), - ("", "A", "dd phrase"), - ("", "D", "uplicate phrase"), - ] } } } -render!(|self: SequencerStatusBar|{ - lay!(|add|if self.width > 40 { - add(&Tui::fill_x(Tui::fixed_y(1, lay!([ - Tui::fill_x(Tui::at_w(SequencerModeline::from(self))), - Tui::fill_x(Tui::at_e(SequencerStats::from(self))), - ])))) - } else { - add(&Tui::fill_x(Tui::fixed_y(2, col!(![ - Tui::fill_x(Tui::center_x(SequencerModeline::from(self))), - Tui::fill_x(Tui::center_x(SequencerStats::from(self))), - ])))) - }) -}); - -struct SequencerModeline { - mode: &'static str, - help: &'static [(&'static str, &'static str, &'static str)] -} -impl From<&SequencerStatusBar> for SequencerModeline { - fn from (state: &SequencerStatusBar) -> Self { - Self { - mode: state.mode, - help: state.help, - } - } -} -render!(|self: SequencerModeline|{ - let black = TuiTheme::g(0); - let light = TuiTheme::g(50); - let white = TuiTheme::g(255); - let orange = TuiTheme::orange(); - let yellow = TuiTheme::yellow(); - row!([ - //Tui::bg(orange, Tui::fg(black, Tui::bold(true, self.mode))), - Tui::bg(light, Tui::fg(white, row!((prefix, hotkey, suffix) in self.help.iter() => { - row!([" ", prefix, Tui::fg(yellow, *hotkey), suffix]) - }))) +render!(|self: SequencerStatusBar|Tui::fixed_y(2, row!([ + Tui::fixed_xy(11, 2, PlayPause(self.playing)), + lay!([ + { + let bg = TuiTheme::g(50); + let fg = TuiTheme::g(255); + let single = |binding, command|row!([" ", col!([ + Tui::fg(TuiTheme::yellow(), binding), + command + ])]); + let double = |(b1, c1), (b2, c2)|col!([ + row!([" ", Tui::fg(TuiTheme::yellow(), b1), " ", c1, " "]), + row!([" ", Tui::fg(TuiTheme::yellow(), b2), " ", c2, " "]), + ]); + Tui::bg(bg, Tui::fg(fg, row!([ + single("SPACE", "play/pause"), + double((" ✣", "cursor"), ("C-✣", "scroll"), ), + double((",.", "note"), ("<>", "triplet"),), + double(("[]", "phrase"), ("{}", "order"), ), + double(("q", "enqueue"), ("e", "edit"), ), + ]))) + }, + Tui::fill_xy(Tui::at_se({ + let orange = TuiTheme::orange(); + let dark = TuiTheme::g(25); + //let cpu = &self.cpu; + //let res = &self.res; + let size = &self.size; + Tui::bg(dark, row!([ + //Tui::fg(orange, cpu), + //Tui::fg(orange, res), + Tui::fg(orange, size), + ])) + })), ]) -}); - -struct SequencerStats<'a> { - cpu: &'a Option, - size: &'a String, - res: &'a String, -} -impl<'a> From<&'a SequencerStatusBar> for SequencerStats<'a> { - fn from (state: &'a SequencerStatusBar) -> Self { - Self { - cpu: &state.cpu, - size: &state.size, - res: &state.res, - } - } -} -render!(|self:SequencerStats<'a>|{ - let orange = TuiTheme::orange(); - let dark = TuiTheme::g(25); - let cpu = &self.cpu; - let res = &self.res; - let size = &self.size; - Tui::bg(dark, row!([ - Tui::fg(orange, cpu), - Tui::fg(orange, res), - Tui::fg(orange, size), - ])) -}); +]))); diff --git a/crates/tek/src/tui/app_transport.rs b/crates/tek/src/tui/app_transport.rs index b4c3cd6b..bb238e35 100644 --- a/crates/tek/src/tui/app_transport.rs +++ b/crates/tek/src/tui/app_transport.rs @@ -114,18 +114,8 @@ render!(|self: TransportView|{ Tui::bold(true, Tui::fg(Color::Rgb(220, 220, 220), self.1)), ])); - struct PlayPause(bool); - render!(|self: PlayPause|Tui::bg( - if self.0{Color::Rgb(0,128,0)}else{Color::Rgb(128,64,0)}, - Tui::outset_x(1, Tui::fixed_x(9, col!(|add|if self.0 { - add(&Tui::fg(Color::Rgb(0, 255, 0), col!(["▶ PLAYING", "▒ ▒ ▒ ▒ ▒"]))) - } else { - add(&Tui::fg(Color::Rgb(255, 128, 0), col!(["▒ ▒ ▒ ▒ ▒", "⏹ STOPPED"]))) - }))) - )); - Tui::bg(self.bg, Tui::fill_x(row!([ - PlayPause(self.started), " ", + //PlayPause(self.started), " ", col!([ Field("Beat", self.beat.as_str()), Field("BPM ", self.bpm.as_str()), @@ -139,6 +129,16 @@ render!(|self: TransportView|{ }); +pub struct PlayPause(pub bool); +render!(|self: PlayPause|Tui::bg( + if self.0{Color::Rgb(0,128,0)}else{Color::Rgb(128,64,0)}, + Tui::outset_x(1, Tui::fixed_x(9, col!(|add|if self.0 { + add(&Tui::fg(Color::Rgb(0, 255, 0), col!(["▶ PLAYING", "▒ ▒ ▒ ▒ ▒"]))) + } else { + add(&Tui::fg(Color::Rgb(255, 128, 0), col!(["▒ ▒ ▒ ▒ ▒", "⏹ STOPPED"]))) + }))) +)); + impl HasFocus for TransportTui { type Item = TransportFocus; fn focused (&self) -> Self::Item {