mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +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 ::{
|
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
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> {
|
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,
|
||||||
|
|
|
||||||
124
device/track.rs
124
device/track.rs
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
def_sizes_iter!(TracksSizes => Track);
|
def_sizes_iter!(TracksSizes => Track);
|
||||||
|
|
||||||
impl<T: Has<Vec<Track>> + Send + Sync> HasTracks for T {}
|
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;
|
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 {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue