mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 03:36:41 +01:00
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:
parent
ef81b085a0
commit
e6bf5c1f6e
4 changed files with 79 additions and 60 deletions
|
|
@ -1,6 +1,6 @@
|
|||
pub(crate) use ::{
|
||||
tek_device::*,
|
||||
tek_device::tengri::{
|
||||
tengri::{
|
||||
Usually, Perhaps, Has, MaybeHas, has, maybe_has, impl_debug, from,
|
||||
dsl::*,
|
||||
input::*,
|
||||
|
|
@ -8,7 +8,9 @@ pub(crate) use ::{
|
|||
tui::{
|
||||
*,
|
||||
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::{
|
||||
self,
|
||||
|
|
@ -31,6 +33,5 @@ pub(crate) use ::{
|
|||
thread::JoinHandle
|
||||
},
|
||||
xdg::BaseDirectories,
|
||||
atomic_float::*,
|
||||
tengri::tui::ratatui::{prelude::Rect, widgets::{Widget, canvas::{Canvas, Line}}},
|
||||
atomic_float::*
|
||||
};
|
||||
|
|
|
|||
2
deps/tengri
vendored
2
deps/tengri
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit 41fa55fa6ca15abd0a80fd50a30326b1fea6b5f1
|
||||
Subproject commit 8c54510f630e8a81b7d7bdca0a51a69cdb9dffcc
|
||||
|
|
@ -118,7 +118,7 @@ pub trait ScenesView:
|
|||
})
|
||||
}
|
||||
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));
|
||||
}))
|
||||
}
|
||||
|
|
@ -182,7 +182,7 @@ impl Scene {
|
|||
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,
|
||||
//length: h_scenes_area as usize,
|
||||
//total: h_scenes as usize,
|
||||
|
|
|
|||
124
device/track.rs
124
device/track.rs
|
|
@ -1,6 +1,6 @@
|
|||
use crate::*;
|
||||
|
||||
def_sizes_iter!(TracksSizes => Track);
|
||||
def_sizes_iter!(TracksSizes => Track);
|
||||
|
||||
impl<T: Has<Vec<Track>> + Send + Sync> HasTracks for T {}
|
||||
|
||||
|
|
@ -36,33 +36,41 @@ pub trait HasTracks: Has<Vec<Track>> + Send + Sync {
|
|||
const TRACK_SPACING: usize = 0;
|
||||
}
|
||||
|
||||
pub trait HasTrackScroll: HasTracks { fn track_scroll (&self) -> usize; }
|
||||
impl HasTrackScroll for Arrangement { fn track_scroll (&self) -> usize { self.track_scroll } }
|
||||
pub trait HasTrackScroll: HasTracks {
|
||||
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 {
|
||||
fn track (&self) -> Option<&Track> { self.get() }
|
||||
fn track_mut (&mut self) -> Option<&mut Track> { self.get_mut() }
|
||||
fn track (&self) -> Option<&Track> {
|
||||
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)]
|
||||
pub struct Track {
|
||||
|
|
@ -80,13 +88,6 @@ pub struct Track {
|
|||
|
||||
has!(Clock: |self: Track|self.sequencer.clock);
|
||||
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 {
|
||||
/// Create a new track with only the default [Sequencer].
|
||||
pub fn new (
|
||||
|
|
@ -105,7 +106,24 @@ impl Track {
|
|||
..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")]
|
||||
impl Track {
|
||||
/// Create a new track connecting the [Sequencer] to a [Sampler].
|
||||
|
|
@ -148,23 +166,21 @@ impl Track {
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
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()))
|
||||
}
|
||||
}
|
||||
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 }),
|
||||
});
|
||||
|
||||
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))))
|
||||
}
|
||||
|
||||
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 frame = Outer(true, Style::default().fg(Tui::g(96)));
|
||||
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);
|
||||
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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue