mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-08-07 22:17:07 +02:00
This commit is contained in:
parent
8de62463c0
commit
a938b68980
5 changed files with 262 additions and 336 deletions
|
|
@ -439,10 +439,18 @@ pub trait ScenesView: HasEditor + HasSelection + HasSceneScroll + HasClipsSize +
|
||||||
fn w_mid (&self) -> u16;
|
fn w_mid (&self) -> u16;
|
||||||
|
|
||||||
fn view_scenes_names (&self) -> impl Draw<Tui> {
|
fn view_scenes_names (&self) -> impl Draw<Tui> {
|
||||||
view_scenes_names(
|
let select = self.selection();
|
||||||
self.scenes_with_sizes(), self.selection(), self.editor(), self.is_editing()
|
let editor = self.editor();
|
||||||
)
|
let editing = self.is_editing();
|
||||||
|
draw(move |to: &mut Tui|{
|
||||||
|
for (index, scene, ..) in self.scenes_with_sizes() {
|
||||||
|
view_scene_name(select, editor, index, scene, editing).draw(to)?;
|
||||||
}
|
}
|
||||||
|
Ok(Some(XYWH(1, 1, 1, 1)))
|
||||||
|
})
|
||||||
|
.exact_w(20)
|
||||||
|
}
|
||||||
|
|
||||||
fn scenes_with_sizes (&self) -> impl ScenesSizes<'_> {
|
fn scenes_with_sizes (&self) -> impl ScenesSizes<'_> {
|
||||||
let mut y = 0;
|
let mut y = 0;
|
||||||
self.scenes().iter().enumerate().skip(self.scene_scroll()).map_while(move|(s, scene)|{
|
self.scenes().iter().enumerate().skip(self.scene_scroll()).map_while(move|(s, scene)|{
|
||||||
|
|
@ -733,23 +741,84 @@ pub trait HasTrackScroll: HasTracks {
|
||||||
pub trait TracksView: ScenesView + HasMidiIns + HasMidiOuts + HasTrackScroll {
|
pub trait TracksView: ScenesView + HasMidiIns + HasMidiOuts + HasTrackScroll {
|
||||||
/// Draw name of each track
|
/// Draw name of each track
|
||||||
fn view_track_names (&self, theme: ItemTheme) -> impl Draw<Tui> {
|
fn view_track_names (&self, theme: ItemTheme) -> impl Draw<Tui> {
|
||||||
view_track_names(
|
let track_count = self.tracks().len();
|
||||||
theme, self.tracks_with_sizes(), self.tracks().len(), self.scenes().len(), self.selection()
|
let scene_count = self.scenes().len();
|
||||||
)
|
let selected = self.selection();
|
||||||
|
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 = south(
|
||||||
|
button_2("T", "+", false),
|
||||||
|
button_2("S", "+", false));
|
||||||
|
view_track_row_section(theme, button, button_2, bg(theme.darker.term,
|
||||||
|
draw(|to: &mut Tui|{
|
||||||
|
for (index, track, x1, _x2) in self.tracks_with_sizes() {
|
||||||
|
let b = if selected.track() == Some(index) {
|
||||||
|
track.color.light.term
|
||||||
|
} else {
|
||||||
|
track.color.base.term
|
||||||
|
};
|
||||||
|
bg(b, south(east(
|
||||||
|
format!("·t{index:02} "),
|
||||||
|
fg(Rgb(255, 255, 255), bold(true, &track.name))
|
||||||
|
).align_nw().full_w(), ""))
|
||||||
|
.exact_w(track_width(index, track))
|
||||||
|
.push_x(x1 as u16)
|
||||||
|
.draw(to)?;
|
||||||
|
}
|
||||||
|
Ok(Some(XYWH(0, 0, 0, 0)))
|
||||||
|
}).exact_h(2)))
|
||||||
}
|
}
|
||||||
/// Draw outputs per track
|
/// Draw outputs per track
|
||||||
fn view_track_outputs <'a> (&'a self, theme: ItemTheme, _h: u16) -> impl Draw<Tui> {
|
fn view_track_outputs <'a> (&'a self, theme: ItemTheme, _h: u16) -> impl Draw<Tui> {
|
||||||
view_track_outputs(
|
view_track_row_section(theme,
|
||||||
theme, self.tracks_with_sizes(), self.midi_outs().iter()
|
south(button_2("o", "utput", false).align_w().full_w(),
|
||||||
)
|
draw(|to: &mut Tui|{
|
||||||
|
for port in self.midi_outs().iter() {
|
||||||
|
let _ = port.port_name().align_w().full_w().draw(to)?;
|
||||||
|
}
|
||||||
|
Ok(Some(XYWH(0, 0, 0, 0)))
|
||||||
|
})),
|
||||||
|
button_2("O", "+", false),
|
||||||
|
bg(theme.darker.term, draw(|to: &mut Tui|{
|
||||||
|
for (index, track, _x1, _x2) in self.tracks_with_sizes() {
|
||||||
|
let f = Rgb(255, 255, 255);
|
||||||
|
let b = track.color.dark.term;
|
||||||
|
let iter = ||track.sequencer.midi_outs.iter();
|
||||||
|
let draw = |port: &MidiOutput, _|fg(f, bg(b,
|
||||||
|
format!("·o{index:02} {}", port.port_name()).full_w().align_w()).exact_h(1));
|
||||||
|
iter_south(iter, draw).full_h().align_nw()
|
||||||
|
.exact_w(track_width(index, track))
|
||||||
|
.draw(to)?;
|
||||||
|
}
|
||||||
|
Ok(Some(XYWH(0, 0, 0, 0)))
|
||||||
|
}).align_w()))
|
||||||
}
|
}
|
||||||
/// Draw inputs per track
|
/// Draw inputs per track
|
||||||
fn view_track_inputs <'a> (&'a self, theme: ItemTheme) -> impl Draw<Tui> {
|
fn view_track_inputs <'a> (&'a self, theme: ItemTheme) -> impl Draw<Tui> {
|
||||||
let mut h = 0u16;
|
let mut height = 0u16;
|
||||||
for track in self.tracks().iter() {
|
for track in self.tracks().iter() {
|
||||||
h = h.max(track.sequencer.midi_ins.len() as u16);
|
height = height.max(track.sequencer.midi_ins.len() as u16);
|
||||||
}
|
}
|
||||||
view_track_inputs(theme, self.tracks_with_sizes(), h)
|
view_track_row_section(theme, button_2("i", "nput", false), button_2("I", "+", false),
|
||||||
|
bg(theme.darker.term, draw(move|to: &mut Tui|{
|
||||||
|
for (index, track, _x1, _x2) in self.tracks_with_sizes() {
|
||||||
|
south(
|
||||||
|
bg(track.color.base.term,
|
||||||
|
east!(
|
||||||
|
either(track.sequencer.monitoring, fg(Green, "●mon "), "·mon "),
|
||||||
|
either(track.sequencer.recording, fg(Red, "●rec "), "·rec "),
|
||||||
|
either(track.sequencer.overdub, fg(Yellow, "●dub "), "·dub "),
|
||||||
|
).align_w().full_w()),
|
||||||
|
iter_south(||track.sequencer.midi_ins.iter(),
|
||||||
|
|port, _|fg_bg(Rgb(255, 255, 255), track.color.dark.term,
|
||||||
|
format!("·i{index:02} {}", port.port_name()).align_w().full_w()))
|
||||||
|
).align_nw().exact_wh(track_width(index, track), height + 1).draw(to)?;
|
||||||
|
}
|
||||||
|
Ok(Some(XYWH(0, 0, 0, 0)))
|
||||||
|
}).align_w()))
|
||||||
}
|
}
|
||||||
/// Iterate over tracks with their corresponding sizes.
|
/// Iterate over tracks with their corresponding sizes.
|
||||||
fn tracks_with_sizes (&self) -> impl TracksSizes<'_> {
|
fn tracks_with_sizes (&self) -> impl TracksSizes<'_> {
|
||||||
|
|
@ -801,21 +870,102 @@ impl_as_mut!(Vec<Track>: |self: App| self.project.as_mut());
|
||||||
impl Arrangement {
|
impl Arrangement {
|
||||||
|
|
||||||
pub fn view_inputs (&self, _theme: ItemTheme) -> impl Draw<Tui> + '_ {
|
pub fn view_inputs (&self, _theme: ItemTheme) -> impl Draw<Tui> + '_ {
|
||||||
view_inputs(
|
let title_1 = button_3("i", "nput ", format!("{}", self.midi_ins().len()), false).align_w().exact_wh(20, 1);
|
||||||
self.tracks_with_sizes(), self.midi_ins().as_slice()
|
let title_2 = button_2("I", "+", false).exact_wh(4, 1);
|
||||||
|
east(title_1, west(title_2, draw(move|to: &mut Tui|{
|
||||||
|
for (_index, track, x1, _x2) in self.tracks_with_sizes() {
|
||||||
|
let _ = south(
|
||||||
|
bg(track.color.dark.term, east!(
|
||||||
|
either(track.sequencer.monitoring, fg(Green, "mon "), "mon "),
|
||||||
|
either(track.sequencer.recording, fg(Red, "rec "), "rec "),
|
||||||
|
either(track.sequencer.overdub, fg(Yellow, "dub "), "dub "),
|
||||||
|
).exact_w(track.width as u16)).align_w().push_x(x1 as u16),
|
||||||
|
draw(move |to: &mut Tui|{
|
||||||
|
for (index, port) in self.midi_ins().as_slice().iter().enumerate() {
|
||||||
|
let _ = east(
|
||||||
|
east(
|
||||||
|
" ● ",
|
||||||
|
bold(true, fg(Rgb(255,255,255), port.port_name()))
|
||||||
|
).align_w().exact_w(20),
|
||||||
|
west(
|
||||||
|
().exact_w(4),
|
||||||
|
bg(track.color.darker.term, east!(
|
||||||
|
either(track.sequencer.monitoring, fg(Green, " ● "), " · "),
|
||||||
|
either(track.sequencer.recording, fg(Red, " ● "), " · "),
|
||||||
|
either(track.sequencer.overdub, fg(Yellow, " ● "), " · "),
|
||||||
|
).exact_w(track.width as u16).align_w())
|
||||||
)
|
)
|
||||||
|
).push_x(index as u16 * 10).exact_h(1).draw(to)?;
|
||||||
|
}
|
||||||
|
todo!()
|
||||||
|
})
|
||||||
|
).draw(to)?;
|
||||||
|
}
|
||||||
|
Ok(Some(to.area()))
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view_outputs (&self, theme: ItemTheme) -> impl Draw<Tui> {
|
pub fn view_outputs (&self, theme: ItemTheme) -> impl Draw<Tui> {
|
||||||
view_outputs(
|
let height = self.outputs_height();
|
||||||
theme, self.tracks_with_sizes(), self.midi_outs(), self.outputs_height()
|
let list = south(
|
||||||
)
|
button_3(
|
||||||
|
"o", "utput", format!("{}", self.midi_outs().len()), false
|
||||||
|
).align_w().full_w().exact_h(1),
|
||||||
|
draw(|to: &mut Tui|{
|
||||||
|
for (_index, port) in self.midi_outs().iter().enumerate() {
|
||||||
|
east(
|
||||||
|
east(" ● ", fg(Rgb(255,255,255), bold(true, port.port_name()))).align_w(),
|
||||||
|
format!("{}/{} ",
|
||||||
|
port.port().get_connections().len(),
|
||||||
|
port.connections.len()).align_e().full_w().exact_h(1)).full_w().draw(to)?;
|
||||||
|
for (index, conn) in port.connections.iter().enumerate() {
|
||||||
|
format!(" c{index:02}{}", conn.info()).align_w().full_w().exact_h(1).draw(to)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
todo!();
|
||||||
|
}).align_nw().full_wh().exact_h(height - 1)
|
||||||
|
);
|
||||||
|
view_track_row_section(theme, list, button_2("O", "+", false),
|
||||||
|
bg(theme.darker.term, draw(|to: &mut Tui|{
|
||||||
|
for (index, track, _x1, _x2) in self.tracks_with_sizes() {
|
||||||
|
let _ = draw(|to: &mut Tui|{
|
||||||
|
east(
|
||||||
|
either(true, fg(Green, "play "), "play "),
|
||||||
|
either(false, fg(Yellow, "solo "), "solo "),
|
||||||
|
).align_w().exact_h(1).draw(to)?;
|
||||||
|
for (_index, port) in self.midi_outs().iter().enumerate() {
|
||||||
|
east(
|
||||||
|
either(true, fg(Green, " ● "), " · "),
|
||||||
|
either(false, fg(Yellow, " ● "), " · "),
|
||||||
|
).align_w().exact_h(1).draw(to)?;
|
||||||
|
for (_index, _conn) in port.connections.iter().enumerate() {
|
||||||
|
"".full_w().exact_h(1).draw(to)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
todo!()
|
||||||
|
}).exact_w(track_width(index, track)).draw(to)?;
|
||||||
|
}
|
||||||
|
todo!()
|
||||||
|
}).align_w().full_w())).exact_h(height)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view_track_devices (&self, theme: ItemTheme) -> impl Draw<Tui> {
|
pub fn view_track_devices (&self, theme: ItemTheme) -> impl Draw<Tui> {
|
||||||
view_track_devices(
|
let height = self.devices_height();
|
||||||
theme, self.tracks_with_sizes(), self.track(), self.devices_height()
|
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),
|
||||||
|
iter_once(self.tracks_with_sizes(), move|(_, track, _x1, _x2), index|bg(
|
||||||
|
track.color.dark.term,
|
||||||
|
iter_south(move||0..height,
|
||||||
|
|_, _index|fg_bg(
|
||||||
|
ItemTheme::G[32].lightest.term,
|
||||||
|
ItemTheme::G[32].dark.term,
|
||||||
|
format!(" · {}", "--").align_nw()
|
||||||
|
).exact_wh(track.width as u16, 2)
|
||||||
|
).align_nw()).exact_wh(
|
||||||
|
Some(track_width(index, track)),
|
||||||
|
Some(height + 1),
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn devices_height (&self) -> u16 {
|
fn devices_height (&self) -> u16 {
|
||||||
|
|
@ -898,3 +1048,15 @@ impl HasTrackScroll for App {
|
||||||
pub(crate) fn track_width (_index: usize, track: &Track) -> u16 {
|
pub(crate) fn track_width (_index: usize, track: &Track) -> u16 {
|
||||||
track.width as u16
|
track.width as u16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Define a type alias for iterators of sized items (columns).
|
||||||
|
macro_rules! def_sizes_iter {
|
||||||
|
($Type:ident => $($Item:ty),+) => {
|
||||||
|
pub trait $Type<'a>: Iterator<Item=(usize, $(&'a $Item,)+ usize, usize)> + Send + Sync + 'a {}
|
||||||
|
impl<'a, T: Iterator<Item=(usize, $(&'a $Item,)+ usize, usize)> + Send + Sync + 'a> $Type<'a> for T {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def_sizes_iter!(PortsSizes => Arc<str>, [Connect]);
|
||||||
|
def_sizes_iter!(ScenesSizes => Scene);
|
||||||
|
def_sizes_iter!(TracksSizes => Track);
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,7 @@ impl PianoHorizontal {
|
||||||
//if h as usize != note_axis {
|
//if h as usize != note_axis {
|
||||||
//panic!("area height mismatch: {h} <> {note_axis}");
|
//panic!("area height mismatch: {h} <> {note_axis}");
|
||||||
//}
|
//}
|
||||||
|
if let Tui::Draw(to, ..) = to {
|
||||||
for (area_x, screen_x) in (x0..x0+w).enumerate() {
|
for (area_x, screen_x) in (x0..x0+w).enumerate() {
|
||||||
for (area_y, screen_y, _note) in note_y_iter(note_lo, note_hi, y0) {
|
for (area_y, screen_y, _note) in note_y_iter(note_lo, note_hi, y0) {
|
||||||
let source_x = time_start + area_x;
|
let source_x = time_start + area_x;
|
||||||
|
|
@ -155,13 +156,14 @@ impl PianoHorizontal {
|
||||||
let is_in_y = source_y < source.height;
|
let is_in_y = source_y < source.height;
|
||||||
if is_in_x && is_in_y {
|
if is_in_x && is_in_y {
|
||||||
if let Some(source_cell) = source.get(source_x, source_y) {
|
if let Some(source_cell) = source.get(source_x, source_y) {
|
||||||
if let Some(cell) = to.0.cell_mut(ratatui::prelude::Position::from((screen_x, screen_y))) {
|
if let Some(cell) = to.cell_mut(ratatui::prelude::Position::from((screen_x, screen_y))) {
|
||||||
*cell = source_cell.clone();
|
*cell = source_cell.clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Ok(Some(xywh))
|
Ok(Some(xywh))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -279,6 +279,7 @@ fn draw_viewer (sample: Option<&Arc<RwLock<Sample>>>) -> impl Draw<Tui> + use<'_
|
||||||
lines.push(Line::new(x, min_db, x, y, Color::Green));
|
lines.push(Line::new(x, min_db, x, y, Color::Green));
|
||||||
t += step / 2.;
|
t += step / 2.;
|
||||||
}
|
}
|
||||||
|
if let Tui::Draw(buf, ..) = to {
|
||||||
Canvas::default()
|
Canvas::default()
|
||||||
.x_bounds([sample.start as f64, sample.end as f64])
|
.x_bounds([sample.start as f64, sample.end as f64])
|
||||||
.y_bounds([min_db, 0.])
|
.y_bounds([min_db, 0.])
|
||||||
|
|
@ -294,8 +295,10 @@ fn draw_viewer (sample: Option<&Arc<RwLock<Sample>>>) -> impl Draw<Tui> + use<'_
|
||||||
//text.red()
|
//text.red()
|
||||||
//);
|
//);
|
||||||
})
|
})
|
||||||
.render(area, to.as_mut());
|
.render(area, buf);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if let Tui::Draw(buf, ..) = to {
|
||||||
Canvas::default()
|
Canvas::default()
|
||||||
.x_bounds([0.0, width as f64])
|
.x_bounds([0.0, width as f64])
|
||||||
.y_bounds([0.0, height as f64])
|
.y_bounds([0.0, height as f64])
|
||||||
|
|
@ -307,7 +310,8 @@ fn draw_viewer (sample: Option<&Arc<RwLock<Sample>>>) -> impl Draw<Tui> + use<'_
|
||||||
//text.red()
|
//text.red()
|
||||||
//);
|
//);
|
||||||
})
|
})
|
||||||
.render(area, to.as_mut());
|
.render(area, buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(Some(xywh))
|
Ok(Some(xywh))
|
||||||
})
|
})
|
||||||
|
|
|
||||||
274
src/tek.rs
274
src/tek.rs
|
|
@ -1479,76 +1479,49 @@ mod draw {
|
||||||
|
|
||||||
impl Keywords<Tui, XYWH<u16>> for App {
|
impl Keywords<Tui, XYWH<u16>> for App {
|
||||||
fn keywords () -> impl Iterator<Item = fn(&Self, &mut Tui, &str) -> Perhaps<XYWH<u16>>> {
|
fn keywords () -> impl Iterator<Item = fn(&Self, &mut Tui, &str) -> Perhaps<XYWH<u16>>> {
|
||||||
[
|
[kw_when, kw_either, kw_split, kw_align, kw_exact, kw_min, kw_max, kw_push,
|
||||||
kw_when, kw_either, kw_split, kw_align,
|
kw_tui_text, kw_tui_fg, kw_tui_bg]
|
||||||
kw_exact, kw_fixed, kw_min, kw_max, kw_push
|
.into_iter()
|
||||||
].into_iter()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpret<Tui, Option<XYWH<u16>>> for App {
|
impl Interpret<Tui, Option<XYWH<u16>>> for App {
|
||||||
fn interpret_expr <'a> (&'a self, to: &mut Tui, lang: &'a impl Expression) -> Drawn<u16> {
|
fn interpret_expr <'a> (&'a self, to: &mut Tui, lang: &'a impl Expression) -> Drawn<u16> {
|
||||||
tek_draw_expr(self, to, lang)
|
self.keyword(to, lang)
|
||||||
}
|
}
|
||||||
fn interpret_word <'a> (&'a self, to: &mut Tui, lang: &'a impl Expression) -> Drawn<u16> {
|
fn interpret_word <'a> (&'a self, to: &mut Tui, lang: &'a impl Expression) -> Drawn<u16> {
|
||||||
tek_draw_word(self, to, lang)
|
let mut frags = lang.src()?.unwrap().split("/");
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tek_draw_expr (state: &App, to: &mut Tui, lang: &impl Expression) -> Drawn<u16> {
|
|
||||||
Ok(Some(if let Some(area) = eval_view(state, to, lang)? {
|
|
||||||
area
|
|
||||||
} else if let Some(area) = Tui::eval_view(state, to, lang)? {
|
|
||||||
area
|
|
||||||
} else {
|
|
||||||
return Err(format!("App::interpret_expr: unexpected: {lang:?}").into())
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tek_draw_word (state: &App, to: &mut Tui, dsl: &impl Expression) -> Drawn<u16> {
|
|
||||||
let mut frags = dsl.src()?.unwrap().split("/");
|
|
||||||
match frags.next() {
|
match frags.next() {
|
||||||
//Some(":logo") => view_logo().draw(to),
|
//Some(":logo") => view_logo().draw(to),
|
||||||
Some(":meters") => draw_meter_section(to, frags),
|
Some(":meters") => draw_meter_section(to, frags),
|
||||||
Some(":tracks") => draw_tracks(to, frags, state),
|
Some(":tracks") => draw_tracks(to, frags, self),
|
||||||
Some(":scenes") => draw_scenes(to, frags),
|
Some(":scenes") => draw_scenes(to, frags),
|
||||||
Some(":dialog") => draw_dialog(to, frags, state, dsl),
|
Some(":dialog") => draw_dialog(to, frags, self, lang),
|
||||||
Some(":templates") => draw_templates(to, frags, state),
|
Some(":templates") => draw_templates(to, frags, self),
|
||||||
Some(":sessions") => view_sessions().draw(to),
|
Some(":sessions") => view_sessions().draw(to),
|
||||||
Some(":browse/title") => view_browse_title(state).draw(to),
|
Some(":browse/title") => view_browse_title(self).draw(to),
|
||||||
Some(":device") => view_device(state).draw(to),
|
Some(":device") => view_device(self).draw(to),
|
||||||
Some(":status") => "TODO: Status Bar".exact_h(1).draw(to),
|
Some(":status") => "TODO: Status Bar".exact_h(1).draw(to),
|
||||||
Some(":editor") => "TODO Editor".draw(to),
|
Some(":editor") => "TODO Editor".draw(to),
|
||||||
Some(":transport") => view_transport(true, "", "", "").draw(to),
|
Some(":transport") => view_transport(true, "", "", "").draw(to),
|
||||||
Some(":debug") => format!("[{:?}]", to.area()).exact_h(1).draw(to),
|
Some(":debug") => format!("[{:?}]", to.area()).exact_h(1).draw(to),
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
let views = state.config.views.read().unwrap();
|
let views = self.config.views.read().unwrap();
|
||||||
if let Some(dsl) = views.get(dsl.src()?.unwrap()) {
|
if let Some(lang) = views.get(lang.src()?.unwrap()) {
|
||||||
let dsl = dsl.clone();
|
let lang = lang.clone();
|
||||||
std::mem::drop(views);
|
std::mem::drop(views);
|
||||||
state.interpret(to, &dsl)
|
self.interpret(to, &lang)
|
||||||
} else {
|
} else {
|
||||||
unimplemented!("{dsl:?}");
|
unimplemented!("{lang:?}");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl_has!(Sizer: |self: App|self.size);
|
impl_has!(Sizer: |self: App|self.size);
|
||||||
|
|
||||||
/// Define a type alias for iterators of sized items (columns).
|
|
||||||
macro_rules! def_sizes_iter {
|
|
||||||
($Type:ident => $($Item:ty),+) => {
|
|
||||||
pub trait $Type<'a>: Iterator<Item=(usize, $(&'a $Item,)+ usize, usize)> + Send + Sync + 'a {}
|
|
||||||
impl<'a, T: Iterator<Item=(usize, $(&'a $Item,)+ usize, usize)> + Send + Sync + 'a> $Type<'a> for T {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def_sizes_iter!(PortsSizes => Arc<str>, [Connect]);
|
|
||||||
def_sizes_iter!(ScenesSizes => Scene);
|
|
||||||
def_sizes_iter!(TracksSizes => Track);
|
|
||||||
|
|
||||||
pub trait HasWidth {
|
pub trait HasWidth {
|
||||||
const MIN_WIDTH: usize;
|
const MIN_WIDTH: usize;
|
||||||
/// Increment track width.
|
/// Increment track width.
|
||||||
|
|
@ -1967,106 +1940,6 @@ mod draw {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view_track_names <'a> (
|
|
||||||
theme: ItemTheme,
|
|
||||||
tracks: impl TracksSizes<'a>,
|
|
||||||
track_count: usize,
|
|
||||||
scene_count: usize,
|
|
||||||
selected: &Selection,
|
|
||||||
) -> impl Draw<Tui> {
|
|
||||||
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 = south(
|
|
||||||
button_2("T", "+", false),
|
|
||||||
button_2("S", "+", false));
|
|
||||||
view_track_row_section(theme, button, button_2, bg(theme.darker.term,
|
|
||||||
draw(|to: &mut Tui|{
|
|
||||||
for (index, track, x1, _x2) in tracks {
|
|
||||||
let b = if selected.track() == Some(index) {
|
|
||||||
track.color.light.term
|
|
||||||
} else {
|
|
||||||
track.color.base.term
|
|
||||||
};
|
|
||||||
bg(b, south(east(
|
|
||||||
format!("·t{index:02} "),
|
|
||||||
fg(Rgb(255, 255, 255), bold(true, &track.name))
|
|
||||||
).align_nw().full_w(), ""))
|
|
||||||
.exact_w(track_width(index, track))
|
|
||||||
.push_x(x1 as u16)
|
|
||||||
.draw(to)?;
|
|
||||||
}
|
|
||||||
Ok(Some(XYWH(0, 0, 0, 0)))
|
|
||||||
}).exact_h(2)))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn view_track_outputs <'a> (
|
|
||||||
theme: ItemTheme,
|
|
||||||
tracks: impl TracksSizes<'a>,
|
|
||||||
midi_outs: impl Iterator<Item = &'a MidiOutput>,
|
|
||||||
) -> impl Draw<Tui> {
|
|
||||||
view_track_row_section(theme,
|
|
||||||
south(button_2("o", "utput", false).align_w().full_w(),
|
|
||||||
draw(|to: &mut Tui|{
|
|
||||||
for port in midi_outs {
|
|
||||||
let _ = port.port_name().align_w().full_w().draw(to)?;
|
|
||||||
}
|
|
||||||
Ok(Some(XYWH(0, 0, 0, 0)))
|
|
||||||
})),
|
|
||||||
button_2("O", "+", false),
|
|
||||||
bg(theme.darker.term, draw(|to: &mut Tui|{
|
|
||||||
for (index, track, _x1, _x2) in tracks {
|
|
||||||
let f = Rgb(255, 255, 255);
|
|
||||||
let b = track.color.dark.term;
|
|
||||||
let iter = ||track.sequencer.midi_outs.iter();
|
|
||||||
let draw = |port: &MidiOutput, _|fg(f, bg(b,
|
|
||||||
format!("·o{index:02} {}", port.port_name()).full_w().align_w()).exact_h(1));
|
|
||||||
iter_south(iter, draw).full_h().align_nw()
|
|
||||||
.exact_w(track_width(index, track))
|
|
||||||
.draw(to)?;
|
|
||||||
}
|
|
||||||
Ok(Some(XYWH(0, 0, 0, 0)))
|
|
||||||
}).align_w()))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn view_track_inputs <'a> (
|
|
||||||
theme: ItemTheme, tracks: impl TracksSizes<'a>, height: u16,
|
|
||||||
) -> impl Draw<Tui> {
|
|
||||||
view_track_row_section(theme, button_2("i", "nput", false), button_2("I", "+", false),
|
|
||||||
bg(theme.darker.term, draw(move|to: &mut Tui|{
|
|
||||||
for (index, track, _x1, _x2) in tracks {
|
|
||||||
south(
|
|
||||||
bg(track.color.base.term,
|
|
||||||
east!(
|
|
||||||
either(track.sequencer.monitoring, fg(Green, "●mon "), "·mon "),
|
|
||||||
either(track.sequencer.recording, fg(Red, "●rec "), "·rec "),
|
|
||||||
either(track.sequencer.overdub, fg(Yellow, "●dub "), "·dub "),
|
|
||||||
).align_w().full_w()),
|
|
||||||
iter_south(||track.sequencer.midi_ins.iter(),
|
|
||||||
|port, _|fg_bg(Rgb(255, 255, 255), track.color.dark.term,
|
|
||||||
format!("·i{index:02} {}", port.port_name()).align_w().full_w()))
|
|
||||||
).align_nw().exact_wh(track_width(index, track), height + 1).draw(to)?;
|
|
||||||
}
|
|
||||||
Ok(Some(XYWH(0, 0, 0, 0)))
|
|
||||||
}).align_w()))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn view_scenes_names <'a> (
|
|
||||||
scenes: impl ScenesSizes<'a>,
|
|
||||||
select: &Selection,
|
|
||||||
editor: Option<&MidiEditor>,
|
|
||||||
editing: bool,
|
|
||||||
) -> impl Draw<Tui> {
|
|
||||||
draw(move |to: &mut Tui|{
|
|
||||||
for (index, scene, ..) in scenes {
|
|
||||||
view_scene_name(select, editor, index, scene, editing).draw(to)?;
|
|
||||||
}
|
|
||||||
Ok(Some(XYWH(1, 1, 1, 1)))
|
|
||||||
}).exact_w(20)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn view_scene_name (
|
pub fn view_scene_name (
|
||||||
select: &Selection,
|
select: &Selection,
|
||||||
editor: Option<&MidiEditor>,
|
editor: Option<&MidiEditor>,
|
||||||
|
|
@ -2121,119 +1994,4 @@ mod draw {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view_per_track () -> impl Draw<Tui> {}
|
|
||||||
|
|
||||||
pub fn view_per_track_top () -> impl Draw<Tui> {}
|
|
||||||
|
|
||||||
pub fn view_inputs <'a> (
|
|
||||||
tracks: impl TracksSizes<'a>, midi_ins: &[MidiInput]
|
|
||||||
) -> impl Draw<Tui> {
|
|
||||||
let title_1 = button_3("i", "nput ", format!("{}", midi_ins.len()), false).align_w().exact_wh(20, 1);
|
|
||||||
let title_2 = button_2("I", "+", false).exact_wh(4, 1);
|
|
||||||
east(title_1, west(title_2, draw(move|to: &mut Tui|{
|
|
||||||
for (_index, track, x1, _x2) in tracks {
|
|
||||||
let _ = south(
|
|
||||||
bg(track.color.dark.term, east!(
|
|
||||||
either(track.sequencer.monitoring, fg(Green, "mon "), "mon "),
|
|
||||||
either(track.sequencer.recording, fg(Red, "rec "), "rec "),
|
|
||||||
either(track.sequencer.overdub, fg(Yellow, "dub "), "dub "),
|
|
||||||
).exact_w(track.width as u16)).align_w().push_x(x1 as u16),
|
|
||||||
draw(move |to: &mut Tui|{
|
|
||||||
for (index, port) in midi_ins.iter().enumerate() {
|
|
||||||
let _ = east(
|
|
||||||
east(
|
|
||||||
" ● ",
|
|
||||||
bold(true, fg(Rgb(255,255,255), port.port_name()))
|
|
||||||
).align_w().exact_w(20),
|
|
||||||
west(
|
|
||||||
().exact_w(4),
|
|
||||||
bg(track.color.darker.term, east!(
|
|
||||||
either(track.sequencer.monitoring, fg(Green, " ● "), " · "),
|
|
||||||
either(track.sequencer.recording, fg(Red, " ● "), " · "),
|
|
||||||
either(track.sequencer.overdub, fg(Yellow, " ● "), " · "),
|
|
||||||
).exact_w(track.width as u16).align_w())
|
|
||||||
)
|
|
||||||
).push_x(index as u16 * 10).exact_h(1).draw(to)?;
|
|
||||||
}
|
|
||||||
todo!()
|
|
||||||
})
|
|
||||||
).draw(to)?;
|
|
||||||
}
|
|
||||||
todo!()
|
|
||||||
})))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn view_outputs <'a> (
|
|
||||||
theme: ItemTheme,
|
|
||||||
tracks: impl TracksSizes<'a>,
|
|
||||||
midi_outs: &[MidiOutput],
|
|
||||||
height: u16,
|
|
||||||
) -> impl Draw<Tui> {
|
|
||||||
|
|
||||||
let list = south(
|
|
||||||
button_3(
|
|
||||||
"o", "utput", format!("{}", midi_outs.len()), false
|
|
||||||
).align_w().full_w().exact_h(1),
|
|
||||||
draw(|to: &mut Tui|{
|
|
||||||
for (_index, port) in midi_outs.iter().enumerate() {
|
|
||||||
east(
|
|
||||||
east(" ● ", fg(Rgb(255,255,255), bold(true, port.port_name()))).align_w(),
|
|
||||||
format!("{}/{} ",
|
|
||||||
port.port().get_connections().len(),
|
|
||||||
port.connections.len()).align_e().full_w().exact_h(1)).full_w().draw(to)?;
|
|
||||||
for (index, conn) in port.connections.iter().enumerate() {
|
|
||||||
format!(" c{index:02}{}", conn.info()).align_w().full_w().exact_h(1).draw(to)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
todo!();
|
|
||||||
}).align_nw().full_wh().exact_h(height - 1)
|
|
||||||
);
|
|
||||||
|
|
||||||
view_track_row_section(theme, list, button_2("O", "+", false),
|
|
||||||
bg(theme.darker.term, draw(|to: &mut Tui|{
|
|
||||||
for (index, track, _x1, _x2) in tracks {
|
|
||||||
let _ = draw(|to: &mut Tui|{
|
|
||||||
east(
|
|
||||||
either(true, fg(Green, "play "), "play "),
|
|
||||||
either(false, fg(Yellow, "solo "), "solo "),
|
|
||||||
).align_w().exact_h(1).draw(to)?;
|
|
||||||
for (_index, port) in midi_outs.iter().enumerate() {
|
|
||||||
east(
|
|
||||||
either(true, fg(Green, " ● "), " · "),
|
|
||||||
either(false, fg(Yellow, " ● "), " · "),
|
|
||||||
).align_w().exact_h(1).draw(to)?;
|
|
||||||
for (_index, _conn) in port.connections.iter().enumerate() {
|
|
||||||
"".full_w().exact_h(1).draw(to)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
todo!()
|
|
||||||
}).exact_w(track_width(index, track)).draw(to)?;
|
|
||||||
}
|
|
||||||
todo!()
|
|
||||||
}).align_w().full_w())).exact_h(height)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn view_track_devices <'a> (
|
|
||||||
theme: ItemTheme,
|
|
||||||
tracks: impl TracksSizes<'a>,
|
|
||||||
track: Option<&Track>,
|
|
||||||
h: u16,
|
|
||||||
) -> impl Draw<Tui> {
|
|
||||||
view_track_row_section(theme,
|
|
||||||
button_3("d", "evice", format!("{}", track.map(|t|t.devices.len()).unwrap_or(0)), false),
|
|
||||||
button_2("D", "+", false),
|
|
||||||
iter_once(tracks, move|(_, track, _x1, _x2), index|bg(
|
|
||||||
track.color.dark.term,
|
|
||||||
iter_south(move||0..h,
|
|
||||||
|_, _index|fg_bg(
|
|
||||||
ItemTheme::G[32].lightest.term,
|
|
||||||
ItemTheme::G[32].dark.term,
|
|
||||||
format!(" · {}", "--").align_nw()
|
|
||||||
).exact_wh(track.width as u16, 2)
|
|
||||||
).align_nw()).exact_wh(
|
|
||||||
Some(track_width(index, track)),
|
|
||||||
Some(h + 1),
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
tengri
2
tengri
|
|
@ -1 +1 @@
|
||||||
Subproject commit eb028c85fc94a1b86c44d4f079e5fb91667d4db2
|
Subproject commit ac9fd7dfba24335d09793a55d94ea54039253f62
|
||||||
Loading…
Add table
Add a link
Reference in a new issue