demacroify io_header

This commit is contained in:
🪞👃🪞 2025-01-25 19:28:08 +01:00
parent a66a6a9669
commit 1fb5dfbe11
3 changed files with 57 additions and 47 deletions

View file

@ -13,7 +13,7 @@ macro_rules! impl_port {
} }
impl AsRef<Port<$Spec>> for $Name { fn as_ref (&self) -> &Port<$Spec> { &self.port } } impl AsRef<Port<$Spec>> for $Name { fn as_ref (&self) -> &Port<$Spec> { &self.port } }
impl $Name { impl $Name {
pub fn name (&self) -> &str { self.name.as_ref() } pub fn name (&self) -> &Arc<str> { &self.name }
pub fn port (&self) -> &Port<$Spec> { &self.port } pub fn port (&self) -> &Port<$Spec> { &self.port }
pub fn port_mut (&mut self) -> &mut Port<$Spec> { &mut self.port } pub fn port_mut (&mut self) -> &mut Port<$Spec> { &mut self.port }
pub fn new ($jack: &Jack, name: impl AsRef<str>, connect: &[PortConnect]) pub fn new ($jack: &Jack, name: impl AsRef<str>, connect: &[PortConnect])

View file

@ -5,6 +5,7 @@
#![feature(if_let_guard)] #![feature(if_let_guard)]
#![feature(impl_trait_in_assoc_type)] #![feature(impl_trait_in_assoc_type)]
#![feature(type_alias_impl_trait)] #![feature(type_alias_impl_trait)]
#![feature(trait_alias)]
mod cli; pub use self::cli::*; mod cli; pub use self::cli::*;
mod model; pub use self::model::*; mod model; pub use self::model::*;
mod view; pub use self::view::*; mod view; pub use self::view::*;

View file

@ -1,9 +1,17 @@
use crate::*; use crate::*;
use std::fmt::Write; use std::fmt::Write;
#[derive(Debug, Default)] struct ViewMemo<T, U> { macro_rules! def_sizes_iter {
value: T, ($Type:ident => $($Item:ty),+) => {
view: Arc<RwLock<U>> trait $Type<'a> = Iterator<Item=(usize, $(&'a $Item,)+ usize, usize)> + Send + Sync + 'a;
}
} }
def_sizes_iter!(ScenesSizes => Scene);
def_sizes_iter!(TracksSizes => Track);
def_sizes_iter!(InputsSizes => JackMidiIn);
def_sizes_iter!(OutputsSizes => JackMidiOut);
def_sizes_iter!(PortsSizes => Arc<str>, [PortConnect]);
#[derive(Debug, Default)] struct ViewMemo<T, U> { value: T, view: Arc<RwLock<U>> }
impl<T: PartialEq, U> ViewMemo<T, U> { impl<T: PartialEq, U> ViewMemo<T, U> {
fn new (value: T, view: U) -> Self { fn new (value: T, view: U) -> Self {
Self { Self {
@ -186,12 +194,6 @@ macro_rules! per_track {
let content = Fixed::y(1, $content); let content = Fixed::y(1, $content);
let styled = Tui::fg_bg($track.color.lightest.rgb, $track.color.base.rgb, content); let styled = Tui::fg_bg($track.color.lightest.rgb, $track.color.base.rgb, content);
map_east(x1 as u16, width, Align::y(Fixed::x(width, styled))) }))).into() }} } map_east(x1 as u16, width, Align::y(Fixed::x(width, styled))) }))).into() }} }
macro_rules! io_header {
($self:ident, $key:expr, $label:expr, $count:expr, $content:expr) => {
(move||Fill::xy(Align::nw({
let button = $self.button($key, format!("{:10} ({})", $label, $count));
Bsp::s(button, $content)
})).boxed()).into() } }
macro_rules! per_track_top { macro_rules! per_track_top {
($area:expr;|$self:ident,$track:ident,$index:ident|$content:expr) => {{ ($area:expr;|$self:ident,$track:ident,$index:ident|$content:expr) => {{
let tracks = ||$self.tracks_sizes($self.is_editing(), $self.editor_w()) let tracks = ||$self.tracks_sizes($self.is_editing(), $self.editor_w())
@ -215,14 +217,44 @@ impl Tek {
fn wrap (bg: Color, fg: Color, content: impl Content<TuiOut>) -> impl Content<TuiOut> { fn wrap (bg: Color, fg: Color, content: impl Content<TuiOut>) -> impl Content<TuiOut> {
Bsp::e(Tui::fg_bg(bg, Reset, ""), Bsp::w(Tui::fg_bg(bg, Reset, ""), Tui::fg_bg(fg, bg, content))) Bsp::e(Tui::fg_bg(bg, Reset, ""), Bsp::w(Tui::fg_bg(bg, Reset, ""), Tui::fg_bg(fg, bg, content)))
} }
fn view_header <'a> (
&'a self, key: &'a str, label: &str, count: usize, content: impl Content<TuiOut> + Send + Sync + 'a
) -> impl Content<TuiOut> + 'a {
Fill::xy(Align::nw(Bsp::s(
self.button(key, format!("{:10} ({})", label, count)),
content,
)))
}
fn view_io_header <'a, T: PortsSizes<'a>> (
&'a self,
key: &'a str,
label: &str,
count: usize,
fg: Color,
bg: Color,
iter: impl Fn()->T + Send + Sync + 'a,
) -> impl Content<TuiOut> + 'a {
self.view_header(key, label, count, Map::new(iter,
move|(index, name, connections, y, y2), _|map_south(y as u16, (y2-y) as u16, Bsp::s(
Fill::x(Tui::bold(true, Tui::fg_bg(fg, bg, Align::w(name)))),
Map::new(||connections.iter(), move|connect, index|map_south(index as u16, 1,
Fill::x(Align::w(Tui::bold(false, Tui::fg_bg(fg, bg, connect.info()))))))))))
}
fn button <'a> (
&'a self, key: impl Content<TuiOut> + 'a, label: impl Content<TuiOut> + 'a
) -> impl Content<TuiOut> + 'a {
let compact = !self.is_editing();
Tui::bold(true, Bsp::e(
Margin::x(1, Tui::fg_bg(Tui::g(0), Tui::orange(), key)),
When::new(compact, Margin::x(1, Tui::fg_bg(Tui::g(255), Tui::g(96), label))),
))
}
// TRACKS ///////////////////////////////////////////////////////////////////////////////////// // TRACKS /////////////////////////////////////////////////////////////////////////////////////
fn w_tracks (&self, editing: bool, bigger: usize) -> u16 { fn w_tracks (&self, editing: bool, bigger: usize) -> u16 {
self.tracks_sizes(editing, bigger).last().map(|(_, _, _, x)|x as u16).unwrap_or(0) self.tracks_sizes(editing, bigger).last().map(|(_, _, _, x)|x as u16).unwrap_or(0)
} }
fn tracks_sizes <'a> (&'a self, editing: bool, bigger: usize) fn tracks_sizes <'a> (&'a self, editing: bool, bigger: usize) -> impl TracksSizes<'a> {
-> impl Iterator<Item=(usize, &'a Track, usize, usize)> + Send + Sync + 'a
{
let mut x = 0; let mut x = 0;
let active = match self.selected() { let active = match self.selected() {
Selection::Track(t) if editing => Some(t.saturating_sub(1)), Selection::Track(t) if editing => Some(t.saturating_sub(1)),
@ -254,28 +286,22 @@ impl Tek {
} }
// INPUTS ///////////////////////////////////////////////////////////////////////////////////// // INPUTS /////////////////////////////////////////////////////////////////////////////////////
fn inputs_sizes (&self) -> impl Iterator<Item = (usize, &JackMidiIn, usize, usize)> + Send + Sync { fn inputs_sizes (&self) -> impl PortsSizes<'_> {
let mut y = 0; let mut y = 0;
self.midi_ins.iter().enumerate().map(move|(i, input)|{ self.midi_ins.iter().enumerate().map(move|(i, input)|{
let height = 1 + input.conn().len(); let height = 1 + input.conn().len();
let data = (i, input, y, y + height); let data = (i, input.name(), input.conn(), y, y + height);
y += height; y += height;
data data
}) })
} }
fn h_inputs (&self) -> u16 { fn h_inputs (&self) -> u16 {
1 + self.inputs_sizes().last().map(|(_, _, _, y)|y as u16).unwrap_or(0) 1 + self.inputs_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
} }
fn view_inputs (&self) -> impl Content<TuiOut> + use<'_> { fn view_inputs (&self) -> impl Content<TuiOut> + use<'_> {
let fg = Tui::g(224); let fg = Tui::g(224);
let bg = Tui::g(64); let bg = Tui::g(64);
let header: ThunkBox<_> = io_header!(self, " I ", " midi ins", self.midi_ins.len(), let header = self.view_io_header(" I ", " midi ins", self.midi_ins.len(), fg, bg, ||self.inputs_sizes());
Map::new(||self.inputs_sizes(),
move|(index, input, y, y2), _|map_south(y as u16, (y2-y) as u16, Bsp::s(
Fill::x(Tui::bold(true, Tui::fg_bg(fg, bg, Align::w(input.name())))),
Map::new(||input.conn().iter(), move|connect, index|map_south(index as u16, 1,
Fill::x(Align::w(Tui::bold(false, Tui::fg_bg(fg, bg, connect.info()))))))))));
let cells: ThunkBox<_> = per_track_top!(self.size.w();|self, track, t|{ let cells: ThunkBox<_> = per_track_top!(self.size.w();|self, track, t|{
let rec = track.player.recording; let rec = track.player.recording;
let mon = track.player.monitoring; let mon = track.player.monitoring;
@ -287,7 +313,7 @@ impl Tek {
Tui::fg_bg(if mon { White } else { track.color.darkest.rgb }, bg, "Mon ")))))), Tui::fg_bg(if mon { White } else { track.color.darkest.rgb }, bg, "Mon ")))))),
Fill::y(Tui::bg(Green, Map::new( Fill::y(Tui::bg(Green, Map::new(
||self.inputs_sizes(), ||self.inputs_sizes(),
move|(index, input, y, y2), _|map_south(y as u16, (y2-y) as u16, move|(index, name, conn, y, y2), _|map_south(y as u16, (y2-y) as u16,
Self::wrap(bg, fg, Bsp::e( Self::wrap(bg, fg, Bsp::e(
Tui::fg_bg(if rec { White } else { track.color.darkest.rgb }, bg, "R▞▞▞▞"), Tui::fg_bg(if rec { White } else { track.color.darkest.rgb }, bg, "R▞▞▞▞"),
Tui::fg_bg(if mon { White } else { track.color.darkest.rgb }, bg, "M▞▞▞▞"))))))))}); Tui::fg_bg(if mon { White } else { track.color.darkest.rgb }, bg, "M▞▞▞▞"))))))))});
@ -300,13 +326,13 @@ impl Tek {
// OUTPUTS //////////////////////////////////////////////////////////////////////////////////// // OUTPUTS ////////////////////////////////////////////////////////////////////////////////////
fn h_outputs (&self) -> u16 { fn h_outputs (&self) -> u16 {
1 + self.outputs_sizes().last().map(|(_, _, _, y)|y as u16).unwrap_or(0) 1 + self.outputs_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
} }
fn outputs_sizes (&self) -> impl Iterator<Item = (usize, &JackMidiOut, usize, usize)> + Send + Sync { fn outputs_sizes (&self) -> impl PortsSizes<'_> {
let mut y = 0; let mut y = 0;
self.midi_outs.iter().enumerate().map(move|(i, output)|{ self.midi_outs.iter().enumerate().map(move|(i, output)|{
let height = 1 + output.conn().len(); let height = 1 + output.conn().len();
let data = (i, output, y, y + height); let data = (i, output.name(), output.conn(), y, y + height);
y += height; y += height;
data data
}) })
@ -314,13 +340,7 @@ impl Tek {
fn view_outputs (&self) -> impl Content<TuiOut> + use<'_> { fn view_outputs (&self) -> impl Content<TuiOut> + use<'_> {
let fg = Tui::g(224); let fg = Tui::g(224);
let bg = Tui::g(64); let bg = Tui::g(64);
let header: ThunkBox<_> = io_header!(self, " O ", " midi outs", self.midi_outs.len(), let header = self.view_io_header(" O ", " midi outs", self.midi_outs.len(), fg, bg, ||self.outputs_sizes());
Map::new(||self.outputs_sizes(),
move|(index, output, y, y2), _|map_south(y as u16, (y2-y) as u16, Bsp::s(
Fill::x(Tui::bold(true, Tui::fg_bg(fg, bg, Align::w(output.name())))),
Map::new(||output.conn().iter(), move|connect, index|map_south(index as u16, 1,
Fill::x(Align::w(Tui::bold(false, Tui::fg_bg(fg, bg, connect.info()))))))))));
let mute = false; let mute = false;
let solo = false; let solo = false;
let cells: ThunkBox<_> = per_track_top!(self.size.w();|self, track, t|{ let cells: ThunkBox<_> = per_track_top!(self.size.w();|self, track, t|{
@ -332,7 +352,7 @@ impl Tek {
Tui::fg_bg(if solo { White } else { track.color.darkest.rgb }, bg, "Solo "),)))), Tui::fg_bg(if solo { White } else { track.color.darkest.rgb }, bg, "Solo "),)))),
Fill::y(Map::new( Fill::y(Map::new(
||self.outputs_sizes(), ||self.outputs_sizes(),
move|(index, output, y, y2), _|map_south(y as u16, (y2-y) as u16, move|(index, name, conn, y, y2), _|map_south(y as u16, (y2-y) as u16,
Self::wrap(bg, fg, Bsp::e( Self::wrap(bg, fg, Bsp::e(
Tui::fg_bg(if mute { White } else { track.color.darkest.rgb }, bg, "P▞▞▞▞"), Tui::fg_bg(if mute { White } else { track.color.darkest.rgb }, bg, "P▞▞▞▞"),
Tui::fg_bg(if solo { White } else { track.color.darkest.rgb }, bg, "S▞▞▞▞")))))))}); Tui::fg_bg(if solo { White } else { track.color.darkest.rgb }, bg, "S▞▞▞▞")))))))});
@ -346,9 +366,7 @@ impl Tek {
fn h_scenes (&self, editing: bool, height: usize, larger: usize) -> u16 { fn h_scenes (&self, editing: bool, height: usize, larger: usize) -> u16 {
self.scenes_sizes(editing, height, larger).last().map(|(_, _, _, y)|y as u16).unwrap_or(0) self.scenes_sizes(editing, height, larger).last().map(|(_, _, _, y)|y as u16).unwrap_or(0)
} }
fn scenes_sizes (&self, editing: bool, height: usize, larger: usize) fn scenes_sizes (&self, editing: bool, height: usize, larger: usize) -> impl ScenesSizes<'_> {
-> impl Iterator<Item = (usize, &Scene, usize, usize)> + Send + Sync
{
let mut y = 0; let mut y = 0;
let (selected_track, selected_scene) = match self.selected() { let (selected_track, selected_scene) = match self.selected() {
Selection::Clip(t, s) => (Some(t.saturating_sub(1)), Some(s.saturating_sub(1))), Selection::Clip(t, s) => (Some(t.saturating_sub(1)), Some(s.saturating_sub(1))),
@ -461,15 +479,6 @@ impl Tek {
//let w = if self.is_editing() { w / 2 } else { w }; //let w = if self.is_editing() { w / 2 } else { w };
w as u16 w as u16
} }
fn button <'a> (
&'a self, key: impl Content<TuiOut> + 'a, label: impl Content<TuiOut> + 'a
) -> impl Content<TuiOut> + 'a {
let compact = !self.is_editing();
Tui::bold(true, Bsp::e(
Margin::x(1, Tui::fg_bg(Tui::g(0), Tui::orange(), key)),
When::new(compact, Margin::x(1, Tui::fg_bg(Tui::g(255), Tui::g(96), label))),
))
}
fn view_track_add (&self) -> impl Content<TuiOut> + use<'_> { fn view_track_add (&self) -> impl Content<TuiOut> + use<'_> {
let data = (self.selected.track().unwrap_or(0), self.tracks().len()); let data = (self.selected.track().unwrap_or(0), self.tracks().len());
self.fmtd.write().unwrap().trks.update(Some(data), self.fmtd.write().unwrap().trks.update(Some(data),