mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-04-03 21:00:44 +02:00
well, 55 errors until up to date
and then we fix
This commit is contained in:
parent
0577309b19
commit
7ff1d989a9
5 changed files with 333 additions and 344 deletions
159
app/tek.rs
159
app/tek.rs
|
|
@ -22,10 +22,13 @@ pub(crate) use tengri::{
|
|||
*,
|
||||
lang::*,
|
||||
play::*,
|
||||
keys::*,
|
||||
sing::*,
|
||||
time::*,
|
||||
draw::*,
|
||||
tui::*,
|
||||
term::*,
|
||||
color::*,
|
||||
space::*,
|
||||
crossterm::event::{Event, KeyEvent},
|
||||
ratatui::{
|
||||
self,
|
||||
|
|
@ -953,13 +956,13 @@ mod view {
|
|||
/// ```
|
||||
/// let _ = tek::view_logo();
|
||||
/// ```
|
||||
pub fn view_logo () -> impl Content<TuiOut> {
|
||||
Fixed::XY(32, 7, Tui::bold(true, Tui::fg(Rgb(240,200,180), col!{
|
||||
Fixed::Y(1, ""),
|
||||
Fixed::Y(1, ""),
|
||||
Fixed::Y(1, "~~ ╓─╥─╖ ╓──╖ ╥ ╖ ~~~~~~~~~~~~"),
|
||||
Fixed::Y(1, Bsp::e("~~~~ ║ ~ ╟─╌ ~╟─< ~~ ", Bsp::e(Tui::fg(Rgb(230,100,40), "v0.3.0"), " ~~"))),
|
||||
Fixed::Y(1, "~~~~ ╨ ~ ╙──╜ ╨ ╜ ~~~~~~~~~~~~"),
|
||||
pub fn view_logo () -> impl Draw<Tui> {
|
||||
wh_exact(32, 7, Tui::bold(true, Tui::fg(Rgb(240,200,180), south!{
|
||||
h_exact(1, ""),
|
||||
h_exact(1, ""),
|
||||
h_exact(1, "~~ ╓─╥─╖ ╓──╖ ╥ ╖ ~~~~~~~~~~~~"),
|
||||
h_exact(1, east("~~~~ ║ ~ ╟─╌ ~╟─< ~~ ", east(Tui::fg(Rgb(230,100,40), "v0.3.0"), " ~~"))),
|
||||
h_exact(1, "~~~~ ╨ ~ ╙──╜ ╨ ╜ ~~~~~~~~~~~~"),
|
||||
})))
|
||||
}
|
||||
|
||||
|
|
@ -973,14 +976,14 @@ mod view {
|
|||
bpm: Arc<RwLock<String>>,
|
||||
beat: Arc<RwLock<String>>,
|
||||
time: Arc<RwLock<String>>,
|
||||
) -> impl Content<TuiOut> {
|
||||
) -> impl Draw<Tui> {
|
||||
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),
|
||||
Tui::bg(Black, east!(above(
|
||||
wh_full(origin_w(button_play_pause(play))),
|
||||
wh_full(origin_e(east!(
|
||||
field_h(theme, "BPM", bpm),
|
||||
field_h(theme, "Beat", beat),
|
||||
field_h(theme, "Time", time),
|
||||
)))
|
||||
)))
|
||||
}
|
||||
|
|
@ -995,14 +998,14 @@ mod view {
|
|||
sr: Arc<RwLock<String>>,
|
||||
buf: Arc<RwLock<String>>,
|
||||
lat: Arc<RwLock<String>>,
|
||||
) -> impl Content<TuiOut> {
|
||||
) -> impl Draw<Tui> {
|
||||
let theme = ItemTheme::G[96];
|
||||
Tui::bg(Black, row!(Bsp::a(
|
||||
Fill::XY(Align::w(sel.map(|sel|FieldH(theme, "Selected", sel)))),
|
||||
Fill::XY(Align::e(row!(
|
||||
FieldH(theme, "SR", sr),
|
||||
FieldH(theme, "Buf", buf),
|
||||
FieldH(theme, "Lat", lat),
|
||||
Tui::bg(Black, east!(above(
|
||||
wh_full(origin_w(sel.map(|sel|field_h(theme, "Selected", sel)))),
|
||||
wh_full(origin_e(east!(
|
||||
field_h(theme, "SR", sr),
|
||||
field_h(theme, "Buf", buf),
|
||||
field_h(theme, "Lat", lat),
|
||||
)))
|
||||
)))
|
||||
}
|
||||
|
|
@ -1010,17 +1013,17 @@ mod view {
|
|||
/// ```
|
||||
/// let _ = tek::button_play_pause(true);
|
||||
/// ```
|
||||
pub fn button_play_pause (playing: bool) -> impl Content<TuiOut> {
|
||||
pub fn button_play_pause (playing: bool) -> impl Draw<Tui> {
|
||||
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|to: &mut TuiOut|to.place(&Fixed::X(9, Either::new(playing,
|
||||
either(compact,
|
||||
Thunk::new(move|to: &mut Tui|to.place(&w_exact(9, either(playing,
|
||||
Tui::fg(Rgb(0, 255, 0), " PLAYING "),
|
||||
Tui::fg(Rgb(255, 128, 0), " STOPPED ")))
|
||||
)),
|
||||
Thunk::new(move|to: &mut TuiOut|to.place(&Fixed::X(5, Either::new(playing,
|
||||
Tui::fg(Rgb(0, 255, 0), Bsp::s(" 🭍🭑🬽 ", " 🭞🭜🭘 ",)),
|
||||
Tui::fg(Rgb(255, 128, 0), Bsp::s(" ▗▄▖ ", " ▝▀▘ ",))))
|
||||
Thunk::new(move|to: &mut Tui|to.place(&w_exact(5, either(playing,
|
||||
Tui::fg(Rgb(0, 255, 0), south(" 🭍🭑🬽 ", " 🭞🭜🭘 ",)),
|
||||
Tui::fg(Rgb(255, 128, 0), south(" ▗▄▖ ", " ▝▀▘ ",))))
|
||||
))
|
||||
)
|
||||
)
|
||||
|
|
@ -1028,12 +1031,12 @@ mod view {
|
|||
|
||||
#[cfg(feature = "track")] pub fn view_track_row_section (
|
||||
_theme: ItemTheme,
|
||||
button: impl Content<TuiOut>,
|
||||
button_add: impl Content<TuiOut>,
|
||||
content: impl Content<TuiOut>,
|
||||
) -> impl Content<TuiOut> {
|
||||
Bsp::w(Fill::Y(Fixed::X(4, Align::nw(button_add))),
|
||||
Bsp::e(Fixed::X(20, Fill::Y(Align::nw(button))), Fill::XY(Align::c(content))))
|
||||
button: impl Draw<Tui>,
|
||||
button_add: impl Draw<Tui>,
|
||||
content: impl Draw<Tui>,
|
||||
) -> impl Draw<Tui> {
|
||||
west(h_full(w_exact(4, origin_nw(button_add))),
|
||||
east(w_exact(20, h_full(origin_nw(button))), wh_full(origin_c(content))))
|
||||
}
|
||||
|
||||
/// ```
|
||||
|
|
@ -1041,20 +1044,20 @@ mod view {
|
|||
/// let fg = tengri::ratatui::style::Color::Green;
|
||||
/// let _ = tek::view_wrap(bg, fg, "and then blue, too!");
|
||||
/// ```
|
||||
pub fn view_wrap (bg: Color, fg: Color, content: impl Content<TuiOut>) -> impl Content<TuiOut> {
|
||||
let left = Tui::fg_bg(bg, Reset, Fixed::X(1, Repeat::Y("▐")));
|
||||
let right = Tui::fg_bg(bg, Reset, Fixed::X(1, Repeat::Y("▌")));
|
||||
Bsp::e(left, Bsp::w(right, Tui::fg_bg(fg, bg, content)))
|
||||
pub fn view_wrap (bg: Color, fg: Color, content: impl Draw<Tui>) -> impl Draw<Tui> {
|
||||
let left = Tui::fg_bg(bg, Reset, w_exact(1, y_repeat("▐")));
|
||||
let right = Tui::fg_bg(bg, Reset, w_exact(1, y_repeat("▌")));
|
||||
east(left, west(right, Tui::fg_bg(fg, bg, content)))
|
||||
}
|
||||
|
||||
/// ```
|
||||
/// let _ = tek::view_meter("", 0.0);
|
||||
/// let _ = tek::view_meters(&[0.0, 0.0]);
|
||||
/// ```
|
||||
pub 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 }
|
||||
pub fn view_meter <'a> (label: &'a str, value: f32) -> impl Draw<Tui> + 'a {
|
||||
south!(
|
||||
field_h(ItemTheme::G[128], label, format!("{:>+9.3}", value)),
|
||||
wh_exact(if value >= 0.0 { 13 }
|
||||
else if value >= -1.0 { 12 }
|
||||
else if value >= -2.0 { 11 }
|
||||
else if value >= -3.0 { 10 }
|
||||
|
|
@ -1072,47 +1075,47 @@ mod view {
|
|||
else { Green }, ())))
|
||||
}
|
||||
|
||||
pub fn view_meters (values: &[f32;2]) -> impl Content<TuiOut> + use<'_> {
|
||||
pub fn view_meters (values: &[f32;2]) -> impl Draw<Tui> + use<'_> {
|
||||
let left = format!("L/{:>+9.3}", values[0]);
|
||||
let right = format!("R/{:>+9.3}", values[1]);
|
||||
Bsp::s(left, right)
|
||||
south(left, right)
|
||||
}
|
||||
|
||||
pub fn draw_info (sample: Option<&Arc<RwLock<Sample>>>) -> impl Content<TuiOut> + use<'_> {
|
||||
When::new(sample.is_some(), Thunk::new(move|to: &mut TuiOut|{
|
||||
pub fn draw_info (sample: Option<&Arc<RwLock<Sample>>>) -> impl Draw<Tui> + use<'_> {
|
||||
when(sample.is_some(), Thunk::new(move|to: &mut Tui|{
|
||||
let sample = sample.unwrap().read().unwrap();
|
||||
let theme = sample.color;
|
||||
to.place(&row!(
|
||||
FieldH(theme, "Name", format!("{:<10}", sample.name.clone())),
|
||||
FieldH(theme, "Length", format!("{:<8}", sample.channels[0].len())),
|
||||
FieldH(theme, "Start", format!("{:<8}", sample.start)),
|
||||
FieldH(theme, "End", format!("{:<8}", sample.end)),
|
||||
FieldH(theme, "Trans", "0"),
|
||||
FieldH(theme, "Gain", format!("{}", sample.gain)),
|
||||
to.place(&east!(
|
||||
field_h(theme, "Name", format!("{:<10}", sample.name.clone())),
|
||||
field_h(theme, "Length", format!("{:<8}", sample.channels[0].len())),
|
||||
field_h(theme, "Start", format!("{:<8}", sample.start)),
|
||||
field_h(theme, "End", format!("{:<8}", sample.end)),
|
||||
field_h(theme, "Trans", "0"),
|
||||
field_h(theme, "Gain", format!("{}", sample.gain)),
|
||||
))
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn draw_info_v (sample: Option<&Arc<RwLock<Sample>>>) -> impl Content<TuiOut> + use<'_> {
|
||||
Either::new(sample.is_some(), Thunk::new(move|to: &mut TuiOut|{
|
||||
pub fn draw_info_v (sample: Option<&Arc<RwLock<Sample>>>) -> impl Draw<Tui> + use<'_> {
|
||||
either(sample.is_some(), Thunk::new(move|to: &mut Tui|{
|
||||
let sample = sample.unwrap().read().unwrap();
|
||||
let theme = sample.color;
|
||||
to.place(&Fixed::X(20, col!(
|
||||
Fill::X(Align::w(FieldH(theme, "Name ", format!("{:<10}", sample.name.clone())))),
|
||||
Fill::X(Align::w(FieldH(theme, "Length", format!("{:<8}", sample.channels[0].len())))),
|
||||
Fill::X(Align::w(FieldH(theme, "Start ", format!("{:<8}", sample.start)))),
|
||||
Fill::X(Align::w(FieldH(theme, "End ", format!("{:<8}", sample.end)))),
|
||||
Fill::X(Align::w(FieldH(theme, "Trans ", "0"))),
|
||||
Fill::X(Align::w(FieldH(theme, "Gain ", format!("{}", sample.gain)))),
|
||||
to.place(&w_exact(20, south!(
|
||||
w_full(origin_w(field_h(theme, "Name ", format!("{:<10}", sample.name.clone())))),
|
||||
w_full(origin_w(field_h(theme, "Length", format!("{:<8}", sample.channels[0].len())))),
|
||||
w_full(origin_w(field_h(theme, "Start ", format!("{:<8}", sample.start)))),
|
||||
w_full(origin_w(field_h(theme, "End ", format!("{:<8}", sample.end)))),
|
||||
w_full(origin_w(field_h(theme, "Trans ", "0"))),
|
||||
w_full(origin_w(field_h(theme, "Gain ", format!("{}", sample.gain)))),
|
||||
)))
|
||||
}), Thunk::new(|to: &mut TuiOut|to.place(&Tui::fg(Red, col!(
|
||||
}), Thunk::new(|to: &mut Tui|to.place(&Tui::fg(Red, south!(
|
||||
Tui::bold(true, "× No sample."),
|
||||
"[r] record",
|
||||
"[Shift-F9] import",
|
||||
)))))
|
||||
}
|
||||
|
||||
pub fn draw_status (sample: Option<&Arc<RwLock<Sample>>>) -> impl Content<TuiOut> {
|
||||
pub fn draw_status (sample: Option<&Arc<RwLock<Sample>>>) -> impl Draw<Tui> {
|
||||
Tui::bold(true, Tui::fg(Tui::g(224), sample
|
||||
.map(|sample|{
|
||||
let sample = sample.read().unwrap();
|
||||
|
|
@ -1121,31 +1124,31 @@ mod view {
|
|||
.unwrap_or_else(||"No sample".to_string())))
|
||||
}
|
||||
|
||||
pub fn view_track_header (theme: ItemTheme, content: impl Content<TuiOut>) -> impl Content<TuiOut> {
|
||||
Fixed::X(12, Tui::bg(theme.darker.rgb, Fill::X(Align::e(content))))
|
||||
pub fn view_track_header (theme: ItemTheme, content: impl Draw<Tui>) -> impl Draw<Tui> {
|
||||
w_exact(12, Tui::bg(theme.darker.rgb, w_full(origin_e(content))))
|
||||
}
|
||||
|
||||
pub fn view_ports_status <'a, T: JackPort> (theme: ItemTheme, title: &'a str, ports: &'a [T])
|
||||
-> impl Content<TuiOut> + use<'a, T>
|
||||
-> impl Draw<Tui> + use<'a, T>
|
||||
{
|
||||
let ins = ports.len() as u16;
|
||||
let frame = Outer(true, Style::default().fg(Tui::g(96)));
|
||||
let iter = move||ports.iter();
|
||||
let names = Map::south(1, iter, move|port, index|Fill::Y(Align::w(format!(" {index} {}", port.port_name()))));
|
||||
let field = FieldV(theme, title, names);
|
||||
Fixed::XY(20, 1 + ins, frame.enclose(Fixed::XY(20, 1 + ins, field)))
|
||||
let names = iter_south(1, iter, move|port, index|h_full(origin_w(format!(" {index} {}", port.port_name()))));
|
||||
let field = field_v(theme, title, names);
|
||||
wh_exact(20, 1 + ins, frame.enclose(wh_exact(20, 1 + ins, field)))
|
||||
}
|
||||
|
||||
pub fn io_ports <'a, T: PortsSizes<'a>> (
|
||||
fg: Color, bg: Color, iter: impl Fn()->T + Send + Sync + 'a
|
||||
) -> impl Content<TuiOut> + 'a {
|
||||
Map::new(iter, move|(
|
||||
fg: Color, bg: Color, items: impl Fn()->T + Send + Sync + 'a
|
||||
) -> impl Draw<Tui> + 'a {
|
||||
iter(items, move|(
|
||||
_index, name, connections, y, y2
|
||||
): (usize, &'a Arc<str>, &'a [Connect], usize, usize), _|
|
||||
map_south(y as u16, (y2-y) as u16, Bsp::s(
|
||||
Fill::Y(Tui::bold(true, Tui::fg_bg(fg, bg, Align::w(Bsp::e(&" ", name))))),
|
||||
Map::new(||connections.iter(), move|connect: &'a Connect, index|map_south(index as u16, 1,
|
||||
Fill::Y(Align::w(Tui::bold(false, Tui::fg_bg(fg, bg,
|
||||
iter_south(y as u16, (y2-y) as u16, south(
|
||||
h_full(Tui::bold(true, Tui::fg_bg(fg, bg, origin_w(east(&" ", name))))),
|
||||
iter(||connections.iter(), move|connect: &'a Connect, index|iter_south(index as u16, 1,
|
||||
h_full(origin_w(Tui::bold(false, Tui::fg_bg(fg, bg,
|
||||
&connect.info)))))))))
|
||||
}
|
||||
}
|
||||
|
|
@ -1210,5 +1213,5 @@ pub const NOTE_NAMES: [&str; 128] = [
|
|||
pub(crate) const HEADER: &'static str = r#"
|
||||
|
||||
~ █▀█▀█ █▀▀█ █ █ ~~~ ~ ~ ~~ ~ ~ ~ ~~ ~ ~ ~ ~
|
||||
█ █▀ █▀▀▄ ~ v0.4.0, 2026 winter (or is it) ~
|
||||
█ term█▀ █▀▀▄ ~ v0.4.0, 2026 winter (or is it) ~
|
||||
~ ▀ █▀▀█ ▀ ▀ ~ ~~~ ~ ~ ~ ~ ~~~ ~~~ ~ ~~ "#;
|
||||
|
|
|
|||
364
app/tek_impls.rs
364
app/tek_impls.rs
|
|
@ -73,7 +73,7 @@ impl <T: AsRefOpt<MidiEditor>+AsMutOpt<MidiEditor>> HasE
|
|||
impl <T: AsRefOpt<Scene>+AsMutOpt<Scene>+Send+Sync> HasScene for T {}
|
||||
impl <T: AsRefOpt<Track>+AsMutOpt<Track>+Send+Sync> HasTrack for T {}
|
||||
impl <T: NotePoint+TimePoint> MidiPoint for T {}
|
||||
impl <T: ScenesView+HasMidiIns+HasMidiOuts+HasTrackScroll+Measured<TuiOut>> TracksView for T {}
|
||||
impl <T: ScenesView+HasMidiIns+HasMidiOuts+HasTrackScroll+Measured<Tui>> TracksView for T {}
|
||||
impl <T: TimeRange+NoteRange> MidiRange for T {}
|
||||
impl <T: TracksView+ScenesView+Send+Sync> ClipsView for T {}
|
||||
|
||||
|
|
@ -84,24 +84,24 @@ mod app {
|
|||
impl_has!(Vec<MidiOutput>: |self: App|self.project.midi_outs);
|
||||
impl_has!(Dialog: |self: App|self.dialog);
|
||||
impl_has!(Jack<'static>: |self: App|self.jack);
|
||||
impl_has!(Measure<TuiOut>: |self: App|self.size);
|
||||
impl_has!(Measure<Tui>: |self: App|self.size);
|
||||
impl_has!(Pool: |self: App|self.pool);
|
||||
impl_has!(Selection: |self: App|self.project.selection);
|
||||
impl_as_ref!(Vec<Scene>: |self: App|self.project.as_ref());
|
||||
impl_as_mut!(Vec<Scene>: |self: App|self.project.as_mut());
|
||||
impl_as_ref_opt!(MidiEditor: |self: App|self.project.as_ref_opt());
|
||||
impl_as_mut_opt!(MidiEditor: |self: App|self.project.as_mut_opt());
|
||||
has_clips!( |self: App|self.pool.clips);
|
||||
impl_has_clips!( |self: App|self.pool.clips);
|
||||
impl_audio!(App: tek_jack_process, tek_jack_event);
|
||||
handle!(TuiIn: |self: App, input|{
|
||||
impl_handle!(TuiIn: |self: App, input|{
|
||||
let commands = collect_commands(self, input)?;
|
||||
let history = execute_commands(self, commands)?;
|
||||
self.history.extend(history.into_iter());
|
||||
Ok(None)
|
||||
});
|
||||
|
||||
impl Draw<TuiOut> for App {
|
||||
fn draw (&self, to: &mut TuiOut) {
|
||||
impl Draw<Tui> for App {
|
||||
fn draw (self, to: &mut Tui) -> Usually<XYWH<u16>> {
|
||||
if let Some(e) = self.error.read().unwrap().as_ref() {
|
||||
to.show(to.area(), e);
|
||||
}
|
||||
|
|
@ -125,16 +125,16 @@ mod app {
|
|||
});
|
||||
}
|
||||
|
||||
impl Understand<TuiOut, ()> for App {
|
||||
fn understand_expr <'a> (&'a self, to: &mut TuiOut, lang: &'a impl Expression) -> Usually<()> {
|
||||
impl Understand<Tui, ()> for App {
|
||||
fn understand_expr <'a> (&'a self, to: &mut Tui, lang: &'a impl Expression) -> Usually<()> {
|
||||
app_understand_expr(self, to, lang)
|
||||
}
|
||||
fn understand_word <'a> (&'a self, to: &mut TuiOut, lang: &'a impl Expression) -> Usually<()> {
|
||||
fn understand_word <'a> (&'a self, to: &mut Tui, lang: &'a impl Expression) -> Usually<()> {
|
||||
app_understand_word(self, to, lang)
|
||||
}
|
||||
}
|
||||
|
||||
fn app_understand_expr (state: &App, to: &mut TuiOut, lang: &impl Expression) -> Usually<()> {
|
||||
fn app_understand_expr (state: &App, to: &mut Tui, lang: &impl Expression) -> Usually<()> {
|
||||
if evaluate_output_expression(state, to, lang)?
|
||||
|| evaluate_output_expression_tui(state, to, lang)? {
|
||||
Ok(())
|
||||
|
|
@ -143,22 +143,22 @@ mod app {
|
|||
}
|
||||
}
|
||||
|
||||
fn app_understand_word (state: &App, to: &mut TuiOut, dsl: &impl Expression) -> Usually<()> {
|
||||
fn app_understand_word (state: &App, to: &mut Tui, dsl: &impl Expression) -> Usually<()> {
|
||||
let mut frags = dsl.src()?.unwrap().split("/");
|
||||
match frags.next() {
|
||||
Some(":logo") => to.place(&view_logo()),
|
||||
Some(":status") => to.place(&Fixed::Y(1, "TODO: Status Bar")),
|
||||
Some(":status") => to.place(&h_exact(1, "TODO: Status Bar")),
|
||||
Some(":meters") => match frags.next() {
|
||||
Some("input") => to.place(&Tui::bg(Rgb(30, 30, 30), Fill::Y(Align::s("Input Meters")))),
|
||||
Some("output") => to.place(&Tui::bg(Rgb(30, 30, 30), Fill::Y(Align::s("Output Meters")))),
|
||||
Some("input") => to.place(&Tui::bg(Rgb(30, 30, 30), h_full(origin_s("Input Meters")))),
|
||||
Some("output") => to.place(&Tui::bg(Rgb(30, 30, 30), h_full(origin_s("Output Meters")))),
|
||||
_ => panic!()
|
||||
},
|
||||
Some(":tracks") => match frags.next() {
|
||||
None => to.place(&"TODO tracks"),
|
||||
Some("names") => to.place(&state.project.view_track_names(state.color.clone())),//Tui::bg(Rgb(40, 40, 40), Fill::X(Align::w("Track Names")))),
|
||||
Some("inputs") => to.place(&Tui::bg(Rgb(40, 40, 40), Fill::X(Align::w("Track Inputs")))),
|
||||
Some("devices") => to.place(&Tui::bg(Rgb(40, 40, 40), Fill::X(Align::w("Track Devices")))),
|
||||
Some("outputs") => to.place(&Tui::bg(Rgb(40, 40, 40), Fill::X(Align::w("Track Outputs")))),
|
||||
Some("names") => to.place(&state.project.view_track_names(state.color.clone())),//Tui::bg(Rgb(40, 40, 40), w_full(origin_w("Track Names")))),
|
||||
Some("inputs") => to.place(&Tui::bg(Rgb(40, 40, 40), w_full(origin_w("Track Inputs")))),
|
||||
Some("devices") => to.place(&Tui::bg(Rgb(40, 40, 40), w_full(origin_w("Track Devices")))),
|
||||
Some("outputs") => to.place(&Tui::bg(Rgb(40, 40, 40), w_full(origin_w("Track Outputs")))),
|
||||
_ => panic!()
|
||||
},
|
||||
Some(":scenes") => match frags.next() {
|
||||
|
|
@ -171,13 +171,13 @@ mod app {
|
|||
Some("menu") => to.place(&if let Dialog::Menu(selected, items) = &state.dialog {
|
||||
let items = items.clone();
|
||||
let selected = selected;
|
||||
Some(Fill::XY(Thunk::new(move|to: &mut TuiOut|{
|
||||
Some(wh_full(Thunk::new(move|to: &mut Tui|{
|
||||
for (index, MenuItem(item, _)) in items.0.iter().enumerate() {
|
||||
to.place(&Push::Y((2 * index) as u16,
|
||||
to.place(&y_push((2 * index) as u16,
|
||||
Tui::fg_bg(
|
||||
if *selected == index { Rgb(240,200,180) } else { Rgb(200, 200, 200) },
|
||||
if *selected == index { Rgb(80, 80, 50) } else { Rgb(30, 30, 30) },
|
||||
Fixed::Y(2, Align::n(Fill::X(item)))
|
||||
h_exact(2, origin_n(w_full(item)))
|
||||
)));
|
||||
}
|
||||
})))
|
||||
|
|
@ -189,31 +189,31 @@ mod app {
|
|||
Some(":templates") => to.place(&{
|
||||
let modes = state.config.modes.clone();
|
||||
let height = (modes.read().unwrap().len() * 2) as u16;
|
||||
Fixed::Y(height, Min::X(30, Thunk::new(move |to: &mut TuiOut|{
|
||||
h_exact(height, w_min(30, Thunk::new(move |to: &mut Tui|{
|
||||
for (index, (id, profile)) in modes.read().unwrap().iter().enumerate() {
|
||||
let bg = if index == 0 { Rgb(70,70,70) } else { Rgb(50,50,50) };
|
||||
let name = profile.name.get(0).map(|x|x.as_ref()).unwrap_or("<no name>");
|
||||
let info = profile.info.get(0).map(|x|x.as_ref()).unwrap_or("<no info>");
|
||||
let fg1 = Rgb(224, 192, 128);
|
||||
let fg2 = Rgb(224, 128, 32);
|
||||
let field_name = Fill::X(Align::w(Tui::fg(fg1, name)));
|
||||
let field_id = Fill::X(Align::e(Tui::fg(fg2, id)));
|
||||
let field_info = Fill::X(Align::w(info));
|
||||
to.place(&Push::Y((2 * index) as u16,
|
||||
Fixed::Y(2, Fill::X(Tui::bg(bg, Bsp::s(
|
||||
Bsp::a(field_name, field_id), field_info))))));
|
||||
let field_name = w_full(origin_w(Tui::fg(fg1, name)));
|
||||
let field_id = w_full(origin_e(Tui::fg(fg2, id)));
|
||||
let field_info = w_full(origin_w(info));
|
||||
to.place(&y_push((2 * index) as u16,
|
||||
h_exact(2, w_full(Tui::bg(bg, south(
|
||||
above(field_name, field_id), field_info))))));
|
||||
}
|
||||
})))
|
||||
}),
|
||||
Some(":sessions") => to.place(&Fixed::Y(6, Min::X(30, Thunk::new(|to: &mut TuiOut|{
|
||||
Some(":sessions") => to.place(&h_exact(6, w_min(30, Thunk::new(|to: &mut Tui|{
|
||||
let fg = Rgb(224, 192, 128);
|
||||
for (index, name) in ["session1", "session2", "session3"].iter().enumerate() {
|
||||
let bg = if index == 0 { Rgb(50,50,50) } else { Rgb(40,40,40) };
|
||||
to.place(&Push::Y((2 * index) as u16,
|
||||
&Fixed::Y(2, Fill::X(Tui::bg(bg, Align::w(Tui::fg(fg, name)))))));
|
||||
to.place(&y_push((2 * index) as u16,
|
||||
&h_exact(2, w_full(Tui::bg(bg, origin_w(Tui::fg(fg, name)))))));
|
||||
}
|
||||
})))),
|
||||
Some(":browse/title") => to.place(&Fill::X(Align::w(FieldV(ItemColor::default(),
|
||||
Some(":browse/title") => to.place(&w_full(origin_w(field_v(ItemColor::default(),
|
||||
match state.dialog.browser_target().unwrap() {
|
||||
BrowseTarget::SaveProject => "Save project:",
|
||||
BrowseTarget::LoadProject => "Load project:",
|
||||
|
|
@ -221,18 +221,18 @@ mod app {
|
|||
BrowseTarget::ExportSample(_) => "Export sample:",
|
||||
BrowseTarget::ImportClip(_) => "Import clip:",
|
||||
BrowseTarget::ExportClip(_) => "Export clip:",
|
||||
}, Shrink::X(3, Fixed::Y(1, Tui::fg(Tui::g(96), Repeat::X("🭻")))))))),
|
||||
}, w_shrink(3, h_exact(1, Tui::fg(Tui::g(96), x_repeat("🭻")))))))),
|
||||
Some(":device") => {
|
||||
let selected = state.dialog.device_kind().unwrap();
|
||||
to.place(&Bsp::s(Tui::bold(true, "Add device"), Map::south(1,
|
||||
to.place(&south(Tui::bold(true, "Add device"), iter_south(1,
|
||||
move||device_kinds().iter(),
|
||||
move|_label: &&'static str, i|{
|
||||
let bg = if i == selected { Rgb(64,128,32) } else { Rgb(0,0,0) };
|
||||
let lb = if i == selected { "[ " } else { " " };
|
||||
let rb = if i == selected { " ]" } else { " " };
|
||||
Fill::X(Tui::bg(bg, Bsp::e(lb, Bsp::w(rb, "FIXME device name")))) })))
|
||||
w_full(Tui::bg(bg, east(lb, west(rb, "FIXME device name")))) })))
|
||||
},
|
||||
Some(":debug") => to.place(&Fixed::Y(1, format!("[{:?}]", to.area()))),
|
||||
Some(":debug") => to.place(&h_exact(1, format!("[{:?}]", to.area()))),
|
||||
Some(_) => {
|
||||
let views = state.config.views.read().unwrap();
|
||||
if let Some(dsl) = views.get(dsl.src()?.unwrap()) {
|
||||
|
|
@ -375,7 +375,7 @@ mod app {
|
|||
mod arrange {
|
||||
use crate::*;
|
||||
impl_has!(Jack<'static>: |self: Arrangement| self.jack);
|
||||
impl_has!(Measure<TuiOut>: |self: Arrangement| self.size);
|
||||
impl_has!(Measure<Tui>: |self: Arrangement| self.size);
|
||||
impl_has!(Vec<Track>: |self: Arrangement| self.tracks);
|
||||
impl_has!(Vec<Scene>: |self: Arrangement| self.scenes);
|
||||
impl_has!(Vec<MidiInput>: |self: Arrangement| self.midi_ins);
|
||||
|
|
@ -479,79 +479,79 @@ mod arrange {
|
|||
}
|
||||
Ok((index, &mut self.tracks_mut()[index]))
|
||||
}
|
||||
#[cfg(feature = "track")] pub fn view_inputs (&self, _theme: ItemTheme) -> impl Content<TuiOut> + '_ {
|
||||
Bsp::s(
|
||||
Fixed::Y(1, self.view_inputs_header()),
|
||||
Thunk::new(|to: &mut TuiOut|{
|
||||
#[cfg(feature = "track")] pub fn view_inputs (&self, _theme: ItemTheme) -> impl Draw<Tui> + '_ {
|
||||
south(
|
||||
h_exact(1, self.view_inputs_header()),
|
||||
Thunk::new(|to: &mut Tui|{
|
||||
for (index, port) in self.midi_ins().iter().enumerate() {
|
||||
to.place(&Push::X(index as u16 * 10, Fixed::Y(1, self.view_inputs_row(port))))
|
||||
to.place(&x_push(index as u16 * 10, h_exact(1, self.view_inputs_row(port))))
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
#[cfg(feature = "track")] fn view_inputs_header (&self) -> impl Content<TuiOut> + '_ {
|
||||
Bsp::e(Fixed::X(20, Align::w(button_3("i", "nput ", format!("{}", self.midi_ins.len()), false))),
|
||||
Bsp::w(Fixed::X(4, button_2("I", "+", false)), Thunk::new(move|to: &mut TuiOut|for (_index, track, x1, _x2) in self.tracks_with_sizes() {
|
||||
#[cfg(feature = "track")] fn view_inputs_header (&self) -> impl Draw<Tui> + '_ {
|
||||
east(w_exact(20, origin_w(button_3("i", "nput ", format!("{}", self.midi_ins.len()), false))),
|
||||
west(w_exact(4, button_2("I", "+", false)), Thunk::new(move|to: &mut Tui|for (_index, track, x1, _x2) in self.tracks_with_sizes() {
|
||||
#[cfg(feature = "track")]
|
||||
to.place(&Push::X(x1 as u16, Tui::bg(track.color.dark.rgb, Align::w(Fixed::X(track.width as u16, row!(
|
||||
Either::new(track.sequencer.monitoring, Tui::fg(Green, "mon "), "mon "),
|
||||
Either::new(track.sequencer.recording, Tui::fg(Red, "rec "), "rec "),
|
||||
Either::new(track.sequencer.overdub, Tui::fg(Yellow, "dub "), "dub "),
|
||||
to.place(&x_push(x1 as u16, Tui::bg(track.color.dark.rgb, origin_w(w_exact(track.width as u16, east!(
|
||||
either(track.sequencer.monitoring, Tui::fg(Green, "mon "), "mon "),
|
||||
either(track.sequencer.recording, Tui::fg(Red, "rec "), "rec "),
|
||||
either(track.sequencer.overdub, Tui::fg(Yellow, "dub "), "dub "),
|
||||
))))))
|
||||
})))
|
||||
}
|
||||
#[cfg(feature = "track")] fn view_inputs_row (&self, port: &MidiInput) -> impl Content<TuiOut> {
|
||||
Bsp::e(Fixed::X(20, Align::w(Bsp::e(" ● ", Tui::bold(true, Tui::fg(Rgb(255,255,255), port.port_name()))))),
|
||||
Bsp::w(Fixed::X(4, ()), Thunk::new(move|to: &mut TuiOut|for (_index, track, _x1, _x2) in self.tracks_with_sizes() {
|
||||
#[cfg(feature = "track")] fn view_inputs_row (&self, port: &MidiInput) -> impl Draw<Tui> {
|
||||
east(w_exact(20, origin_w(east(" ● ", Tui::bold(true, Tui::fg(Rgb(255,255,255), port.port_name()))))),
|
||||
west(w_exact(4, ()), Thunk::new(move|to: &mut Tui|for (_index, track, _x1, _x2) in self.tracks_with_sizes() {
|
||||
#[cfg(feature = "track")]
|
||||
to.place(&Tui::bg(track.color.darker.rgb, Align::w(Fixed::X(track.width as u16, row!(
|
||||
Either::new(track.sequencer.monitoring, Tui::fg(Green, " ● "), " · "),
|
||||
Either::new(track.sequencer.recording, Tui::fg(Red, " ● "), " · "),
|
||||
Either::new(track.sequencer.overdub, Tui::fg(Yellow, " ● "), " · "),
|
||||
to.place(&Tui::bg(track.color.darker.rgb, origin_w(w_exact(track.width as u16, east!(
|
||||
either(track.sequencer.monitoring, Tui::fg(Green, " ● "), " · "),
|
||||
either(track.sequencer.recording, Tui::fg(Red, " ● "), " · "),
|
||||
either(track.sequencer.overdub, Tui::fg(Yellow, " ● "), " · "),
|
||||
)))))
|
||||
})))
|
||||
}
|
||||
#[cfg(feature = "track")] pub fn view_outputs (&self, theme: ItemTheme) -> impl Content<TuiOut> {
|
||||
#[cfg(feature = "track")] pub fn view_outputs (&self, theme: ItemTheme) -> impl Draw<Tui> {
|
||||
let mut h = 1;
|
||||
for output in self.midi_outs().iter() {
|
||||
h += 1 + output.connections.len();
|
||||
}
|
||||
let h = h as u16;
|
||||
let list = Bsp::s(
|
||||
Fixed::Y(1, Fill::X(Align::w(button_3("o", "utput", format!("{}", self.midi_outs.len()), false)))),
|
||||
Fixed::Y(h - 1, Fill::XY(Align::nw(Thunk::new(|to: &mut TuiOut|{
|
||||
let list = south(
|
||||
h_exact(1, w_full(origin_w(button_3("o", "utput", format!("{}", self.midi_outs.len()), false)))),
|
||||
h_exact(h - 1, wh_full(origin_nw(Thunk::new(|to: &mut Tui|{
|
||||
for (_index, port) in self.midi_outs().iter().enumerate() {
|
||||
to.place(&Fixed::Y(1,Fill::X(Bsp::e(
|
||||
Align::w(Bsp::e(" ● ", Tui::fg(Rgb(255,255,255),Tui::bold(true, port.port_name())))),
|
||||
Fill::X(Align::e(format!("{}/{} ",
|
||||
to.place(&h_exact(1,w_full(east(
|
||||
origin_w(east(" ● ", Tui::fg(Rgb(255,255,255),Tui::bold(true, port.port_name())))),
|
||||
w_full(origin_e(format!("{}/{} ",
|
||||
port.port().get_connections().len(),
|
||||
port.connections.len())))))));
|
||||
for (index, conn) in port.connections.iter().enumerate() {
|
||||
to.place(&Fixed::Y(1, Fill::X(Align::w(format!(" c{index:02}{}", conn.info())))));
|
||||
to.place(&h_exact(1, w_full(origin_w(format!(" c{index:02}{}", conn.info())))));
|
||||
}
|
||||
}
|
||||
})))));
|
||||
Fixed::Y(h, view_track_row_section(theme, list, button_2("O", "+", false),
|
||||
Tui::bg(theme.darker.rgb, Align::w(Fill::X(
|
||||
Thunk::new(|to: &mut TuiOut|{
|
||||
h_exact(h, view_track_row_section(theme, list, button_2("O", "+", false),
|
||||
Tui::bg(theme.darker.rgb, origin_w(w_full(
|
||||
Thunk::new(|to: &mut Tui|{
|
||||
for (index, track, _x1, _x2) in self.tracks_with_sizes() {
|
||||
to.place(&Fixed::X(track_width(index, track),
|
||||
Thunk::new(|to: &mut TuiOut|{
|
||||
to.place(&Fixed::Y(1, Align::w(Bsp::e(
|
||||
Either::new(true, Tui::fg(Green, "play "), "play "),
|
||||
Either::new(false, Tui::fg(Yellow, "solo "), "solo "),
|
||||
to.place(&w_exact(track_width(index, track),
|
||||
Thunk::new(|to: &mut Tui|{
|
||||
to.place(&h_exact(1, origin_w(east(
|
||||
either(true, Tui::fg(Green, "play "), "play "),
|
||||
either(false, Tui::fg(Yellow, "solo "), "solo "),
|
||||
))));
|
||||
for (_index, port) in self.midi_outs().iter().enumerate() {
|
||||
to.place(&Fixed::Y(1, Align::w(Bsp::e(
|
||||
Either::new(true, Tui::fg(Green, " ● "), " · "),
|
||||
Either::new(false, Tui::fg(Yellow, " ● "), " · "),
|
||||
to.place(&h_exact(1, origin_w(east(
|
||||
either(true, Tui::fg(Green, " ● "), " · "),
|
||||
either(false, Tui::fg(Yellow, " ● "), " · "),
|
||||
))));
|
||||
for (_index, _conn) in port.connections.iter().enumerate() {
|
||||
to.place(&Fixed::Y(1, Fill::X("")));
|
||||
to.place(&h_exact(1, w_full("")));
|
||||
}
|
||||
}})))}}))))))
|
||||
}
|
||||
#[cfg(feature = "track")] pub fn view_track_devices (&self, theme: ItemTheme) -> impl Content<TuiOut> {
|
||||
#[cfg(feature = "track")] pub fn view_track_devices (&self, theme: ItemTheme) -> impl Draw<Tui> {
|
||||
let mut h = 2u16;
|
||||
for track in self.tracks().iter() {
|
||||
h = h.max(track.devices.len() as u16 * 2);
|
||||
|
|
@ -559,14 +559,14 @@ mod arrange {
|
|||
view_track_row_section(theme,
|
||||
button_3("d", "evice", format!("{}", self.track().map(|t|t.devices.len()).unwrap_or(0)), false),
|
||||
button_2("D", "+", false),
|
||||
Thunk::new(move|to: &mut TuiOut|for (index, track, _x1, _x2) in self.tracks_with_sizes() {
|
||||
to.place(&Fixed::XY(track_width(index, track), h + 1,
|
||||
Tui::bg(track.color.dark.rgb, Align::nw(Map::south(2, move||0..h,
|
||||
|_, _index|Fixed::XY(track.width as u16, 2,
|
||||
Thunk::new(move|to: &mut Tui|for (index, track, _x1, _x2) in self.tracks_with_sizes() {
|
||||
to.place(&wh_exact(track_width(index, track), h + 1,
|
||||
Tui::bg(track.color.dark.rgb, origin_nw(iter_south(2, move||0..h,
|
||||
|_, _index|wh_exact(track.width as u16, 2,
|
||||
Tui::fg_bg(
|
||||
ItemTheme::G[32].lightest.rgb,
|
||||
ItemTheme::G[32].dark.rgb,
|
||||
Align::nw(format!(" · {}", "--")))))))));
|
||||
origin_nw(format!(" · {}", "--")))))))));
|
||||
}))
|
||||
}
|
||||
/// Put a clip in a slot
|
||||
|
|
@ -616,7 +616,7 @@ mod arrange {
|
|||
}
|
||||
}
|
||||
impl HasClipsSize for Arrangement {
|
||||
fn clips_size (&self) -> &Measure<TuiOut> { &self.size_inner }
|
||||
fn clips_size (&self) -> &Measure<Tui> { &self.size_inner }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -657,14 +657,14 @@ mod browse {
|
|||
fn _todo_stub_usize (&self) -> usize { todo!() }
|
||||
fn _todo_stub_arc_str (&self) -> Arc<str> { todo!() }
|
||||
}
|
||||
impl HasContent<TuiOut> for Browse {
|
||||
fn content (&self) -> impl Content<TuiOut> {
|
||||
Map::south(1, ||EntriesIterator {
|
||||
impl Browse {
|
||||
fn tui (&self) -> impl Draw<Tui> {
|
||||
iter_south(1, ||EntriesIterator {
|
||||
offset: 0,
|
||||
index: 0,
|
||||
length: self.dirs.len() + self.files.len(),
|
||||
browser: self,
|
||||
}, |entry, _index|Fill::X(Align::w(entry)))
|
||||
}, |entry, _index|w_full(origin_w(entry)))
|
||||
}
|
||||
}
|
||||
impl<'a> Iterator for EntriesIterator<'a> {
|
||||
|
|
@ -1117,7 +1117,7 @@ impl InteriorMutable<usize> for AtomicUsize { fn set (&self, value: usize) -> us
|
|||
|
||||
impl PartialEq for MenuItem { fn eq (&self, other: &Self) -> bool { self.0 == other.0 } }
|
||||
impl AsRef<Arc<[MenuItem]>> for MenuItems { fn as_ref (&self) -> &Arc<[MenuItem]> { &self.0 } }
|
||||
impl HasClipsSize for App { fn clips_size (&self) -> &Measure<TuiOut> { &self.project.size_inner } }
|
||||
impl HasClipsSize for App { fn clips_size (&self) -> &Measure<Tui> { &self.project.size_inner } }
|
||||
impl HasJack<'static> for MidiInput { fn jack (&self) -> &Jack<'static> { &self.jack } }
|
||||
impl HasJack<'static> for MidiOutput { fn jack (&self) -> &Jack<'static> { &self.jack } }
|
||||
impl HasJack<'static> for AudioInput { fn jack (&self) -> &Jack<'static> { &self.jack } }
|
||||
|
|
@ -1795,11 +1795,8 @@ mod audio {
|
|||
mod meter {
|
||||
use crate::*;
|
||||
|
||||
impl Layout<TuiOut> for RmsMeter {}
|
||||
impl Layout<TuiOut> for Log10Meter {}
|
||||
|
||||
impl Draw<TuiOut> for RmsMeter {
|
||||
fn draw (&self, to: &mut TuiOut) {
|
||||
impl Draw<Tui> for RmsMeter {
|
||||
fn draw(self, to: &mut Tui) -> Usually<XYWH<u16>> {
|
||||
let XYWH(x, y, w, h) = to.area();
|
||||
let signal = f32::max(0.0, f32::min(100.0, self.0.abs()));
|
||||
let v = (signal * h as f32).ceil() as u16;
|
||||
|
|
@ -1813,8 +1810,8 @@ mod audio {
|
|||
}
|
||||
}
|
||||
|
||||
impl Draw<TuiOut> for Log10Meter {
|
||||
fn draw (&self, to: &mut TuiOut) {
|
||||
impl Draw<Tui> for Log10Meter {
|
||||
fn draw(self, to: &mut Tui) -> Usually<XYWH<u16>> {
|
||||
let XYWH(x, y, w, h) = to.area();
|
||||
let signal = 100.0 - f32::max(0.0, f32::min(100.0, self.0.abs()));
|
||||
let v = (signal * h as f32 / 100.0).ceil() as u16;
|
||||
|
|
@ -1828,9 +1825,9 @@ mod audio {
|
|||
}
|
||||
}
|
||||
|
||||
fn draw_meters (meters: &[f32]) -> impl Content<TuiOut> + use<'_> {
|
||||
Tui::bg(Black, Fixed::X(2, Map::east(1, ||meters.iter(), |value, _index|{
|
||||
Fill::Y(RmsMeter(*value))
|
||||
fn draw_meters (meters: &[f32]) -> impl Draw<Tui> + use<'_> {
|
||||
Tui::bg(Black, w_exact(2, iter_east(1, ||meters.iter(), |value, _index|{
|
||||
h_full(RmsMeter(*value))
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
|
@ -1879,14 +1876,14 @@ mod audio {
|
|||
fn _todo_usize_stub_ (&self) -> usize { todo!() }
|
||||
fn _todo_arc_str_stub_ (&self) -> Arc<str> { todo!() }
|
||||
fn _todo_item_theme_stub (&self) -> ItemTheme { todo!() }
|
||||
pub fn per <'a, T: Content<TuiOut> + 'a, U: TracksSizes<'a>> (
|
||||
pub fn per <'a, T: Draw<Tui> + 'a, U: TracksSizes<'a>> (
|
||||
tracks: impl Fn() -> U + Send + Sync + 'a,
|
||||
callback: impl Fn(usize, &'a Track)->T + Send + Sync + 'a
|
||||
) -> impl Content<TuiOut> + 'a {
|
||||
Map::new(tracks,
|
||||
) -> impl Draw<Tui> + 'a {
|
||||
iter(tracks,
|
||||
move|(index, track, x1, x2): (usize, &'a Track, usize, usize), _|{
|
||||
let width = (x2 - x1) as u16;
|
||||
map_east(x1 as u16, width, Fixed::X(width, Tui::fg_bg(
|
||||
iter_east(x1 as u16, width, w_exact(width, Tui::fg_bg(
|
||||
track.color.lightest.rgb,
|
||||
track.color.base.rgb,
|
||||
callback(index, track))))})
|
||||
|
|
@ -1932,21 +1929,21 @@ mod audio {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn per_track <'a, T: Content<TuiOut> + 'a, U: TracksSizes<'a>> (
|
||||
pub fn per_track <'a, T: Draw<Tui> + 'a, U: TracksSizes<'a>> (
|
||||
tracks: impl Fn() -> U + Send + Sync + 'a,
|
||||
callback: impl Fn(usize, &'a Track)->T + Send + Sync + 'a
|
||||
) -> impl Content<TuiOut> + 'a {
|
||||
per_track_top(tracks, move|index, track|Fill::Y(Align::y(callback(index, track))))
|
||||
) -> impl Draw<Tui> + 'a {
|
||||
per_track_top(tracks, move|index, track|h_full(origin_y(callback(index, track))))
|
||||
}
|
||||
|
||||
pub fn per_track_top <'a, T: Content<TuiOut> + 'a, U: TracksSizes<'a>> (
|
||||
pub fn per_track_top <'a, T: Draw<Tui> + 'a, U: TracksSizes<'a>> (
|
||||
tracks: impl Fn() -> U + Send + Sync + 'a,
|
||||
callback: impl Fn(usize, &'a Track)->T + Send + Sync + 'a
|
||||
) -> impl Content<TuiOut> + 'a {
|
||||
Align::x(Tui::bg(Reset, Map::new(tracks,
|
||||
) -> impl Draw<Tui> + 'a {
|
||||
origin_x(Tui::bg(Reset, iter(tracks,
|
||||
move|(index, track, x1, x2): (usize, &'a Track, usize, usize), _|{
|
||||
let width = (x2 - x1) as u16;
|
||||
map_east(x1 as u16, width, Fixed::X(width, Tui::fg_bg(
|
||||
iter_east(x1 as u16, width, w_exact(width, Tui::fg_bg(
|
||||
track.color.lightest.rgb,
|
||||
track.color.base.rgb,
|
||||
callback(index, track))))})))
|
||||
|
|
@ -2007,8 +2004,8 @@ mod audio {
|
|||
impl_has!(Clock: |self: Sequencer| self.clock);
|
||||
impl_has!(Vec<MidiInput>: |self: Sequencer| self.midi_ins);
|
||||
impl_has!(Vec<MidiOutput>: |self: Sequencer| self.midi_outs);
|
||||
impl_has!(Measure<TuiOut>: |self: MidiEditor| self.size);
|
||||
impl_has!(Measure<TuiOut>: |self: PianoHorizontal| self.size);
|
||||
impl_has!(Measure<Tui>: |self: MidiEditor| self.size);
|
||||
impl_has!(Measure<Tui>: |self: PianoHorizontal| self.size);
|
||||
impl_default!(Sequencer: Self {
|
||||
clock: Clock::default(),
|
||||
play_clip: None,
|
||||
|
|
@ -2224,11 +2221,15 @@ mod audio {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl Draw<TuiOut> for MidiEditor {
|
||||
fn draw (&self, to: &mut TuiOut) { self.content().draw(to) }
|
||||
impl Draw<Tui> for MidiEditor {
|
||||
fn draw(self, to: &mut Tui) -> Usually<XYWH<u16>> {
|
||||
self.tui().draw(to)
|
||||
}
|
||||
}
|
||||
impl Draw<Tui> for PianoHorizontal {
|
||||
fn draw(self, to: &mut Tui) -> Usually<XYWH<u16>> {
|
||||
self.tui().draw(to)
|
||||
}
|
||||
impl Draw<TuiOut> for PianoHorizontal {
|
||||
fn draw (&self, to: &mut TuiOut) { self.content().draw(to) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2320,23 +2321,23 @@ mod audio {
|
|||
self.get_time_pos().overflowing_sub(1)
|
||||
.0.min(self.clip_length().saturating_sub(1))
|
||||
}
|
||||
pub fn clip_status (&self) -> impl Content<TuiOut> + '_ {
|
||||
pub fn clip_status (&self) -> impl Draw<Tui> + '_ {
|
||||
let (_color, name, length, looped) = if let Some(clip) = self.clip().as_ref().map(|p|p.read().unwrap()) {
|
||||
(clip.color, clip.name.clone(), clip.length, clip.looped)
|
||||
} else { (ItemTheme::G[64], String::new().into(), 0, false) };
|
||||
Fixed::X(20, col!(
|
||||
Fill::X(Align::w(Bsp::e(
|
||||
w_exact(20, south!(
|
||||
w_full(origin_w(east(
|
||||
button_2("f2", "name ", false),
|
||||
Fill::X(Align::e(Tui::fg(Rgb(255, 255, 255), format!("{name} "))))))),
|
||||
Fill::X(Align::w(Bsp::e(
|
||||
w_full(origin_e(Tui::fg(Rgb(255, 255, 255), format!("{name} "))))))),
|
||||
w_full(origin_w(east(
|
||||
button_2("l", "ength ", false),
|
||||
Fill::X(Align::e(Tui::fg(Rgb(255, 255, 255), format!("{length} "))))))),
|
||||
Fill::X(Align::w(Bsp::e(
|
||||
w_full(origin_e(Tui::fg(Rgb(255, 255, 255), format!("{length} "))))))),
|
||||
w_full(origin_w(east(
|
||||
button_2("r", "epeat ", false),
|
||||
Fill::X(Align::e(Tui::fg(Rgb(255, 255, 255), format!("{looped} "))))))),
|
||||
w_full(origin_e(Tui::fg(Rgb(255, 255, 255), format!("{looped} "))))))),
|
||||
))
|
||||
}
|
||||
pub fn edit_status (&self) -> impl Content<TuiOut> + '_ {
|
||||
pub fn edit_status (&self) -> impl Draw<Tui> + '_ {
|
||||
let (_color, length) = if let Some(clip) = self.clip().as_ref().map(|p|p.read().unwrap()) {
|
||||
(clip.color, clip.length)
|
||||
} else { (ItemTheme::G[64], 0) };
|
||||
|
|
@ -2347,18 +2348,18 @@ mod audio {
|
|||
let note_name = format!("{:4}", note_pitch_to_name(note_pos));
|
||||
let note_pos = format!("{:>3}", note_pos);
|
||||
let note_len = format!("{:>4}", self.get_note_len());
|
||||
Fixed::X(20, col!(
|
||||
Fill::X(Align::w(Bsp::e(
|
||||
w_exact(20, south!(
|
||||
w_full(origin_w(east(
|
||||
button_2("t", "ime ", false),
|
||||
Fill::X(Align::e(Tui::fg(Rgb(255, 255, 255),
|
||||
w_full(origin_e(Tui::fg(Rgb(255, 255, 255),
|
||||
format!("{length} /{time_zoom} +{time_pos} "))))))),
|
||||
Fill::X(Align::w(Bsp::e(
|
||||
w_full(origin_w(east(
|
||||
button_2("z", "lock ", false),
|
||||
Fill::X(Align::e(Tui::fg(Rgb(255, 255, 255),
|
||||
w_full(origin_e(Tui::fg(Rgb(255, 255, 255),
|
||||
format!("{time_lock}"))))))),
|
||||
Fill::X(Align::w(Bsp::e(
|
||||
w_full(origin_w(east(
|
||||
button_2("x", "note ", false),
|
||||
Fill::X(Align::e(Tui::fg(Rgb(255, 255, 255),
|
||||
w_full(origin_e(Tui::fg(Rgb(255, 255, 255),
|
||||
format!("{note_name} {note_pos} {note_len}"))))))),
|
||||
))
|
||||
}
|
||||
|
|
@ -2394,12 +2395,8 @@ mod audio {
|
|||
fn set_clip (&mut self, p: Option<&Arc<RwLock<MidiClip>>>) { self.mode.set_clip(p) }
|
||||
}
|
||||
|
||||
impl Layout<TuiOut> for MidiEditor {
|
||||
fn layout (&self, to: XYWH<u16>) -> XYWH<u16> { self.content().layout(to) }
|
||||
}
|
||||
|
||||
impl HasContent<TuiOut> for MidiEditor {
|
||||
fn content (&self) -> impl Content<TuiOut> { self.autoscroll(); /*self.autozoom();*/ self.size.of(&self.mode) }
|
||||
impl MidiEditor {
|
||||
fn tui (&self) -> impl Draw<Tui> { self.autoscroll(); /*self.autozoom();*/ self.size.of(&self.mode) }
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2423,14 +2420,11 @@ mod audio {
|
|||
}
|
||||
}
|
||||
|
||||
impl Layout<TuiOut> for PianoHorizontal {
|
||||
fn layout (&self, to: XYWH<u16>) -> XYWH<u16> { self.content().layout(to) }
|
||||
}
|
||||
impl HasContent<TuiOut> for PianoHorizontal {
|
||||
fn content (&self) -> impl Content<TuiOut> {
|
||||
Bsp::s(
|
||||
Bsp::e(Fixed::X(5, format!("{}x{}", self.size.w(), self.size.h())), self.timeline()),
|
||||
Bsp::e(self.keys(), self.size.of(Bsp::b(Fill::XY(self.notes()), Fill::XY(self.cursor())))),
|
||||
impl PianoHorizontal {
|
||||
fn tui (&self) -> impl Draw<Tui> {
|
||||
south(
|
||||
east(w_exact(5, format!("{}x{}", self.size.w(), self.size.h())), self.timeline()),
|
||||
east(self.keys(), self.size.of(below(wh_full(self.notes()), wh_full(self.cursor())))),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -2507,12 +2501,12 @@ mod audio {
|
|||
|
||||
}
|
||||
}
|
||||
fn notes (&self) -> impl Content<TuiOut> {
|
||||
fn notes (&self) -> impl Draw<Tui> {
|
||||
let time_start = self.get_time_start();
|
||||
let note_lo = self.get_note_lo();
|
||||
let note_hi = self.get_note_hi();
|
||||
let buffer = self.buffer.clone();
|
||||
Thunk::new(move|to: &mut TuiOut|{
|
||||
Thunk::new(move|to: &mut Tui|{
|
||||
let source = buffer.read().unwrap();
|
||||
let XYWH(x0, y0, w, _h) = to.area();
|
||||
//if h as usize != note_axis {
|
||||
|
|
@ -2538,7 +2532,7 @@ mod audio {
|
|||
}
|
||||
})
|
||||
}
|
||||
fn cursor (&self) -> impl Content<TuiOut> {
|
||||
fn cursor (&self) -> impl Draw<Tui> {
|
||||
let note_hi = self.get_note_hi();
|
||||
let note_lo = self.get_note_lo();
|
||||
let note_pos = self.get_note_pos();
|
||||
|
|
@ -2547,7 +2541,7 @@ mod audio {
|
|||
let time_start = self.get_time_start();
|
||||
let time_zoom = self.get_time_zoom();
|
||||
let style = Some(Style::default().fg(self.color.lightest.rgb));
|
||||
Thunk::new(move|to: &mut TuiOut|{
|
||||
Thunk::new(move|to: &mut Tui|{
|
||||
let XYWH(x0, y0, w, _) = to.area();
|
||||
for (_area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) {
|
||||
if note == note_pos {
|
||||
|
|
@ -2569,7 +2563,7 @@ mod audio {
|
|||
}
|
||||
})
|
||||
}
|
||||
fn keys (&self) -> impl Content<TuiOut> {
|
||||
fn keys (&self) -> impl Draw<Tui> {
|
||||
let state = self;
|
||||
let color = state.color;
|
||||
let note_lo = state.get_note_lo();
|
||||
|
|
@ -2578,7 +2572,7 @@ mod audio {
|
|||
let key_style = Some(Style::default().fg(Rgb(192, 192, 192)).bg(Rgb(0, 0, 0)));
|
||||
let off_style = Some(Style::default().fg(Tui::g(255)));
|
||||
let on_style = Some(Style::default().fg(Rgb(255,0,0)).bg(color.base.rgb).bold());
|
||||
Fill::Y(Fixed::X(self.keys_width, Thunk::new(move|to: &mut TuiOut|{
|
||||
h_full(w_exact(self.keys_width, Thunk::new(move|to: &mut Tui|{
|
||||
let XYWH(x, y0, _w, _h) = to.area();
|
||||
for (_area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) {
|
||||
to.blit(&to_key(note), x, screen_y, key_style);
|
||||
|
|
@ -2593,8 +2587,8 @@ mod audio {
|
|||
}
|
||||
})))
|
||||
}
|
||||
fn timeline (&self) -> impl Content<TuiOut> + '_ {
|
||||
Fill::X(Fixed::Y(1, Thunk::new(move|to: &mut TuiOut|{
|
||||
fn timeline (&self) -> impl Draw<Tui> + '_ {
|
||||
w_full(h_exact(1, Thunk::new(move|to: &mut Tui|{
|
||||
let XYWH(x, y, w, _h) = to.area();
|
||||
let style = Some(Style::default().dim());
|
||||
let length = self.clip.as_ref().map(|p|p.read().unwrap().length).unwrap_or(1);
|
||||
|
|
@ -2635,7 +2629,7 @@ mod audio {
|
|||
fn clip_mut (&mut self) -> &mut Option<Arc<RwLock<MidiClip>>> { &mut self.clip }
|
||||
/// Determine the required space to render the clip.
|
||||
fn buffer_size (&self, clip: &MidiClip) -> (usize, usize) { (clip.length / self.range.time_zoom().get(), 128) }
|
||||
fn redraw (&self) {
|
||||
fn redraw(self) {
|
||||
*self.buffer.write().unwrap() = if let Some(clip) = self.clip.as_ref() {
|
||||
let clip = clip.read().unwrap();
|
||||
let buf_size = self.buffer_size(&clip);
|
||||
|
|
@ -2671,9 +2665,9 @@ mod audio {
|
|||
self.colors[if self.on[pitch] { 2 } else { match pitch { 0 | 2 | 4 | 5 | 6 | 8 | 10 => 0, _ => 1 } }]
|
||||
}
|
||||
}
|
||||
impl HasContent<TuiOut> for OctaveVertical {
|
||||
fn content (&self) -> impl Content<TuiOut> {
|
||||
row!(
|
||||
impl OctaveVertical {
|
||||
fn tui (&self) -> impl Draw<Tui> {
|
||||
east!(
|
||||
Tui::fg_bg(self.color(0), self.color(1), "▙"),
|
||||
Tui::fg_bg(self.color(2), self.color(3), "▙"),
|
||||
Tui::fg_bg(self.color(4), self.color(5), "▌"),
|
||||
|
|
@ -3107,8 +3101,8 @@ mod audio {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
impl Draw<TuiOut> for SampleAdd {
|
||||
fn draw (&self, _to: &mut TuiOut) {
|
||||
impl Draw<Tui> for SampleAdd {
|
||||
fn draw (self, _to: &mut Tui) -> Usually<XYWH<u16>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
@ -3129,9 +3123,9 @@ mod audio {
|
|||
}
|
||||
}
|
||||
|
||||
fn draw_viewer (sample: Option<&Arc<RwLock<Sample>>>) -> impl Content<TuiOut> + use<'_> {
|
||||
fn draw_viewer (sample: Option<&Arc<RwLock<Sample>>>) -> impl Draw<Tui> + use<'_> {
|
||||
let min_db = -64.0;
|
||||
Thunk::new(move|to: &mut TuiOut|{
|
||||
Thunk::new(move|to: &mut Tui|{
|
||||
let XYWH(x, y, width, height) = to.area();
|
||||
let area = Rect { x, y, width, height };
|
||||
if let Some(sample) = &sample {
|
||||
|
|
@ -3216,7 +3210,7 @@ mod audio {
|
|||
}
|
||||
|
||||
fn draw_sample (
|
||||
to: &mut TuiOut, x: u16, y: u16, note: Option<&u7>, sample: &Sample, focus: bool
|
||||
to: &mut Tui, x: u16, y: u16, note: Option<&u7>, sample: &Sample, focus: bool
|
||||
) -> Usually<usize> {
|
||||
let style = if focus { Style::default().green() } else { Style::default() };
|
||||
if focus {
|
||||
|
|
@ -3340,8 +3334,8 @@ mod audio {
|
|||
}
|
||||
}
|
||||
|
||||
impl Draw<TuiOut> for Lv2 {
|
||||
fn draw (&self, to: &mut TuiOut) {
|
||||
impl Draw<Tui> for Lv2 {
|
||||
fn draw(self, to: &mut Tui) {
|
||||
let area = to.area();
|
||||
let XYWH(x, y, _, height) = area;
|
||||
let mut width = 20u16;
|
||||
|
|
@ -3373,7 +3367,7 @@ mod audio {
|
|||
}
|
||||
|
||||
|
||||
fn draw_header (state: &Lv2, to: &mut TuiOut, x: u16, y: u16, w: u16) {
|
||||
fn draw_header (state: &Lv2, to: &mut Tui, x: u16, y: u16, w: u16) {
|
||||
let style = Style::default().gray();
|
||||
let label1 = format!(" {}", state.name);
|
||||
to.blit(&label1, x + 1, y, Some(style.white().bold()));
|
||||
|
|
@ -3387,8 +3381,8 @@ mod audio {
|
|||
|
||||
mod pool {
|
||||
use crate::*;
|
||||
has_clips!(|self: Pool|self.clips);
|
||||
has_clip!(|self: Pool|self.clips().get(self.clip_index()).map(|c|c.clone()));
|
||||
impl_has_clips!(|self: Pool|self.clips);
|
||||
impl_from!(Pool: |clip:&Arc<RwLock<MidiClip>>|{
|
||||
let model = Self::default();
|
||||
model.clips.write().unwrap().push(clip.clone());
|
||||
|
|
@ -3523,14 +3517,14 @@ mod pool {
|
|||
fn _color_random (&self) -> ItemColor { ItemColor::random() }
|
||||
}
|
||||
|
||||
impl<'a> HasContent<TuiOut> for PoolView<'a> {
|
||||
fn content (&self) -> impl Content<TuiOut> {
|
||||
impl<'a> PoolView<'a> {
|
||||
fn tui (&self) -> impl Draw<Tui> {
|
||||
let Self(pool) = self;
|
||||
//let color = self.1.clip().map(|c|c.read().unwrap().color).unwrap_or_else(||Tui::g(32).into());
|
||||
//let on_bg = |x|x;//Bsp::b(Repeat(" "), Tui::bg(color.darkest.rgb, x));
|
||||
//let on_bg = |x|x;//below(Repeat(" "), Tui::bg(color.darkest.rgb, x));
|
||||
//let border = |x|x;//Outer(Style::default().fg(color.dark.rgb).bg(color.darkest.rgb)).enclose(x);
|
||||
//let height = pool.clips.read().unwrap().len() as u16;
|
||||
Fixed::X(20, Fill::Y(Align::n(Map::new(
|
||||
w_exact(20, h_full(origin_n(iter(
|
||||
||pool.clips().clone().into_iter(),
|
||||
move|clip: Arc<RwLock<MidiClip>>, i: usize|{
|
||||
let item_height = 1;
|
||||
|
|
@ -3541,26 +3535,26 @@ mod pool {
|
|||
let fg = color.lightest.rgb;
|
||||
let name = if false { format!(" {i:>3}") } else { format!(" {i:>3} {name}") };
|
||||
let length = if false { String::default() } else { format!("{length} ") };
|
||||
Fixed::Y(1, map_south(item_offset, item_height, Tui::bg(bg, lay!(
|
||||
Fill::X(Align::w(Tui::fg(fg, Tui::bold(selected, name)))),
|
||||
Fill::X(Align::e(Tui::fg(fg, Tui::bold(selected, length)))),
|
||||
Fill::X(Align::w(When::new(selected, Tui::bold(true, Tui::fg(Tui::g(255), "▶"))))),
|
||||
Fill::X(Align::e(When::new(selected, Tui::bold(true, Tui::fg(Tui::g(255), "◀"))))),
|
||||
h_exact(1, iter_south(item_offset, item_height, Tui::bg(bg, below!(
|
||||
w_full(origin_w(Tui::fg(fg, Tui::bold(selected, name)))),
|
||||
w_full(origin_e(Tui::fg(fg, Tui::bold(selected, length)))),
|
||||
w_full(origin_w(When::new(selected, Tui::bold(true, Tui::fg(Tui::g(255), "▶"))))),
|
||||
w_full(origin_e(When::new(selected, Tui::bold(true, Tui::fg(Tui::g(255), "◀"))))),
|
||||
))))
|
||||
}))))
|
||||
}
|
||||
}
|
||||
impl HasContent<TuiOut> for ClipLength {
|
||||
fn content (&self) -> impl Content<TuiOut> {
|
||||
impl ClipLength {
|
||||
fn tui (&self) -> impl Draw<Tui> {
|
||||
use ClipLengthFocus::*;
|
||||
let bars = ||self.bars_string();
|
||||
let beats = ||self.beats_string();
|
||||
let ticks = ||self.ticks_string();
|
||||
match self.focus {
|
||||
None => row!(" ", bars(), ".", beats(), ".", ticks()),
|
||||
Some(Bar) => row!("[", bars(), "]", beats(), ".", ticks()),
|
||||
Some(Beat) => row!(" ", bars(), "[", beats(), "]", ticks()),
|
||||
Some(Tick) => row!(" ", bars(), ".", beats(), "[", ticks()),
|
||||
None => east!(" ", bars(), ".", beats(), ".", ticks()),
|
||||
Some(Bar) => east!("[", bars(), "]", beats(), ".", ticks()),
|
||||
Some(Beat) => east!(" ", bars(), "[", beats(), "]", ticks()),
|
||||
Some(Tick) => east!(" ", bars(), ".", beats(), "[", ticks()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3848,14 +3842,6 @@ mod config {
|
|||
Ok(map)
|
||||
}
|
||||
}
|
||||
|
||||
// Each mode contains a view, so here we should be drawing it.
|
||||
// I'm not sure what's going on with this code, though.
|
||||
impl<D: Language + Ord> Draw<TuiOut> for Mode<D> {
|
||||
fn draw (&self, _to: &mut TuiOut) {
|
||||
//self.content().draw(to)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod dialog {
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ use builder_pattern::Builder;
|
|||
/// Must not be dropped for the duration of the process
|
||||
pub jack: Jack<'static>,
|
||||
/// Display size
|
||||
pub size: Measure<TuiOut>,
|
||||
pub size: Measure<Tui>,
|
||||
/// Performance counter
|
||||
pub perf: PerfModel,
|
||||
/// Available view modes and input bindings
|
||||
|
|
@ -468,9 +468,9 @@ use builder_pattern::Builder;
|
|||
/// TODO rename to "render_cache" or smth
|
||||
pub arranger: Arc<RwLock<Buffer>>,
|
||||
/// Display size
|
||||
pub size: Measure<TuiOut>,
|
||||
pub size: Measure<Tui>,
|
||||
/// Display size of clips area
|
||||
pub size_inner: Measure<TuiOut>,
|
||||
pub size_inner: Measure<Tui>,
|
||||
/// Source of time
|
||||
#[cfg(feature = "clock")] pub clock: Clock,
|
||||
/// Allows one MIDI clip to be edited
|
||||
|
|
@ -509,7 +509,7 @@ use builder_pattern::Builder;
|
|||
pub filter: String,
|
||||
pub index: usize,
|
||||
pub scroll: usize,
|
||||
pub size: Measure<TuiOut>,
|
||||
pub size: Measure<Tui>,
|
||||
}
|
||||
|
||||
pub(crate) struct EntriesIterator<'a> {
|
||||
|
|
@ -598,7 +598,7 @@ pub struct DeviceAudio<'a>(pub &'a mut Device);
|
|||
/// ```
|
||||
pub struct MidiEditor {
|
||||
/// Size of editor on screen
|
||||
pub size: Measure<TuiOut>,
|
||||
pub size: Measure<Tui>,
|
||||
/// View mode and state of editor
|
||||
pub mode: PianoHorizontal,
|
||||
}
|
||||
|
|
@ -613,7 +613,7 @@ pub struct MidiEditor {
|
|||
/// Buffer where the whole clip is rerendered on change
|
||||
pub buffer: Arc<RwLock<BigBuffer>>,
|
||||
/// Size of actual notes area
|
||||
pub size: Measure<TuiOut>,
|
||||
pub size: Measure<Tui>,
|
||||
/// The display window
|
||||
pub range: MidiSelection,
|
||||
/// The note cursor
|
||||
|
|
@ -808,7 +808,7 @@ pub struct PoolView<'a>(pub &'a Pool);
|
|||
/// Currently active modal, if any.
|
||||
pub mode: Option<SamplerMode>,
|
||||
/// Size of rendered sampler.
|
||||
pub size: Measure<TuiOut>,
|
||||
pub size: Measure<Tui>,
|
||||
/// Lowest note displayed.
|
||||
pub note_lo: AtomicUsize,
|
||||
/// Currently selected note.
|
||||
|
|
|
|||
116
app/tek_trait.rs
116
app/tek_trait.rs
|
|
@ -119,7 +119,7 @@ pub trait MidiRange: TimeRange + NoteRange {}
|
|||
/// can be clocked in microseconds with f64 without losing precision.
|
||||
pub trait TimeUnit: InteriorMutable<f64> {}
|
||||
|
||||
pub trait HasClipsSize { fn clips_size (&self) -> &Measure<TuiOut>; }
|
||||
pub trait HasClipsSize { fn clips_size (&self) -> &Measure<Tui>; }
|
||||
|
||||
pub trait HasMidiClip {
|
||||
fn clip (&self) -> Option<Arc<RwLock<MidiClip>>>;
|
||||
|
|
@ -327,16 +327,16 @@ pub trait HasTracks: AsRef<Vec<Track>> + AsMut<Vec<Track>> {
|
|||
pub trait HasTrack: AsRefOpt<Track> + AsMutOpt<Track> {
|
||||
fn track (&self) -> Option<&Track> { self.as_ref_opt() }
|
||||
fn track_mut (&mut self) -> Option<&mut Track> { self.as_mut_opt() }
|
||||
#[cfg(feature = "port")] fn view_midi_ins_status <'a> (&'a self, theme: ItemTheme) -> impl Content<TuiOut> + 'a {
|
||||
#[cfg(feature = "port")] fn view_midi_ins_status <'a> (&'a self, theme: ItemTheme) -> impl Draw<Tui> + 'a {
|
||||
self.track().map(move|track|view_ports_status(theme, "MIDI ins: ", &track.sequencer.midi_ins))
|
||||
}
|
||||
#[cfg(feature = "port")] fn view_midi_outs_status (&self, theme: ItemTheme) -> impl Content<TuiOut> + '_ {
|
||||
#[cfg(feature = "port")] fn view_midi_outs_status (&self, theme: ItemTheme) -> impl Draw<Tui> + '_ {
|
||||
self.track().map(move|track|view_ports_status(theme, "MIDI outs: ", &track.sequencer.midi_outs))
|
||||
}
|
||||
#[cfg(feature = "port")] fn view_audio_ins_status (&self, theme: ItemTheme) -> impl Content<TuiOut> {
|
||||
#[cfg(feature = "port")] fn view_audio_ins_status (&self, theme: ItemTheme) -> impl Draw<Tui> {
|
||||
self.track().map(move|track|view_ports_status(theme, "Audio ins: ", &track.audio_ins()))
|
||||
}
|
||||
#[cfg(feature = "port")] fn view_audio_outs_status (&self, theme: ItemTheme) -> impl Content<TuiOut> {
|
||||
#[cfg(feature = "port")] fn view_audio_outs_status (&self, theme: ItemTheme) -> impl Draw<Tui> {
|
||||
self.track().map(move|track|view_ports_status(theme, "Audio outs:", &track.audio_outs()))
|
||||
}
|
||||
}
|
||||
|
|
@ -379,7 +379,7 @@ pub trait HasPlayClip: HasClock {
|
|||
*self.reset_mut() = true;
|
||||
}
|
||||
|
||||
fn play_status (&self) -> impl Content<TuiOut> {
|
||||
fn play_status (&self) -> impl Draw<Tui> {
|
||||
let (name, color): (Arc<str>, ItemTheme) = if let Some((_, Some(clip))) = self.play_clip() {
|
||||
let MidiClip { ref name, color, .. } = *clip.read().unwrap();
|
||||
(name.clone(), color)
|
||||
|
|
@ -389,10 +389,10 @@ pub trait HasPlayClip: HasClock {
|
|||
let time: String = self.pulses_since_start_looped()
|
||||
.map(|(times, time)|format!("{:>3}x {:>}", times+1.0, self.clock().timebase.format_beats_1(time)))
|
||||
.unwrap_or_else(||String::from(" ")).into();
|
||||
FieldV(color, "Now:", format!("{} {}", time, name))
|
||||
field_v(color, "Now:", format!("{} {}", time, name))
|
||||
}
|
||||
|
||||
fn next_status (&self) -> impl Content<TuiOut> {
|
||||
fn next_status (&self) -> impl Draw<Tui> {
|
||||
let mut time: Arc<str> = String::from("--.-.--").into();
|
||||
let mut name: Arc<str> = String::from("").into();
|
||||
let mut color = ItemTheme::G[64];
|
||||
|
|
@ -425,7 +425,7 @@ pub trait HasPlayClip: HasClock {
|
|||
name = "Stop".to_string().into();
|
||||
}
|
||||
};
|
||||
FieldV(color, "Next:", format!("{} {}", time, name))
|
||||
field_v(color, "Next:", format!("{} {}", time, name))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -489,7 +489,7 @@ pub trait MidiRecord: MidiMonitor + HasClock + HasPlayClip {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait MidiViewer: Measured<TuiOut> + MidiRange + MidiPoint + Debug + Send + Sync {
|
||||
pub trait MidiViewer: Measured<Tui> + MidiRange + MidiPoint + Debug + Send + Sync {
|
||||
fn buffer_size (&self, clip: &MidiClip) -> (usize, usize);
|
||||
fn redraw (&self);
|
||||
fn clip (&self) -> &Option<Arc<RwLock<MidiClip>>>;
|
||||
|
|
@ -557,20 +557,20 @@ pub trait MidiViewer: Measured<TuiOut> + MidiRange + MidiPoint + Debug + Send +
|
|||
pub trait ClipsView: TracksView + ScenesView {
|
||||
|
||||
fn view_scenes_clips <'a> (&'a self)
|
||||
-> impl Content<TuiOut> + 'a
|
||||
-> impl Draw<Tui> + 'a
|
||||
{
|
||||
self.clips_size().of(Fill::XY(Bsp::a(
|
||||
Fill::XY(Align::se(Tui::fg(Green, format!("{}x{}", self.clips_size().w(), self.clips_size().h())))),
|
||||
Thunk::new(|to: &mut TuiOut|for (
|
||||
self.clips_size().of(wh_full(above(
|
||||
wh_full(origin_se(Tui::fg(Green, format!("{}x{}", self.clips_size().w(), self.clips_size().h())))),
|
||||
Thunk::new(|to: &mut Tui|for (
|
||||
track_index, track, _, _
|
||||
) in self.tracks_with_sizes() {
|
||||
to.place(&Fixed::X(track.width as u16,
|
||||
Fill::Y(self.view_track_clips(track_index, track))))
|
||||
to.place(&w_exact(track.width as u16,
|
||||
h_full(self.view_track_clips(track_index, track))))
|
||||
}))))
|
||||
}
|
||||
|
||||
fn view_track_clips <'a> (&'a self, track_index: usize, track: &'a Track) -> impl Content<TuiOut> + 'a {
|
||||
Thunk::new(move|to: &mut TuiOut|for (
|
||||
fn view_track_clips <'a> (&'a self, track_index: usize, track: &'a Track) -> impl Draw<Tui> + 'a {
|
||||
Thunk::new(move|to: &mut Tui|for (
|
||||
scene_index, scene, ..
|
||||
) in self.scenes_with_sizes() {
|
||||
let (name, theme): (Arc<str>, ItemTheme) = if let Some(Some(clip)) = &scene.clips.get(track_index) {
|
||||
|
|
@ -609,14 +609,14 @@ pub trait ClipsView: TracksView + ScenesView {
|
|||
Self::H_SCENE as usize
|
||||
} as u16;
|
||||
|
||||
to.place(&Fixed::XY(w, y, Bsp::b(
|
||||
Fill::XY(Outer(true, Style::default().fg(outline))),
|
||||
Fill::XY(Bsp::b(
|
||||
Bsp::b(
|
||||
Tui::fg_bg(outline, bg, Fill::XY("")),
|
||||
Fill::XY(Align::nw(Tui::fg_bg(fg, bg, Tui::bold(true, name)))),
|
||||
to.place(&wh_exact(w, y, below(
|
||||
wh_full(Outer(true, Style::default().fg(outline))),
|
||||
wh_full(below(
|
||||
below(
|
||||
Tui::fg_bg(outline, bg, wh_full("")),
|
||||
wh_full(origin_nw(Tui::fg_bg(fg, bg, Tui::bold(true, name)))),
|
||||
),
|
||||
Fill::XY(When::new(self.selection().track() == Some(track_index)
|
||||
wh_full(when(self.selection().track() == Some(track_index)
|
||||
&& self.selection().scene() == Some(scene_index)
|
||||
&& self.is_editing(), self.editor())))))));
|
||||
})
|
||||
|
|
@ -624,7 +624,7 @@ pub trait ClipsView: TracksView + ScenesView {
|
|||
|
||||
}
|
||||
|
||||
pub trait TracksView: ScenesView + HasMidiIns + HasMidiOuts + HasTrackScroll + Measured<TuiOut> {
|
||||
pub trait TracksView: ScenesView + HasMidiIns + HasMidiOuts + HasTrackScroll + Measured<Tui> {
|
||||
|
||||
fn tracks_width_available (&self) -> u16 {
|
||||
(self.measure_width() as u16).saturating_sub(40)
|
||||
|
|
@ -647,68 +647,68 @@ pub trait TracksView: ScenesView + HasMidiIns + HasMidiOuts + HasTrackScroll + M
|
|||
})
|
||||
}
|
||||
|
||||
fn view_track_names (&self, theme: ItemTheme) -> impl Content<TuiOut> {
|
||||
fn view_track_names (&self, theme: ItemTheme) -> impl Draw<Tui> {
|
||||
let track_count = self.tracks().len();
|
||||
let scene_count = self.scenes().len();
|
||||
let selected = self.selection();
|
||||
let button = Bsp::s(
|
||||
let button = south(
|
||||
button_3("t", "rack ", format!("{}{track_count}", selected.track()
|
||||
.map(|track|format!("{track}/")).unwrap_or_default()), false),
|
||||
button_3("s", "cene ", format!("{}{scene_count}", selected.scene()
|
||||
.map(|scene|format!("{scene}/")).unwrap_or_default()), false));
|
||||
let button_2 = Bsp::s(
|
||||
let button_2 = south(
|
||||
button_2("T", "+", false),
|
||||
button_2("S", "+", false));
|
||||
view_track_row_section(theme, button, button_2, Tui::bg(theme.darker.rgb,
|
||||
Fixed::Y(2, Thunk::new(|to: &mut TuiOut|{
|
||||
h_exact(2, Thunk::new(|to: &mut Tui|{
|
||||
for (index, track, x1, _x2) in self.tracks_with_sizes() {
|
||||
to.place(&Push::X(x1 as u16, Fixed::X(track_width(index, track),
|
||||
to.place(&x_push(x1 as u16, w_exact(track_width(index, track),
|
||||
Tui::bg(if selected.track() == Some(index) {
|
||||
track.color.light.rgb
|
||||
} else {
|
||||
track.color.base.rgb
|
||||
}, Bsp::s(Fill::X(Align::nw(Bsp::e(
|
||||
}, south(w_full(origin_nw(east(
|
||||
format!("·t{index:02} "),
|
||||
Tui::fg(Rgb(255, 255, 255), Tui::bold(true, &track.name))
|
||||
))), ""))) ));}}))))
|
||||
}
|
||||
|
||||
fn view_track_outputs <'a> (&'a self, theme: ItemTheme, _h: u16) -> impl Content<TuiOut> {
|
||||
fn view_track_outputs <'a> (&'a self, theme: ItemTheme, _h: u16) -> impl Draw<Tui> {
|
||||
view_track_row_section(theme,
|
||||
Bsp::s(Fill::X(Align::w(button_2("o", "utput", false))),
|
||||
Thunk::new(|to: &mut TuiOut|for port in self.midi_outs().iter() {
|
||||
to.place(&Fill::X(Align::w(port.port_name())));
|
||||
south(w_full(origin_w(button_2("o", "utput", false))),
|
||||
Thunk::new(|to: &mut Tui|for port in self.midi_outs().iter() {
|
||||
to.place(&w_full(origin_w(port.port_name())));
|
||||
})),
|
||||
button_2("O", "+", false),
|
||||
Tui::bg(theme.darker.rgb, Align::w(Thunk::new(|to: &mut TuiOut|{
|
||||
Tui::bg(theme.darker.rgb, origin_w(Thunk::new(|to: &mut Tui|{
|
||||
for (index, track, _x1, _x2) in self.tracks_with_sizes() {
|
||||
to.place(&Fixed::X(track_width(index, track),
|
||||
Align::nw(Fill::Y(Map::south(1, ||track.sequencer.midi_outs.iter(),
|
||||
to.place(&w_exact(track_width(index, track),
|
||||
origin_nw(h_full(iter_south(1, ||track.sequencer.midi_outs.iter(),
|
||||
|port, index|Tui::fg(Rgb(255, 255, 255),
|
||||
Fixed::Y(1, Tui::bg(track.color.dark.rgb, Fill::X(Align::w(
|
||||
h_exact(1, Tui::bg(track.color.dark.rgb, w_full(origin_w(
|
||||
format!("·o{index:02} {}", port.port_name())))))))))));}}))))
|
||||
}
|
||||
|
||||
fn view_track_inputs <'a> (&'a self, theme: ItemTheme) -> impl Content<TuiOut> {
|
||||
fn view_track_inputs <'a> (&'a self, theme: ItemTheme) -> impl Draw<Tui> {
|
||||
let mut h = 0u16;
|
||||
for track in self.tracks().iter() {
|
||||
h = h.max(track.sequencer.midi_ins.len() as u16);
|
||||
}
|
||||
let content = Thunk::new(move|to: &mut TuiOut|for (index, track, _x1, _x2) in self.tracks_with_sizes() {
|
||||
to.place(&Fixed::XY(track_width(index, track), h + 1,
|
||||
Align::nw(Bsp::s(
|
||||
let content = Thunk::new(move|to: &mut Tui|for (index, track, _x1, _x2) in self.tracks_with_sizes() {
|
||||
to.place(&wh_exact(track_width(index, track), h + 1,
|
||||
origin_nw(south(
|
||||
Tui::bg(track.color.base.rgb,
|
||||
Fill::X(Align::w(row!(
|
||||
Either::new(track.sequencer.monitoring, Tui::fg(Green, "●mon "), "·mon "),
|
||||
Either::new(track.sequencer.recording, Tui::fg(Red, "●rec "), "·rec "),
|
||||
Either::new(track.sequencer.overdub, Tui::fg(Yellow, "●dub "), "·dub "),
|
||||
w_full(origin_w(east!(
|
||||
either(track.sequencer.monitoring, Tui::fg(Green, "●mon "), "·mon "),
|
||||
either(track.sequencer.recording, Tui::fg(Red, "●rec "), "·rec "),
|
||||
either(track.sequencer.overdub, Tui::fg(Yellow, "●dub "), "·dub "),
|
||||
)))),
|
||||
Map::south(1, ||track.sequencer.midi_ins.iter(),
|
||||
iter_south(1, ||track.sequencer.midi_ins.iter(),
|
||||
|port, index|Tui::fg_bg(Rgb(255, 255, 255), track.color.dark.rgb,
|
||||
Fill::X(Align::w(format!("·i{index:02} {}", port.port_name())))))))));
|
||||
w_full(origin_w(format!("·i{index:02} {}", port.port_name())))))))));
|
||||
});
|
||||
view_track_row_section(theme, button_2("i", "nput", false), button_2("I", "+", false),
|
||||
Tui::bg(theme.darker.rgb, Align::w(content)))
|
||||
Tui::bg(theme.darker.rgb, origin_w(content)))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -739,13 +739,13 @@ pub trait ScenesView: HasEditor + HasSelection + HasSceneScroll + HasClipsSize +
|
|||
})
|
||||
}
|
||||
|
||||
fn view_scenes_names (&self) -> impl Content<TuiOut> {
|
||||
Fixed::X(20, Thunk::new(|to: &mut TuiOut|for (index, scene, ..) in self.scenes_with_sizes() {
|
||||
fn view_scenes_names (&self) -> impl Draw<Tui> {
|
||||
w_exact(20, Thunk::new(|to: &mut Tui|for (index, scene, ..) in self.scenes_with_sizes() {
|
||||
to.place(&self.view_scene_name(index, scene));
|
||||
}))
|
||||
}
|
||||
|
||||
fn view_scene_name <'a> (&'a self, index: usize, scene: &'a Scene) -> impl Content<TuiOut> + 'a {
|
||||
fn view_scene_name <'a> (&'a self, index: usize, scene: &'a Scene) -> impl Draw<Tui> + 'a {
|
||||
let h = if self.selection().scene() == Some(index) && let Some(_editor) = self.editor() {
|
||||
7
|
||||
} else {
|
||||
|
|
@ -756,13 +756,13 @@ pub trait ScenesView: HasEditor + HasSelection + HasSceneScroll + HasClipsSize +
|
|||
} else {
|
||||
scene.color.base.rgb
|
||||
};
|
||||
let a = Fill::X(Align::w(Bsp::e(format!("·s{index:02} "),
|
||||
let a = w_full(origin_w(east(format!("·s{index:02} "),
|
||||
Tui::fg(Tui::g(255), Tui::bold(true, &scene.name)))));
|
||||
let b = When::new(self.selection().scene() == Some(index) && self.is_editing(),
|
||||
Fill::XY(Align::nw(Bsp::s(
|
||||
let b = when(self.selection().scene() == Some(index) && self.is_editing(),
|
||||
wh_full(origin_nw(south(
|
||||
self.editor().as_ref().map(|e|e.clip_status()),
|
||||
self.editor().as_ref().map(|e|e.edit_status())))));
|
||||
Fixed::XY(20, h, Tui::bg(bg, Align::nw(Bsp::s(a, b))))
|
||||
wh_exact(20, h, Tui::bg(bg, origin_nw(south(a, b))))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
2
tengri
2
tengri
|
|
@ -1 +1 @@
|
|||
Subproject commit 9dbf4fcab5f31a68e3d24c8f8f7fc866159e89f1
|
||||
Subproject commit cf57f44933c45507e8de072e32c284f20f12ac7a
|
||||
Loading…
Add table
Add a link
Reference in a new issue