mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
demacroify io_header
This commit is contained in:
parent
a66a6a9669
commit
1fb5dfbe11
3 changed files with 57 additions and 47 deletions
|
|
@ -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])
|
||||||
|
|
|
||||||
|
|
@ -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::*;
|
||||||
|
|
|
||||||
101
tek/src/view.rs
101
tek/src/view.rs
|
|
@ -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),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue