mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
This commit is contained in:
parent
57102d7e6b
commit
b0ef0cfd21
6 changed files with 197 additions and 188 deletions
|
|
@ -6,4 +6,4 @@
|
||||||
(@f10 toggle-dialog :dialog-quit)
|
(@f10 toggle-dialog :dialog-quit)
|
||||||
|
|
||||||
(@u undo 1)
|
(@u undo 1)
|
||||||
(@shift-u redo 1)
|
(@r redo 1)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ use crate::*;
|
||||||
pub(crate) use std::fmt::Write;
|
pub(crate) use std::fmt::Write;
|
||||||
pub(crate) use ::tengri::tui::ratatui::prelude::Position;
|
pub(crate) use ::tengri::tui::ratatui::prelude::Position;
|
||||||
|
|
||||||
|
mod view_output; pub use self::view_output::*;
|
||||||
|
|
||||||
#[tengri_proc::view(TuiOut)]
|
#[tengri_proc::view(TuiOut)]
|
||||||
impl App {
|
impl App {
|
||||||
pub fn view_nil (&self) -> impl Content<TuiOut> + use<'_> {
|
pub fn view_nil (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
|
|
@ -10,18 +12,14 @@ impl App {
|
||||||
pub fn view_status (&self) -> impl Content<TuiOut> + use<'_> {
|
pub fn view_status (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
self.update_clock();
|
self.update_clock();
|
||||||
let cache = self.view_cache.read().unwrap();
|
let cache = self.view_cache.read().unwrap();
|
||||||
view_status(
|
view_status(self.selected.describe(&self.tracks, &self.scenes),
|
||||||
self.selected.describe(&self.tracks, &self.scenes),
|
cache.sr.view.clone(), cache.buf.view.clone(), cache.lat.view.clone())
|
||||||
cache.sr.view.clone(), cache.buf.view.clone(), cache.lat.view.clone(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
pub fn view_transport (&self) -> impl Content<TuiOut> + use<'_> {
|
pub fn view_transport (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
self.update_clock();
|
self.update_clock();
|
||||||
let cache = self.view_cache.read().unwrap();
|
let cache = self.view_cache.read().unwrap();
|
||||||
view_transport(
|
view_transport(self.clock.is_rolling(),
|
||||||
self.clock.is_rolling(),
|
cache.bpm.view.clone(), cache.beat.view.clone(), cache.time.view.clone())
|
||||||
cache.bpm.view.clone(), cache.beat.view.clone(), cache.time.view.clone(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
pub fn view_arranger (&self) -> impl Content<TuiOut> + use<'_> {
|
pub fn view_arranger (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
ArrangerView::new(self)
|
ArrangerView::new(self)
|
||||||
|
|
@ -85,23 +83,24 @@ impl App {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
});
|
});
|
||||||
let binding = |mut binding: TokenIter, _|Bsp::e(
|
//let binding = ;[> Bsp::e(
|
||||||
Fixed::x(15, Align::w(Tui::bold(true, Tui::fg(Rgb(255,192,0), if let Some(Token {
|
//Fixed::x(15, Align::w(Tui::bold(true, Tui::fg(Rgb(255,192,0), if let Some(Token {
|
||||||
value: Value::Sym(key), ..
|
//value: Value::Sym(key), ..
|
||||||
}) = binding.next() {
|
//}) = binding.next() {
|
||||||
Some(key.to_string())
|
//Some(key.to_string())
|
||||||
} else {
|
//} else {
|
||||||
None
|
//None
|
||||||
})))),
|
//})))),
|
||||||
Bsp::e(" ", Tui::fg(Rgb(255,255,255), if let Some(Token {
|
//Bsp::e(" ", Tui::fg(Rgb(255,255,255), if let Some(Token {
|
||||||
value: Value::Key(command), ..
|
//value: Value::Key(command), ..
|
||||||
}) = binding.next() {
|
//}) = binding.next() {
|
||||||
Some(command.to_string())
|
//Some(command.to_string())
|
||||||
} else {
|
//} else {
|
||||||
None
|
//None
|
||||||
})),
|
//})),
|
||||||
);
|
//);*/
|
||||||
Bsp::s(Tui::bold(true, "Help"), Bsp::s("", Map::south(1, bindings, binding)))
|
Bsp::s(Tui::bold(true, "Help"), Bsp::s("", Map::south(1, bindings, |b,i|format!("{i}:{b:?}"))))
|
||||||
|
//|mut binding: TokenIter, _|Map::east(5, move||binding.clone(), |_,_|"kyp"))))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view_dialog_device (&self, index: usize) -> impl Content<TuiOut> + use<'_> {
|
fn view_dialog_device (&self, index: usize) -> impl Content<TuiOut> + use<'_> {
|
||||||
|
|
@ -149,16 +148,6 @@ impl App {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn outputs_with_sizes (&self) -> impl PortsSizes<'_> {
|
|
||||||
let mut y = 0;
|
|
||||||
self.midi_outs.iter().enumerate().map(move|(i, output)|{
|
|
||||||
let height = 1 + output.conn().len();
|
|
||||||
let data = (i, output.name(), output.conn(), y, y + height);
|
|
||||||
y += height;
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn tracks_with_sizes (&self) -> impl TracksSizes<'_> {
|
pub(crate) fn tracks_with_sizes (&self) -> impl TracksSizes<'_> {
|
||||||
use Selection::*;
|
use Selection::*;
|
||||||
let mut x = 0;
|
let mut x = 0;
|
||||||
|
|
@ -292,14 +281,6 @@ impl<'a> ArrangerView<'a> {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Render output matrix.
|
|
||||||
pub(crate) fn outputs (&'a self) -> impl Content<TuiOut> + 'a {
|
|
||||||
Tui::bg(Reset, Align::n(Bsp::s(
|
|
||||||
Bsp::s(self.output_ports(), self.output_conns()),
|
|
||||||
Bsp::s(self.output_nexts(), self.output_froms()),
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Render device switches.
|
/// Render device switches.
|
||||||
pub(crate) fn devices (&'a self) -> impl Content<TuiOut> + 'a {
|
pub(crate) fn devices (&'a self) -> impl Content<TuiOut> + 'a {
|
||||||
let Self { width_side, width_mid, track_count, track_selected, is_editing, .. } = self;
|
let Self { width_side, width_mid, track_count, track_selected, is_editing, .. } = self;
|
||||||
|
|
@ -388,72 +369,6 @@ impl<'a> ArrangerView<'a> {
|
||||||
|_, _|Tui::bg(Reset, Align::c(Bsp::s(OctaveVertical::default(), " ------ ")))))
|
|_, _|Tui::bg(Reset, Align::c(Bsp::s(OctaveVertical::default(), " ------ ")))))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn output_nexts (&'a self) -> impl Content<TuiOut> + 'a {
|
|
||||||
Tryptich::top(2)
|
|
||||||
.left(self.width_side, Align::ne("From clip:"))
|
|
||||||
.middle(self.width_mid, per_track_top(
|
|
||||||
self.width_mid,
|
|
||||||
||self.tracks_with_sizes_scrolled(),
|
|
||||||
|_, _|Tui::bg(Reset, Align::c(Bsp::s(" ------ ", OctaveVertical::default())))))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn output_froms (&'a self) -> impl Content<TuiOut> + 'a {
|
|
||||||
let label = Align::ne("Next clip:");
|
|
||||||
Tryptich::top(2).left(self.width_side, label).middle(self.width_mid, per_track_top(
|
|
||||||
self.width_mid, ||self.tracks_with_sizes_scrolled(), |t, track|{
|
|
||||||
let queued = track.sequencer.next_clip.is_some();
|
|
||||||
let queued_blank = Thunk::new(||Tui::bg(Reset, " ------ "));
|
|
||||||
let queued_clip = Thunk::new(||{
|
|
||||||
Tui::bg(Reset, if let Some((_, clip)) = track.sequencer.next_clip.as_ref() {
|
|
||||||
if let Some(clip) = clip {
|
|
||||||
clip.read().unwrap().name.clone()
|
|
||||||
} else {
|
|
||||||
"Stop".into()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
"".into()
|
|
||||||
})
|
|
||||||
});
|
|
||||||
Either(queued, queued_clip, queued_blank)
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn output_ports (&'a self) -> impl Content<TuiOut> + 'a {
|
|
||||||
Tryptich::top(1)
|
|
||||||
.left(self.width_side,
|
|
||||||
button_3("o", "midi outs", format!("{}", self.outputs_count), self.is_editing))
|
|
||||||
.right(self.width_side,
|
|
||||||
button_2("O", "add midi out", self.is_editing))
|
|
||||||
.middle(self.width_mid,
|
|
||||||
per_track_top(self.width_mid, ||self.tracks_with_sizes_scrolled(), move|i, t|{
|
|
||||||
let mute = false;
|
|
||||||
let solo = false;
|
|
||||||
let mute = if mute { White } else { t.color.darkest.rgb };
|
|
||||||
let solo = if solo { White } else { t.color.darkest.rgb };
|
|
||||||
let bg_1 = if self.track_selected == Some(i) {
|
|
||||||
t.color.light.rgb
|
|
||||||
} else {
|
|
||||||
t.color.base.rgb
|
|
||||||
};
|
|
||||||
let bg_2 = if i > 0 { t.color.base.rgb } else { Reset };
|
|
||||||
let mute = Tui::fg_bg(mute, bg_1, "Play ");
|
|
||||||
let solo = Tui::fg_bg(solo, bg_1, "Solo ");
|
|
||||||
wrap(bg_1, Tui::g(224), Tui::bold(true, Fill::x(Bsp::e(mute, solo))))
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn output_conns (&'a self) -> impl Content<TuiOut> + 'a {
|
|
||||||
Tryptich::top(self.outputs_height)
|
|
||||||
.left(self.width_side,
|
|
||||||
io_ports(Tui::g(224), Tui::g(32), ||self.app.outputs_with_sizes()))
|
|
||||||
.middle(self.width_mid,
|
|
||||||
per_track_top(self.width_mid, ||self.tracks_with_sizes_scrolled(), |_, t|io_conns(
|
|
||||||
t.color.dark.rgb,
|
|
||||||
t.color.darker.rgb,
|
|
||||||
||self.app.outputs_with_sizes()
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Render scenes with clips
|
/// Render scenes with clips
|
||||||
pub(crate) fn scenes (&'a self) -> impl Content<TuiOut> + 'a {
|
pub(crate) fn scenes (&'a self) -> impl Content<TuiOut> + 'a {
|
||||||
|
|
||||||
|
|
@ -612,83 +527,6 @@ def_sizes_iter!(OutputsSizes => JackMidiOut);
|
||||||
|
|
||||||
def_sizes_iter!(PortsSizes => Arc<str>, [PortConnect]);
|
def_sizes_iter!(PortsSizes => Arc<str>, [PortConnect]);
|
||||||
|
|
||||||
fn view_transport (
|
|
||||||
play: bool,
|
|
||||||
bpm: Arc<RwLock<String>>,
|
|
||||||
beat: Arc<RwLock<String>>,
|
|
||||||
time: Arc<RwLock<String>>,
|
|
||||||
) -> impl Content<TuiOut> {
|
|
||||||
let theme = ItemTheme::G[96];
|
|
||||||
Tui::bg(Black, row!(Bsp::a(
|
|
||||||
Fill::xy(Align::w(button_play_pause(play))),
|
|
||||||
Fill::xy(Align::e(row!(
|
|
||||||
FieldH(theme, "BPM", bpm),
|
|
||||||
FieldH(theme, "Beat", beat),
|
|
||||||
FieldH(theme, "Time", time),
|
|
||||||
)))
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn view_status (
|
|
||||||
sel: Arc<str>,
|
|
||||||
sr: Arc<RwLock<String>>,
|
|
||||||
buf: Arc<RwLock<String>>,
|
|
||||||
lat: Arc<RwLock<String>>,
|
|
||||||
) -> impl Content<TuiOut> {
|
|
||||||
let theme = ItemTheme::G[96];
|
|
||||||
Tui::bg(Black, row!(Bsp::a(
|
|
||||||
Fill::xy(Align::w(FieldH(theme, "Selected", sel))),
|
|
||||||
Fill::xy(Align::e(row!(
|
|
||||||
FieldH(theme, "SR", sr),
|
|
||||||
FieldH(theme, "Buf", buf),
|
|
||||||
FieldH(theme, "Lat", lat),
|
|
||||||
)))
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn button_play_pause (playing: bool) -> impl Content<TuiOut> {
|
|
||||||
let compact = true;//self.is_editing();
|
|
||||||
Tui::bg(if playing { Rgb(0, 128, 0) } else { Rgb(128, 64, 0) },
|
|
||||||
Either::new(compact,
|
|
||||||
Thunk::new(move||Fixed::x(9, Either::new(playing,
|
|
||||||
Tui::fg(Rgb(0, 255, 0), " PLAYING "),
|
|
||||||
Tui::fg(Rgb(255, 128, 0), " STOPPED ")))
|
|
||||||
),
|
|
||||||
Thunk::new(move||Fixed::x(5, Either::new(playing,
|
|
||||||
Tui::fg(Rgb(0, 255, 0), Bsp::s(" 🭍🭑🬽 ", " 🭞🭜🭘 ",)),
|
|
||||||
Tui::fg(Rgb(255, 128, 0), Bsp::s(" ▗▄▖ ", " ▝▀▘ ",))))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub (crate) fn view_meter <'a> (label: &'a str, value: f32) -> impl Content<TuiOut> + 'a {
|
|
||||||
col!(
|
|
||||||
FieldH(ItemTheme::G[128], label, format!("{:>+9.3}", value)),
|
|
||||||
Fixed::xy(if value >= 0.0 { 13 }
|
|
||||||
else if value >= -1.0 { 12 }
|
|
||||||
else if value >= -2.0 { 11 }
|
|
||||||
else if value >= -3.0 { 10 }
|
|
||||||
else if value >= -4.0 { 9 }
|
|
||||||
else if value >= -6.0 { 8 }
|
|
||||||
else if value >= -9.0 { 7 }
|
|
||||||
else if value >= -12.0 { 6 }
|
|
||||||
else if value >= -15.0 { 5 }
|
|
||||||
else if value >= -20.0 { 4 }
|
|
||||||
else if value >= -25.0 { 3 }
|
|
||||||
else if value >= -30.0 { 2 }
|
|
||||||
else if value >= -40.0 { 1 }
|
|
||||||
else { 0 }, 1, Tui::bg(if value >= 0.0 { Red }
|
|
||||||
else if value >= -3.0 { Yellow }
|
|
||||||
else { Green }, ())))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn view_meters (values: &[f32;2]) -> impl Content<TuiOut> + use<'_> {
|
|
||||||
let left = format!("L/{:>+9.3}", values[0]);
|
|
||||||
let right = format!("R/{:>+9.3}", values[1]);
|
|
||||||
Bsp::s(left, right)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn wrap (bg: Color, fg: Color, content: impl Content<TuiOut>) -> impl Content<TuiOut> {
|
pub(crate) fn wrap (bg: Color, fg: Color, content: impl Content<TuiOut>) -> impl Content<TuiOut> {
|
||||||
let left = Tui::fg_bg(bg, Reset, Fixed::x(1, RepeatV("▐")));
|
let left = Tui::fg_bg(bg, Reset, Fixed::x(1, RepeatV("▐")));
|
||||||
let right = Tui::fg_bg(bg, Reset, Fixed::x(1, RepeatV("▌")));
|
let right = Tui::fg_bg(bg, Reset, Fixed::x(1, RepeatV("▌")));
|
||||||
|
|
|
||||||
92
crates/app/src/view/view_output.rs
Normal file
92
crates/app/src/view/view_output.rs
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
/// Outputs.
|
||||||
|
impl App {
|
||||||
|
pub(crate) fn outputs_with_sizes (&self) -> impl PortsSizes<'_> {
|
||||||
|
let mut y = 0;
|
||||||
|
self.midi_outs.iter().enumerate().map(move|(i, output)|{
|
||||||
|
let height = 1 + output.conn().len();
|
||||||
|
let data = (i, output.name(), output.conn(), y, y + height);
|
||||||
|
y += height;
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a> ArrangerView<'a> {
|
||||||
|
fn output_nexts (&self) -> impl Content<TuiOut> + '_ {
|
||||||
|
Tryptich::top(2)
|
||||||
|
.left(self.width_side, Align::ne("From clip:"))
|
||||||
|
.middle(self.width_mid, per_track_top(
|
||||||
|
self.width_mid,
|
||||||
|
||self.tracks_with_sizes_scrolled(),
|
||||||
|
|_, _|Tui::bg(Reset, Align::c(Bsp::s(" ------ ", OctaveVertical::default())))))
|
||||||
|
}
|
||||||
|
/// Render output matrix.
|
||||||
|
pub(crate) fn outputs (&'a self) -> impl Content<TuiOut> + 'a {
|
||||||
|
Tui::bg(Reset, Align::n(Bsp::s(
|
||||||
|
Bsp::s(self.output_ports(), self.output_conns()),
|
||||||
|
Bsp::s(self.output_nexts(), self.output_froms()),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
fn output_froms (&'a self) -> impl Content<TuiOut> + 'a {
|
||||||
|
let label = Align::ne("Next clip:");
|
||||||
|
Tryptich::top(2).left(self.width_side, label).middle(self.width_mid, per_track_top(
|
||||||
|
self.width_mid, ||self.tracks_with_sizes_scrolled(), |t, track|{
|
||||||
|
let queued = track.sequencer.next_clip.is_some();
|
||||||
|
let queued_blank = Thunk::new(||Tui::bg(Reset, " ------ "));
|
||||||
|
let queued_clip = Thunk::new(||{
|
||||||
|
Tui::bg(Reset, if let Some((_, clip)) = track.sequencer.next_clip.as_ref() {
|
||||||
|
if let Some(clip) = clip {
|
||||||
|
clip.read().unwrap().name.clone()
|
||||||
|
} else {
|
||||||
|
"Stop".into()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
"".into()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
Either(queued, queued_clip, queued_blank)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
fn output_ports (&'a self) -> impl Content<TuiOut> + 'a {
|
||||||
|
Tryptich::top(1)
|
||||||
|
.left(self.width_side, self.output_count())
|
||||||
|
.right(self.width_side, self.output_add())
|
||||||
|
.middle(self.width_mid, self.output_map())
|
||||||
|
}
|
||||||
|
fn output_count (&'a self) -> impl Content<TuiOut> + 'a {
|
||||||
|
button_3("o", "midi outs", format!("{}", self.outputs_count), self.is_editing)
|
||||||
|
}
|
||||||
|
fn output_add (&'a self) -> impl Content<TuiOut> + 'a {
|
||||||
|
button_2("O", "add midi out", self.is_editing)
|
||||||
|
}
|
||||||
|
fn output_map (&'a self) -> impl Content<TuiOut> + 'a {
|
||||||
|
per_track_top(self.width_mid, ||self.tracks_with_sizes_scrolled(), move|i, t|{
|
||||||
|
let mute = false;
|
||||||
|
let solo = false;
|
||||||
|
let mute = if mute { White } else { t.color.darkest.rgb };
|
||||||
|
let solo = if solo { White } else { t.color.darkest.rgb };
|
||||||
|
let bg_1 = if self.track_selected == Some(i) {
|
||||||
|
t.color.light.rgb
|
||||||
|
} else {
|
||||||
|
t.color.base.rgb
|
||||||
|
};
|
||||||
|
let bg_2 = if i > 0 { t.color.base.rgb } else { Reset };
|
||||||
|
let mute = Tui::fg_bg(mute, bg_1, "Play ");
|
||||||
|
let solo = Tui::fg_bg(solo, bg_1, "Solo ");
|
||||||
|
wrap(bg_1, Tui::g(224), Tui::bold(true, Fill::x(Bsp::e(mute, solo))))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn output_conns (&'a self) -> impl Content<TuiOut> + 'a {
|
||||||
|
Tryptich::top(self.outputs_height)
|
||||||
|
.left(self.width_side, io_ports(Tui::g(224), Tui::g(32), ||self.app.outputs_with_sizes()))
|
||||||
|
.middle(self.width_mid, per_track_top(
|
||||||
|
self.width_mid,
|
||||||
|
||self.tracks_with_sizes_scrolled(),
|
||||||
|
|_, t|io_conns(
|
||||||
|
t.color.dark.rgb,
|
||||||
|
t.color.darker.rgb,
|
||||||
|
||self.app.outputs_with_sizes()
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
mod clock_api; pub use self::clock_api::*;
|
mod clock_api; pub use self::clock_api::*;
|
||||||
mod clock_model; pub use self::clock_model::*;
|
mod clock_model; pub use self::clock_model::*;
|
||||||
|
mod clock_view; pub use self::clock_view::*;
|
||||||
|
|
||||||
pub trait HasClock: Send + Sync {
|
pub trait HasClock: Send + Sync {
|
||||||
fn clock (&self) -> &Clock;
|
fn clock (&self) -> &Clock;
|
||||||
|
|
|
||||||
51
crates/device/src/clock/clock_view.rs
Normal file
51
crates/device/src/clock/clock_view.rs
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
pub fn view_transport (
|
||||||
|
play: bool,
|
||||||
|
bpm: Arc<RwLock<String>>,
|
||||||
|
beat: Arc<RwLock<String>>,
|
||||||
|
time: Arc<RwLock<String>>,
|
||||||
|
) -> impl Content<TuiOut> {
|
||||||
|
let theme = ItemTheme::G[96];
|
||||||
|
Tui::bg(Black, row!(Bsp::a(
|
||||||
|
Fill::xy(Align::w(button_play_pause(play))),
|
||||||
|
Fill::xy(Align::e(row!(
|
||||||
|
FieldH(theme, "BPM", bpm),
|
||||||
|
FieldH(theme, "Beat", beat),
|
||||||
|
FieldH(theme, "Time", time),
|
||||||
|
)))
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn view_status (
|
||||||
|
sel: Arc<str>,
|
||||||
|
sr: Arc<RwLock<String>>,
|
||||||
|
buf: Arc<RwLock<String>>,
|
||||||
|
lat: Arc<RwLock<String>>,
|
||||||
|
) -> impl Content<TuiOut> {
|
||||||
|
let theme = ItemTheme::G[96];
|
||||||
|
Tui::bg(Black, row!(Bsp::a(
|
||||||
|
Fill::xy(Align::w(FieldH(theme, "Selected", sel))),
|
||||||
|
Fill::xy(Align::e(row!(
|
||||||
|
FieldH(theme, "SR", sr),
|
||||||
|
FieldH(theme, "Buf", buf),
|
||||||
|
FieldH(theme, "Lat", lat),
|
||||||
|
)))
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn button_play_pause (playing: bool) -> impl Content<TuiOut> {
|
||||||
|
let compact = true;//self.is_editing();
|
||||||
|
Tui::bg(if playing { Rgb(0, 128, 0) } else { Rgb(128, 64, 0) },
|
||||||
|
Either::new(compact,
|
||||||
|
Thunk::new(move||Fixed::x(9, Either::new(playing,
|
||||||
|
Tui::fg(Rgb(0, 255, 0), " PLAYING "),
|
||||||
|
Tui::fg(Rgb(255, 128, 0), " STOPPED ")))
|
||||||
|
),
|
||||||
|
Thunk::new(move||Fixed::x(5, Either::new(playing,
|
||||||
|
Tui::fg(Rgb(0, 255, 0), Bsp::s(" 🭍🭑🬽 ", " 🭞🭜🭘 ",)),
|
||||||
|
Tui::fg(Rgb(255, 128, 0), Bsp::s(" ▗▄▖ ", " ▝▀▘ ",))))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -52,3 +52,30 @@ pub fn to_rms (samples: &[f32]) -> f32 {
|
||||||
.unwrap_or(0.0);
|
.unwrap_or(0.0);
|
||||||
(sum / samples.len() as f32).sqrt()
|
(sum / samples.len() as f32).sqrt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub (crate) fn view_meter <'a> (label: &'a str, value: f32) -> impl Content<TuiOut> + 'a {
|
||||||
|
col!(
|
||||||
|
FieldH(ItemTheme::G[128], label, format!("{:>+9.3}", value)),
|
||||||
|
Fixed::xy(if value >= 0.0 { 13 }
|
||||||
|
else if value >= -1.0 { 12 }
|
||||||
|
else if value >= -2.0 { 11 }
|
||||||
|
else if value >= -3.0 { 10 }
|
||||||
|
else if value >= -4.0 { 9 }
|
||||||
|
else if value >= -6.0 { 8 }
|
||||||
|
else if value >= -9.0 { 7 }
|
||||||
|
else if value >= -12.0 { 6 }
|
||||||
|
else if value >= -15.0 { 5 }
|
||||||
|
else if value >= -20.0 { 4 }
|
||||||
|
else if value >= -25.0 { 3 }
|
||||||
|
else if value >= -30.0 { 2 }
|
||||||
|
else if value >= -40.0 { 1 }
|
||||||
|
else { 0 }, 1, Tui::bg(if value >= 0.0 { Red }
|
||||||
|
else if value >= -3.0 { Yellow }
|
||||||
|
else { Green }, ())))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn view_meters (values: &[f32;2]) -> impl Content<TuiOut> + use<'_> {
|
||||||
|
let left = format!("L/{:>+9.3}", values[0]);
|
||||||
|
let right = format!("R/{:>+9.3}", values[1]);
|
||||||
|
Bsp::s(left, right)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue