transport compact mode

This commit is contained in:
🪞👃🪞 2025-01-02 15:32:49 +01:00
parent 6776e2ec55
commit 92459b5f82
6 changed files with 134 additions and 83 deletions

View file

@ -11,7 +11,10 @@ pub struct TransportTui {
has_clock!(|self: TransportTui|&self.clock);
audio!(|self: TransportTui, client, scope|ClockAudio(self).process(client, scope));
handle!(<Tui>|self: TransportTui, from|TransportCommand::execute_with_state(self, from));
render!(Tui: (self: TransportTui) => TransportView(&self.clock));
render!(Tui: (self: TransportTui) => TransportView {
compact: false,
clock: &self.clock
});
impl TransportTui {
pub fn new (jack: &Arc<RwLock<JackConnection>>) -> Usually<Self> {
Ok(Self {
@ -21,25 +24,43 @@ impl TransportTui {
}
}
pub struct TransportView<'a>(pub &'a Clock);
pub struct TransportView<'a> { pub compact: bool, pub clock: &'a Clock }
impl<'a> TransportView<'a> {
pub fn new (compact: bool, clock: &'a Clock) -> Self {
Self { compact, clock }
}
}
render!(Tui: (self: TransportView<'a>) => Outer(
Style::default().fg(TuiTheme::g(255)).bg(TuiTheme::g(0))
).enclose(row!(
BeatStats::new(self.0), " ",
PlayPause(self.0.is_rolling()), " ",
OutputStats::new(self.0),
BeatStats::new(self.compact, self.clock), " ",
PlayPause { compact: self.compact, playing: self.clock.is_rolling() }, " ",
OutputStats::new(self.compact, self.clock),
)));
pub struct PlayPause(pub bool);
render!(Tui: (self: PlayPause) => Tui::bg(
if self.0{Color::Rgb(0,128,0)}else{Color::Rgb(128,64,0)},
Fixed::x(5, Tui::either(self.0,
Tui::fg(Color::Rgb(0, 255, 0), Bsp::s(" 🭍🭑🬽 ", " 🭞🭜🭘 ",)),
Tui::fg(Color::Rgb(255, 128, 0), Bsp::s(" ▗▄▖ ", " ▝▀▘ ",))))));
struct Field<'a>(ItemPalette, &'a str, &'a str);
render!(Tui: (self: Field<'a>) => row!(
Tui::bg(self.0.darkest.rgb, Tui::fg(self.0.darker.rgb, "")),
Tui::bg(self.0.darker.rgb, Tui::fg(self.0.lighter.rgb,
Tui::bold(true, format!("{}", self.1)))),
Tui::bg(self.0.darkest.rgb, Tui::fg(self.0.darker.rgb, "")),
Tui::bg(self.0.darkest.rgb, Tui::fg(self.0.lightest.rgb,
Tui::bold(true, format!("{} ", self.2))))));
pub struct BeatStats { bpm: String, beat: String, time: String, }
pub struct PlayPause { pub compact: bool, pub playing: bool }
render!(Tui: (self: PlayPause) => Tui::bg(
if self.playing{Color::Rgb(0,128,0)}else{Color::Rgb(128,64,0)},
Tui::either(self.compact,
Thunk::new(||Fixed::x(9, Tui::either(self.playing,
Tui::fg(Color::Rgb(0, 255, 0), " PLAYING "),
Tui::fg(Color::Rgb(255, 128, 0), " STOPPED ")))),
Thunk::new(||Fixed::x(5, Tui::either(self.playing,
Tui::fg(Color::Rgb(0, 255, 0), Bsp::s(" 🭍🭑🬽 ", " 🭞🭜🭘 ",)),
Tui::fg(Color::Rgb(255, 128, 0), Bsp::s(" ▗▄▖ ", " ▝▀▘ ",))))))));
pub struct BeatStats { compact: bool, bpm: String, beat: String, time: String, }
impl BeatStats {
fn new (clock: &Clock) -> Self {
fn new (compact: bool, clock: &Clock) -> Self {
let (beat, time) = clock.started.read().unwrap().as_ref().map(|started|{
let current_usec = clock.global.usec.get() - started.usec.get();
(
@ -47,32 +68,49 @@ impl BeatStats {
format!("{:.3}s", current_usec/1000000.)
)
}).unwrap_or_else(||("-.-.--".to_string(), "-.---s".to_string()));
Self { bpm: format!("{:.3}", clock.timebase.bpm.get()), beat, time }
Self { compact, bpm: format!("{:.3}", clock.timebase.bpm.get()), beat, time }
}
}
render!(Tui: (self: BeatStats) => col!(
Bsp::e(Tui::fg(TuiTheme::g(255), &self.bpm), " BPM"),
Bsp::e("Beat ", Tui::fg(TuiTheme::g(255), &self.beat)),
Bsp::e("Time ", Tui::fg(TuiTheme::g(255), &self.time)),
));
render!(Tui: (self: BeatStats) => Tui::either(self.compact,
row!(
Field(TuiTheme::g(128).into(), "BPM", &self.bpm),
Field(TuiTheme::g(128).into(), "Beat", &self.beat),
Field(TuiTheme::g(128).into(), "Time", &self.time),
),
col!(
Bsp::e(Tui::fg(TuiTheme::g(255), &self.bpm), " BPM"),
Bsp::e("Beat ", Tui::fg(TuiTheme::g(255), &self.beat)),
Bsp::e("Time ", Tui::fg(TuiTheme::g(255), &self.time)),
)));
pub struct OutputStats { sample_rate: String, buffer_size: String, latency: String, }
pub struct OutputStats { compact: bool, sample_rate: String, buffer_size: String, latency: String, }
impl OutputStats {
fn new (clock: &Clock) -> Self {
fn new (compact: bool, clock: &Clock) -> Self {
let rate = clock.timebase.sr.get();
let chunk = clock.chunk.load(Relaxed);
Self {
sample_rate: format!("{:.1}Hz", rate),
compact,
sample_rate: if compact {
format!("{:.1}kHz", rate / 1000.)
} else {
format!("{:.0}Hz", rate)
},
buffer_size: format!("{chunk}"),
latency: format!("{}", chunk as f64 / rate * 1000.),
}
}
}
render!(Tui: (self: OutputStats) => col!(
Bsp::e(Tui::fg(TuiTheme::g(255), format!("{}", self.sample_rate)), " sample rate"),
Bsp::e(Tui::fg(TuiTheme::g(255), format!("{}", self.buffer_size)), " sample buffer"),
Bsp::e(Tui::fg(TuiTheme::g(255), format!("{:.3}ms", self.latency)), " latency"),
));
render!(Tui: (self: OutputStats) => Tui::either(self.compact,
row!(
Field(TuiTheme::g(128).into(), "SR", &self.sample_rate),
Field(TuiTheme::g(128).into(), "Buf", &self.buffer_size),
Field(TuiTheme::g(128).into(), "Lat", &self.latency),
),
col!(
Bsp::e(Tui::fg(TuiTheme::g(255), format!("{}", self.sample_rate)), " sample rate"),
Bsp::e(Tui::fg(TuiTheme::g(255), format!("{}", self.buffer_size)), " sample buffer"),
Bsp::e(Tui::fg(TuiTheme::g(255), format!("{:.3}ms", self.latency)), " latency"),
)));
#[derive(Clone, Debug, PartialEq)]
pub enum TransportCommand {