almost compiles
Some checks failed
/ build (push) Has been cancelled

the long-standing architectural issues
around how the Draw, Layout, and Content
traits from Tengri should, well, actually work -
that has subsided for now. somewhat.

going to amend this commit with fixes to
the remaining import not founds,
and then... what?
This commit is contained in:
🪞👃🪞 2025-09-29 06:50:40 +03:00
parent ef81b085a0
commit e6bf5c1f6e
4 changed files with 79 additions and 60 deletions

View file

@ -1,6 +1,6 @@
pub(crate) use ::{ pub(crate) use ::{
tek_device::*, tek_device::*,
tek_device::tengri::{ tengri::{
Usually, Perhaps, Has, MaybeHas, has, maybe_has, impl_debug, from, Usually, Perhaps, Has, MaybeHas, has, maybe_has, impl_debug, from,
dsl::*, dsl::*,
input::*, input::*,
@ -8,7 +8,9 @@ pub(crate) use ::{
tui::{ tui::{
*, *,
ratatui::{ ratatui::{
self, prelude::{Style, Stylize, Buffer, Modifier, buffer::Cell, Color::{self, *}} self,
prelude::{Rect, Style, Stylize, Buffer, Modifier, buffer::Cell, Color::{self, *}},
widgets::{Widget, canvas::{Canvas, Line}},
}, },
crossterm::{ crossterm::{
self, self,
@ -31,6 +33,5 @@ pub(crate) use ::{
thread::JoinHandle thread::JoinHandle
}, },
xdg::BaseDirectories, xdg::BaseDirectories,
atomic_float::*, atomic_float::*
tengri::tui::ratatui::{prelude::Rect, widgets::{Widget, canvas::{Canvas, Line}}},
}; };

2
deps/tengri vendored

@ -1 +1 @@
Subproject commit 41fa55fa6ca15abd0a80fd50a30326b1fea6b5f1 Subproject commit 8c54510f630e8a81b7d7bdca0a51a69cdb9dffcc

View file

@ -118,7 +118,7 @@ pub trait ScenesView:
}) })
} }
fn view_scenes_names (&self) -> impl Content<TuiOut> { fn view_scenes_names (&self) -> impl Content<TuiOut> {
Fixed::x(20, Thunk::new(|to: &mut TuiOut|for (index, scene, ..) in self.scenes_with_sizes() { Fixed::X(20, Thunk::new(|to: &mut TuiOut|for (index, scene, ..) in self.scenes_with_sizes() {
to.place(&self.view_scene_name(index, scene)); to.place(&self.view_scene_name(index, scene));
})) }))
} }
@ -182,7 +182,7 @@ impl Scene {
match self.clips.get(index) { Some(Some(clip)) => Some(clip), _ => None } match self.clips.get(index) { Some(Some(clip)) => Some(clip), _ => None }
} }
} }
//scene_scroll: Fill::Y(Fixed::x(1, ScrollbarV { //scene_scroll: Fill::Y(Fixed::X(1, ScrollbarV {
//offset: arrangement.scene_scroll, //offset: arrangement.scene_scroll,
//length: h_scenes_area as usize, //length: h_scenes_area as usize,
//total: h_scenes as usize, //total: h_scenes as usize,

View file

@ -36,33 +36,41 @@ pub trait HasTracks: Has<Vec<Track>> + Send + Sync {
const TRACK_SPACING: usize = 0; const TRACK_SPACING: usize = 0;
} }
pub trait HasTrackScroll: HasTracks { fn track_scroll (&self) -> usize; } pub trait HasTrackScroll: HasTracks {
impl HasTrackScroll for Arrangement { fn track_scroll (&self) -> usize { self.track_scroll } } fn track_scroll (&self) -> usize;
}
impl HasTrackScroll for Arrangement {
fn track_scroll (&self) -> usize {
self.track_scroll
}
}
pub trait HasTrack {
fn track (&self) -> Option<&Track>;
fn track_mut (&mut self) -> Option<&mut Track>;
#[cfg(feature = "port")] fn view_midi_ins_status <'a> (&'a self, theme: ItemTheme) -> impl Content<TuiOut> + '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> + '_ {
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> {
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> {
self.track().map(move|track|view_ports_status(theme, "Audio outs:", &track.audio_outs()))
}
}
impl<T: MaybeHas<Track>> HasTrack for T { impl<T: MaybeHas<Track>> HasTrack for T {
fn track (&self) -> Option<&Track> { self.get() } fn track (&self) -> Option<&Track> {
fn track_mut (&mut self) -> Option<&mut Track> { self.get_mut() } self.get()
}
fn track_mut (&mut self) -> Option<&mut Track> {
self.get_mut()
}
} }
impl Track {
fn _todo_opt_bool_stub_ (&self) -> Option<bool> { todo!() }
fn _todo_usize_stub_ (&self) -> usize { todo!() }
fn _todo_arc_str_stub_ (&self) -> Arc<str> { todo!() }
fn _todo_item_theme_stub (&self) -> ItemTheme { todo!() }
}
def_command!(TrackCommand: |track: Track| {
Stop => { track.sequencer.enqueue_next(None); Ok(None) },
SetMute { mute: Option<bool> } => todo!(),
SetSolo { solo: Option<bool> } => todo!(),
SetSize { size: usize } => todo!(),
SetZoom { zoom: usize } => todo!(),
SetName { name: Arc<str> } =>
swap_value(&mut track.name, name, |name|Self::SetName { name }),
SetColor { color: ItemTheme } =>
swap_value(&mut track.color, color, |color|Self::SetColor { color }),
SetRec { rec: Option<bool> } =>
toggle_bool(&mut track.sequencer.recording, rec, |rec|Self::SetRec { rec }),
SetMon { mon: Option<bool> } =>
toggle_bool(&mut track.sequencer.monitoring, mon, |mon|Self::SetMon { mon }),
});
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct Track { pub struct Track {
@ -80,13 +88,6 @@ pub struct Track {
has!(Clock: |self: Track|self.sequencer.clock); has!(Clock: |self: Track|self.sequencer.clock);
has!(Sequencer: |self: Track|self.sequencer); has!(Sequencer: |self: Track|self.sequencer);
impl HasWidth for Track {
const MIN_WIDTH: usize = 9;
fn width_inc (&mut self) { self.width += 1; }
fn width_dec (&mut self) { if self.width > Track::MIN_WIDTH { self.width -= 1; } }
}
impl Track { impl Track {
/// Create a new track with only the default [Sequencer]. /// Create a new track with only the default [Sequencer].
pub fn new ( pub fn new (
@ -105,7 +106,24 @@ impl Track {
..Default::default() ..Default::default()
}) })
} }
fn audio_ins (&self) -> &[AudioInput] {
self.devices.first().map(|x|x.audio_ins()).unwrap_or_default()
}
fn audio_outs (&self) -> &[AudioOutput] {
self.devices.last().map(|x|x.audio_outs()).unwrap_or_default()
}
fn _todo_opt_bool_stub_ (&self) -> Option<bool> { todo!() }
fn _todo_usize_stub_ (&self) -> usize { todo!() }
fn _todo_arc_str_stub_ (&self) -> Arc<str> { todo!() }
fn _todo_item_theme_stub (&self) -> ItemTheme { todo!() }
} }
impl HasWidth for Track {
const MIN_WIDTH: usize = 9;
fn width_inc (&mut self) { self.width += 1; }
fn width_dec (&mut self) { if self.width > Track::MIN_WIDTH { self.width -= 1; } }
}
#[cfg(feature = "sampler")] #[cfg(feature = "sampler")]
impl Track { impl Track {
/// Create a new track connecting the [Sequencer] to a [Sampler]. /// Create a new track connecting the [Sequencer] to a [Sampler].
@ -148,23 +166,21 @@ impl Track {
None None
} }
} }
def_command!(TrackCommand: |track: Track| {
pub trait HasTrack { Stop => { track.sequencer.enqueue_next(None); Ok(None) },
fn track (&self) -> Option<&Track>; SetMute { mute: Option<bool> } => todo!(),
fn track_mut (&mut self) -> Option<&mut Track>; SetSolo { solo: Option<bool> } => todo!(),
#[cfg(feature = "port")] fn view_midi_ins_status <'a> (&'a self, theme: ItemTheme) -> impl Content<TuiOut> + 'a { SetSize { size: usize } => todo!(),
self.track().map(move|track|view_ports_status(theme, "MIDI ins: ", &track.sequencer.midi_ins)) SetZoom { zoom: usize } => todo!(),
} SetName { name: Arc<str> } =>
#[cfg(feature = "port")] fn view_midi_outs_status (&self, theme: ItemTheme) -> impl Content<TuiOut> + '_ { swap_value(&mut track.name, name, |name|Self::SetName { name }),
self.track().map(move|track|view_ports_status(theme, "MIDI outs: ", &track.sequencer.midi_outs)) SetColor { color: ItemTheme } =>
} swap_value(&mut track.color, color, |color|Self::SetColor { color }),
#[cfg(feature = "port")] fn view_audio_ins_status (&self, theme: ItemTheme) -> impl Content<TuiOut> { SetRec { rec: Option<bool> } =>
self.track().map(move|track|view_ports_status(theme, "Audio ins: ", &track.audio_ins())) toggle_bool(&mut track.sequencer.recording, rec, |rec|Self::SetRec { rec }),
} SetMon { mon: Option<bool> } =>
#[cfg(feature = "port")] fn view_audio_outs_status (&self, theme: ItemTheme) -> impl Content<TuiOut> { toggle_bool(&mut track.sequencer.monitoring, mon, |mon|Self::SetMon { mon }),
self.track().map(move|track|view_ports_status(theme, "Audio outs:", &track.audio_outs())) });
}
}
impl<T: TracksView + ScenesView + Send + Sync> ClipsView for T {} impl<T: TracksView + ScenesView + Send + Sync> ClipsView for T {}
@ -268,13 +284,15 @@ fn view_track_header (theme: ItemTheme, content: impl Content<TuiOut>) -> impl C
Fixed::X(12, Tui::bg(theme.darker.rgb, Fill::X(Align::e(content)))) Fixed::X(12, Tui::bg(theme.darker.rgb, Fill::X(Align::e(content))))
} }
fn view_ports_status <T: JackPort> (theme: ItemTheme, title: &str, ports: &[T]) { fn view_ports_status <'a, T: JackPort> (theme: ItemTheme, title: &'a str, ports: &'a [T])
-> impl Content<TuiOut> + use<'a, T>
{
let ins = ports.len() as u16; let ins = ports.len() as u16;
let frame = Outer(true, Style::default().fg(Tui::g(96))); let frame = Outer(true, Style::default().fg(Tui::g(96)));
let iter = move||ports.iter(); let iter = move||ports.iter();
let names = Map::south(1, iter, |port, index|Fill::Y(Align::w(format!(" {index} {}", port.port_name())))); let names = Map::south(1, iter, move|port, index|Fill::Y(Align::w(format!(" {index} {}", port.port_name()))));
let field = FieldV(theme, title, names); let field = FieldV(theme, title, names);
Fixed::XY(20, 1 + ins, frame.enclose(Fixed::XY(20, 1 + ins, field.content()))) Fixed::XY(20, 1 + ins, frame.enclose(Fixed::XY(20, 1 + ins, field)))
} }
impl Track { impl Track {