mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 20:56:43 +01:00
refactor model into submodules again
This commit is contained in:
parent
deeaaa0b8b
commit
30f43eac79
5 changed files with 183 additions and 179 deletions
157
tek/src/model.rs
157
tek/src/model.rs
|
|
@ -1,4 +1,7 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
mod scene; pub use self::scene::*;
|
||||||
|
mod select; pub use self::select::*;
|
||||||
|
mod track; pub use self::track::*;
|
||||||
#[derive(Default, Debug)] pub struct Tek {
|
#[derive(Default, Debug)] pub struct Tek {
|
||||||
/// Must not be dropped for the duration of the process
|
/// Must not be dropped for the duration of the process
|
||||||
pub jack: Jack,
|
pub jack: Jack,
|
||||||
|
|
@ -182,162 +185,8 @@ impl Tek {
|
||||||
Tui::fg_bg(theme.lightest.rgb, theme.base.rgb, Fixed::y(1, field))
|
Tui::fg_bg(theme.lightest.rgb, theme.base.rgb, Fixed::y(1, field))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Represents the current user selection in the arranger
|
|
||||||
#[derive(PartialEq, Clone, Copy, Debug, Default)] pub enum Selection {
|
|
||||||
/// The whole mix is selected
|
|
||||||
#[default] Mix,
|
|
||||||
/// A track is selected.
|
|
||||||
Track(usize),
|
|
||||||
/// A scene is selected.
|
|
||||||
Scene(usize),
|
|
||||||
/// A clip (track × scene) is selected.
|
|
||||||
Clip(usize, usize),
|
|
||||||
}
|
|
||||||
/// Focus identification methods
|
|
||||||
impl Selection {
|
|
||||||
fn is_mix (&self) -> bool { matches!(self, Self::Mix) }
|
|
||||||
fn is_track (&self) -> bool { matches!(self, Self::Track(_)) }
|
|
||||||
fn is_scene (&self) -> bool { matches!(self, Self::Scene(_)) }
|
|
||||||
fn is_clip (&self) -> bool { matches!(self, Self::Clip(_, _)) }
|
|
||||||
pub fn track (&self) -> Option<usize> {
|
|
||||||
use Selection::*;
|
|
||||||
match self { Clip(t, _) => Some(*t), Track(t) => Some(*t), _ => None }
|
|
||||||
}
|
|
||||||
pub fn scene (&self) -> Option<usize> {
|
|
||||||
use Selection::*;
|
|
||||||
match self { Clip(_, s) => Some(*s), Scene(s) => Some(*s), _ => None }
|
|
||||||
}
|
|
||||||
fn description (&self, tracks: &[Track], scenes: &[Scene]) -> Arc<str> {
|
|
||||||
format!("Selected: {}", match self {
|
|
||||||
Self::Mix => "Everything".to_string(),
|
|
||||||
Self::Track(t) => tracks.get(*t).map(|track|format!("T{t}: {}", &track.name))
|
|
||||||
.unwrap_or_else(||"T??".into()),
|
|
||||||
Self::Scene(s) => scenes.get(*s).map(|scene|format!("S{s}: {}", &scene.name))
|
|
||||||
.unwrap_or_else(||"S??".into()),
|
|
||||||
Self::Clip(t, s) => match (tracks.get(*t), scenes.get(*s)) {
|
|
||||||
(Some(_), Some(scene)) => match scene.clip(*t) {
|
|
||||||
Some(clip) => format!("T{t} S{s} C{}", &clip.read().unwrap().name),
|
|
||||||
None => format!("T{t} S{s}: Empty")
|
|
||||||
},
|
|
||||||
_ => format!("T{t} S{s}: Empty"),
|
|
||||||
}
|
|
||||||
}).into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl HasSelection for Tek {
|
|
||||||
fn selected (&self) -> &Selection { &self.selected }
|
|
||||||
fn selected_mut (&mut self) -> &mut Selection { &mut self.selected }
|
|
||||||
}
|
|
||||||
pub trait HasSelection {
|
|
||||||
fn selected (&self) -> &Selection;
|
|
||||||
fn selected_mut (&mut self) -> &mut Selection;
|
|
||||||
}
|
|
||||||
#[derive(Debug, Default)] pub struct Track {
|
|
||||||
/// Name of track
|
|
||||||
pub name: Arc<str>,
|
|
||||||
/// Preferred width of track column
|
|
||||||
pub width: usize,
|
|
||||||
/// Identifying color of track
|
|
||||||
pub color: ItemPalette,
|
|
||||||
/// MIDI player state
|
|
||||||
pub player: MidiPlayer,
|
|
||||||
/// Device chain
|
|
||||||
pub devices: Vec<Box<dyn Device>>,
|
|
||||||
/// Inputs of 1st device
|
|
||||||
pub audio_ins: Vec<JackAudioIn>,
|
|
||||||
/// Outputs of last device
|
|
||||||
pub audio_outs: Vec<JackAudioOut>,
|
|
||||||
}
|
|
||||||
has_clock!(|self: Track|self.player.clock);
|
|
||||||
has_player!(|self: Track|self.player);
|
|
||||||
impl 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 HasTracks for Tek {
|
|
||||||
fn midi_ins (&self) -> &Vec<JackMidiIn> { &self.midi_ins }
|
|
||||||
fn midi_outs (&self) -> &Vec<JackMidiOut> { &self.midi_outs }
|
|
||||||
fn tracks (&self) -> &Vec<Track> { &self.tracks }
|
|
||||||
fn tracks_mut (&mut self) -> &mut Vec<Track> { &mut self.tracks }
|
|
||||||
}
|
|
||||||
pub trait HasTracks: HasSelection + HasClock + HasJack + HasEditor + Send + Sync {
|
|
||||||
fn midi_ins (&self) -> &Vec<JackMidiIn>;
|
|
||||||
fn midi_outs (&self) -> &Vec<JackMidiOut>;
|
|
||||||
fn tracks (&self) -> &Vec<Track>;
|
|
||||||
fn tracks_mut (&mut self) -> &mut Vec<Track>;
|
|
||||||
fn track_longest (&self) -> usize {
|
|
||||||
self.tracks().iter().map(|s|s.name.len()).fold(0, usize::max)
|
|
||||||
}
|
|
||||||
fn track_next_name (&self) -> Arc<str> {
|
|
||||||
format!("Track{:02}", self.tracks().len() + 1).into()
|
|
||||||
}
|
|
||||||
fn track (&self) -> Option<&Track> {
|
|
||||||
self.selected().track().and_then(|s|self.tracks().get(s))
|
|
||||||
}
|
|
||||||
fn track_mut (&mut self) -> Option<&mut Track> {
|
|
||||||
self.selected().track().and_then(|s|self.tracks_mut().get_mut(s))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub trait Device: Send + Sync + std::fmt::Debug {
|
pub trait Device: Send + Sync + std::fmt::Debug {
|
||||||
fn boxed <'a> (self) -> Box<dyn Device + 'a> where Self: Sized + 'a { Box::new(self) }
|
fn boxed <'a> (self) -> Box<dyn Device + 'a> where Self: Sized + 'a { Box::new(self) }
|
||||||
}
|
}
|
||||||
impl Device for Sampler {}
|
impl Device for Sampler {}
|
||||||
impl Device for Plugin {}
|
impl Device for Plugin {}
|
||||||
#[derive(Debug, Default)] pub struct Scene {
|
|
||||||
/// Name of scene
|
|
||||||
pub name: Arc<str>,
|
|
||||||
/// Clips in scene, one per track
|
|
||||||
pub clips: Vec<Option<Arc<RwLock<MidiClip>>>>,
|
|
||||||
/// Identifying color of scene
|
|
||||||
pub color: ItemPalette,
|
|
||||||
}
|
|
||||||
impl Scene {
|
|
||||||
/// Returns the pulse length of the longest clip in the scene
|
|
||||||
fn pulses (&self) -> usize {
|
|
||||||
self.clips.iter().fold(0, |a, p|{
|
|
||||||
a.max(p.as_ref().map(|q|q.read().unwrap().length).unwrap_or(0))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/// Returns true if all clips in the scene are
|
|
||||||
/// currently playing on the given collection of tracks.
|
|
||||||
fn is_playing (&self, tracks: &[Track]) -> bool {
|
|
||||||
self.clips.iter().any(|clip|clip.is_some()) && self.clips.iter().enumerate()
|
|
||||||
.all(|(track_index, clip)|match clip {
|
|
||||||
Some(c) => tracks
|
|
||||||
.get(track_index)
|
|
||||||
.map(|track|{
|
|
||||||
if let Some((_, Some(clip))) = track.player().play_clip() {
|
|
||||||
*clip.read().unwrap() == *c.read().unwrap()
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.unwrap_or(false),
|
|
||||||
None => true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
fn clip (&self, index: usize) -> Option<&Arc<RwLock<MidiClip>>> {
|
|
||||||
match self.clips.get(index) { Some(Some(clip)) => Some(clip), _ => None }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl HasScenes for Tek {
|
|
||||||
fn scenes (&self) -> &Vec<Scene> { &self.scenes }
|
|
||||||
fn scenes_mut (&mut self) -> &mut Vec<Scene> { &mut self.scenes }
|
|
||||||
}
|
|
||||||
pub trait HasScenes: HasSelection + HasEditor + Send + Sync {
|
|
||||||
fn scenes (&self) -> &Vec<Scene>;
|
|
||||||
fn scenes_mut (&mut self) -> &mut Vec<Scene>;
|
|
||||||
fn scene_longest (&self) -> usize {
|
|
||||||
self.scenes().iter().map(|s|s.name.len()).fold(0, usize::max)
|
|
||||||
}
|
|
||||||
fn scene (&self) -> Option<&Scene> {
|
|
||||||
self.selected().scene().and_then(|s|self.scenes().get(s))
|
|
||||||
}
|
|
||||||
fn scene_mut (&mut self) -> Option<&mut Scene> {
|
|
||||||
self.selected().scene().and_then(|s|self.scenes_mut().get_mut(s))
|
|
||||||
}
|
|
||||||
fn scene_del (&mut self, index: usize) {
|
|
||||||
self.selected().scene().and_then(|s|Some(self.scenes_mut().remove(index)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
58
tek/src/model/scene.rs
Normal file
58
tek/src/model/scene.rs
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
use crate::*;
|
||||||
|
pub trait HasScenes: HasSelection + HasEditor + Send + Sync {
|
||||||
|
fn scenes (&self) -> &Vec<Scene>;
|
||||||
|
fn scenes_mut (&mut self) -> &mut Vec<Scene>;
|
||||||
|
fn scene_longest (&self) -> usize {
|
||||||
|
self.scenes().iter().map(|s|s.name.len()).fold(0, usize::max)
|
||||||
|
}
|
||||||
|
fn scene (&self) -> Option<&Scene> {
|
||||||
|
self.selected().scene().and_then(|s|self.scenes().get(s))
|
||||||
|
}
|
||||||
|
fn scene_mut (&mut self) -> Option<&mut Scene> {
|
||||||
|
self.selected().scene().and_then(|s|self.scenes_mut().get_mut(s))
|
||||||
|
}
|
||||||
|
fn scene_del (&mut self, index: usize) {
|
||||||
|
self.selected().scene().and_then(|s|Some(self.scenes_mut().remove(index)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Debug, Default)] pub struct Scene {
|
||||||
|
/// Name of scene
|
||||||
|
pub name: Arc<str>,
|
||||||
|
/// Clips in scene, one per track
|
||||||
|
pub clips: Vec<Option<Arc<RwLock<MidiClip>>>>,
|
||||||
|
/// Identifying color of scene
|
||||||
|
pub color: ItemPalette,
|
||||||
|
}
|
||||||
|
impl Scene {
|
||||||
|
/// Returns the pulse length of the longest clip in the scene
|
||||||
|
fn pulses (&self) -> usize {
|
||||||
|
self.clips.iter().fold(0, |a, p|{
|
||||||
|
a.max(p.as_ref().map(|q|q.read().unwrap().length).unwrap_or(0))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/// Returns true if all clips in the scene are
|
||||||
|
/// currently playing on the given collection of tracks.
|
||||||
|
fn is_playing (&self, tracks: &[Track]) -> bool {
|
||||||
|
self.clips.iter().any(|clip|clip.is_some()) && self.clips.iter().enumerate()
|
||||||
|
.all(|(track_index, clip)|match clip {
|
||||||
|
Some(c) => tracks
|
||||||
|
.get(track_index)
|
||||||
|
.map(|track|{
|
||||||
|
if let Some((_, Some(clip))) = track.player().play_clip() {
|
||||||
|
*clip.read().unwrap() == *c.read().unwrap()
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap_or(false),
|
||||||
|
None => true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
pub fn clip (&self, index: usize) -> Option<&Arc<RwLock<MidiClip>>> {
|
||||||
|
match self.clips.get(index) { Some(Some(clip)) => Some(clip), _ => None }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl HasScenes for Tek {
|
||||||
|
fn scenes (&self) -> &Vec<Scene> { &self.scenes }
|
||||||
|
fn scenes_mut (&mut self) -> &mut Vec<Scene> { &mut self.scenes }
|
||||||
|
}
|
||||||
51
tek/src/model/select.rs
Normal file
51
tek/src/model/select.rs
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
use crate::*;
|
||||||
|
pub trait HasSelection {
|
||||||
|
fn selected (&self) -> &Selection;
|
||||||
|
fn selected_mut (&mut self) -> &mut Selection;
|
||||||
|
}
|
||||||
|
/// Represents the current user selection in the arranger
|
||||||
|
#[derive(PartialEq, Clone, Copy, Debug, Default)] pub enum Selection {
|
||||||
|
/// The whole mix is selected
|
||||||
|
#[default] Mix,
|
||||||
|
/// A track is selected.
|
||||||
|
Track(usize),
|
||||||
|
/// A scene is selected.
|
||||||
|
Scene(usize),
|
||||||
|
/// A clip (track × scene) is selected.
|
||||||
|
Clip(usize, usize),
|
||||||
|
}
|
||||||
|
/// Focus identification methods
|
||||||
|
impl Selection {
|
||||||
|
fn is_mix (&self) -> bool { matches!(self, Self::Mix) }
|
||||||
|
fn is_track (&self) -> bool { matches!(self, Self::Track(_)) }
|
||||||
|
fn is_scene (&self) -> bool { matches!(self, Self::Scene(_)) }
|
||||||
|
fn is_clip (&self) -> bool { matches!(self, Self::Clip(_, _)) }
|
||||||
|
pub fn track (&self) -> Option<usize> {
|
||||||
|
use Selection::*;
|
||||||
|
match self { Clip(t, _) => Some(*t), Track(t) => Some(*t), _ => None }
|
||||||
|
}
|
||||||
|
pub fn scene (&self) -> Option<usize> {
|
||||||
|
use Selection::*;
|
||||||
|
match self { Clip(_, s) => Some(*s), Scene(s) => Some(*s), _ => None }
|
||||||
|
}
|
||||||
|
fn description (&self, tracks: &[Track], scenes: &[Scene]) -> Arc<str> {
|
||||||
|
format!("Selected: {}", match self {
|
||||||
|
Self::Mix => "Everything".to_string(),
|
||||||
|
Self::Track(t) => tracks.get(*t).map(|track|format!("T{t}: {}", &track.name))
|
||||||
|
.unwrap_or_else(||"T??".into()),
|
||||||
|
Self::Scene(s) => scenes.get(*s).map(|scene|format!("S{s}: {}", &scene.name))
|
||||||
|
.unwrap_or_else(||"S??".into()),
|
||||||
|
Self::Clip(t, s) => match (tracks.get(*t), scenes.get(*s)) {
|
||||||
|
(Some(_), Some(scene)) => match scene.clip(*t) {
|
||||||
|
Some(clip) => format!("T{t} S{s} C{}", &clip.read().unwrap().name),
|
||||||
|
None => format!("T{t} S{s}: Empty")
|
||||||
|
},
|
||||||
|
_ => format!("T{t} S{s}: Empty"),
|
||||||
|
}
|
||||||
|
}).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl HasSelection for Tek {
|
||||||
|
fn selected (&self) -> &Selection { &self.selected }
|
||||||
|
fn selected_mut (&mut self) -> &mut Selection { &mut self.selected }
|
||||||
|
}
|
||||||
49
tek/src/model/track.rs
Normal file
49
tek/src/model/track.rs
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
use crate::*;
|
||||||
|
pub trait HasTracks: HasSelection + HasClock + HasJack + HasEditor + Send + Sync {
|
||||||
|
fn midi_ins (&self) -> &Vec<JackMidiIn>;
|
||||||
|
fn midi_outs (&self) -> &Vec<JackMidiOut>;
|
||||||
|
fn tracks (&self) -> &Vec<Track>;
|
||||||
|
fn tracks_mut (&mut self) -> &mut Vec<Track>;
|
||||||
|
fn track_longest (&self) -> usize {
|
||||||
|
self.tracks().iter().map(|s|s.name.len()).fold(0, usize::max)
|
||||||
|
}
|
||||||
|
const WIDTH_OFFSET: usize = 1;
|
||||||
|
fn track_next_name (&self) -> Arc<str> {
|
||||||
|
format!("Track{:02}", self.tracks().len() + 1).into()
|
||||||
|
}
|
||||||
|
fn track (&self) -> Option<&Track> {
|
||||||
|
self.selected().track().and_then(|s|self.tracks().get(s))
|
||||||
|
}
|
||||||
|
fn track_mut (&mut self) -> Option<&mut Track> {
|
||||||
|
self.selected().track().and_then(|s|self.tracks_mut().get_mut(s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Debug, Default)] pub struct Track {
|
||||||
|
/// Name of track
|
||||||
|
pub name: Arc<str>,
|
||||||
|
/// Preferred width of track column
|
||||||
|
pub width: usize,
|
||||||
|
/// Identifying color of track
|
||||||
|
pub color: ItemPalette,
|
||||||
|
/// MIDI player state
|
||||||
|
pub player: MidiPlayer,
|
||||||
|
/// Device chain
|
||||||
|
pub devices: Vec<Box<dyn Device>>,
|
||||||
|
/// Inputs of 1st device
|
||||||
|
pub audio_ins: Vec<JackAudioIn>,
|
||||||
|
/// Outputs of last device
|
||||||
|
pub audio_outs: Vec<JackAudioOut>,
|
||||||
|
}
|
||||||
|
has_clock!(|self: Track|self.player.clock);
|
||||||
|
has_player!(|self: Track|self.player);
|
||||||
|
impl 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 HasTracks for Tek {
|
||||||
|
fn midi_ins (&self) -> &Vec<JackMidiIn> { &self.midi_ins }
|
||||||
|
fn midi_outs (&self) -> &Vec<JackMidiOut> { &self.midi_outs }
|
||||||
|
fn tracks (&self) -> &Vec<Track> { &self.tracks }
|
||||||
|
fn tracks_mut (&mut self) -> &mut Vec<Track> { &mut self.tracks }
|
||||||
|
}
|
||||||
|
|
@ -67,7 +67,6 @@ view!(TuiOut: |self: Tek| self.size.of(View(self, self.view)); {
|
||||||
":scenes" => self.view_scenes().boxed(),
|
":scenes" => self.view_scenes().boxed(),
|
||||||
":status" => self.view_editor().boxed(),
|
":status" => self.view_editor().boxed(),
|
||||||
":toolbar" => self.view_clock().boxed(),
|
":toolbar" => self.view_clock().boxed(),
|
||||||
":track-add" => self.view_track_add().boxed(),
|
|
||||||
":tracks" => self.view_tracks().boxed(),
|
":tracks" => self.view_tracks().boxed(),
|
||||||
});
|
});
|
||||||
provide_num!(u16: |self: Tek| {
|
provide_num!(u16: |self: Tek| {
|
||||||
|
|
@ -291,12 +290,6 @@ impl Tek {
|
||||||
let content = Fixed::y(1, f(index, track));
|
let content = Fixed::y(1, f(index, track));
|
||||||
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, Fixed::x(width, styled)) }) }
|
map_east(x1 as u16, width, Fixed::x(width, styled)) }) }
|
||||||
fn io_heading <'a, T: PortsSizes<'a>> (
|
|
||||||
&'a self, key: &'a str, label: &'a str, count: usize,
|
|
||||||
fg: Color, bg: Color, iter: impl Fn()->T + Send + Sync + 'a,
|
|
||||||
) -> impl Content<TuiOut> + 'a {
|
|
||||||
self.heading(key, label, count, self.io_ports(fg, bg, iter))
|
|
||||||
}
|
|
||||||
fn io_ports <'a, T: PortsSizes<'a>> (
|
fn io_ports <'a, T: PortsSizes<'a>> (
|
||||||
&'a self, fg: Color, bg: Color, iter: impl Fn()->T + Send + Sync + 'a
|
&'a self, fg: Color, bg: Color, iter: impl Fn()->T + Send + Sync + 'a
|
||||||
) -> impl Content<TuiOut> + 'a {
|
) -> impl Content<TuiOut> + 'a {
|
||||||
|
|
@ -305,7 +298,7 @@ impl Tek {
|
||||||
Fill::x(Tui::bold(true, Tui::fg_bg(fg, bg, Align::w(Bsp::e(" ", name))))),
|
Fill::x(Tui::bold(true, Tui::fg_bg(fg, bg, Align::w(Bsp::e(" ", name))))),
|
||||||
Map::new(||connections.iter(), move|connect, index|map_south(index as u16, 1,
|
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,
|
Fill::x(Align::w(Tui::bold(false, Tui::fg_bg(fg, bg,
|
||||||
&connect.info[..(self.w_sidebar() as usize).min(connect.info.len())])))))))))}
|
&connect.info)))))))))}
|
||||||
fn io_connections <'a, T: PortsSizes<'a>> (
|
fn io_connections <'a, T: PortsSizes<'a>> (
|
||||||
&'a self, fg: Color, bg: Color, iter: impl Fn()->T + Send + Sync + 'a
|
&'a self, fg: Color, bg: Color, iter: impl Fn()->T + Send + Sync + 'a
|
||||||
) -> impl Content<TuiOut> + 'a {
|
) -> impl Content<TuiOut> + 'a {
|
||||||
|
|
@ -351,10 +344,15 @@ impl Tek {
|
||||||
|
|
||||||
// TRACKS /////////////////////////////////////////////////////////////////////////////////////
|
// TRACKS /////////////////////////////////////////////////////////////////////////////////////
|
||||||
fn view_tracks (&self) -> impl Content<TuiOut> + use<'_> {
|
fn view_tracks (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
let height = 3;
|
self.row(self.w(), 3, Tui::bg(Tui::g(32), Fill::x(Align::w({
|
||||||
let heading: ThunkBox<_> =
|
let data = (self.selected.track().unwrap_or(0), self.tracks().len());
|
||||||
(move||Tui::bg(Tui::g(32), Fill::x(Align::w(self.view_track_add()))).boxed()).into();
|
self.fmtd.write().unwrap().trks.update(Some(data),
|
||||||
let content = self.per_track(|t, track|{
|
rewrite!(buf, "({}/{})", data.0, data.1));
|
||||||
|
Bsp::e(
|
||||||
|
self.button3(" t", "track", self.fmtd.read().unwrap().trks.view.clone()),
|
||||||
|
self.button2(" T", "add track"),
|
||||||
|
)
|
||||||
|
}))), self.per_track(|t, track|{
|
||||||
let active = self.selected().track() == Some(t+1);
|
let active = self.selected().track() == Some(t+1);
|
||||||
let name = &track.name;
|
let name = &track.name;
|
||||||
let fg = track.color.lightest.rgb;
|
let fg = track.color.lightest.rgb;
|
||||||
|
|
@ -362,14 +360,7 @@ impl Tek {
|
||||||
let bg2 = Reset;//if t > 0 { self.tracks()[t - 1].color.base.rgb } else { Reset };
|
let bg2 = Reset;//if t > 0 { self.tracks()[t - 1].color.base.rgb } else { Reset };
|
||||||
let bfg = if active { Rgb(255,255,255) } else { Rgb(0,0,0) };
|
let bfg = if active { Rgb(255,255,255) } else { Rgb(0,0,0) };
|
||||||
Self::wrap(bg, fg, Tui::bold(true, Fill::x(Align::nw(name))))
|
Self::wrap(bg, fg, Tui::bold(true, Fill::x(Align::nw(name))))
|
||||||
});
|
}))
|
||||||
self.row(self.w(), height, heading, content)
|
|
||||||
}
|
|
||||||
fn view_track_add (&self) -> impl Content<TuiOut> + use<'_> {
|
|
||||||
let data = (self.selected.track().unwrap_or(0), self.tracks().len());
|
|
||||||
self.fmtd.write().unwrap().trks.update(Some(data),
|
|
||||||
rewrite!(buf, "({}/{})", data.0, data.1));
|
|
||||||
self.button3(" T", "track", self.fmtd.read().unwrap().trks.view.clone())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ACTIVE CLIPS ///////////////////////////////////////////////////////////////////////////////
|
// ACTIVE CLIPS ///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -392,13 +383,16 @@ impl Tek {
|
||||||
// INPUTS /////////////////////////////////////////////////////////////////////////////////////
|
// INPUTS /////////////////////////////////////////////////////////////////////////////////////
|
||||||
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 key = " I";
|
let key = " i";
|
||||||
let label = "midi ins";
|
let label = "midi ins";
|
||||||
let count = self.midi_ins.len();
|
let count = self.midi_ins.len();
|
||||||
Bsp::s(
|
Bsp::s(
|
||||||
Bsp::s(
|
Bsp::s(
|
||||||
self.row_top(self.w(), 1,
|
self.row_top(self.w(), 1,
|
||||||
Fill::x(Align::w(self.button3(key, label, format!("{count}")))),
|
Fill::x(Align::w(Bsp::e(
|
||||||
|
self.button3(" i", "midi ins", format!("{count}")),
|
||||||
|
self.button2(" I", "add midi in"),
|
||||||
|
))),
|
||||||
self.per_track_top(move|t, track|{
|
self.per_track_top(move|t, track|{
|
||||||
let rec = track.player.recording;
|
let rec = track.player.recording;
|
||||||
let mon = track.player.monitoring;
|
let mon = track.player.monitoring;
|
||||||
|
|
@ -412,7 +406,7 @@ impl Tek {
|
||||||
let bg2 = if t > 0 { self.tracks()[t - 1].color.base.rgb } else { Reset };
|
let bg2 = if t > 0 { self.tracks()[t - 1].color.base.rgb } else { Reset };
|
||||||
Self::wrap(bg, fg, Tui::bold(true, Fill::x(Bsp::e(
|
Self::wrap(bg, fg, Tui::bold(true, Fill::x(Bsp::e(
|
||||||
Tui::fg_bg(rec, bg, "Rec "),
|
Tui::fg_bg(rec, bg, "Rec "),
|
||||||
Tui::fg_bg(rec, bg, "Mon ")))))})),
|
Tui::fg_bg(mon, bg, "Mon ")))))})),
|
||||||
self.row_top(self.w(), self.h_inputs() - 1,
|
self.row_top(self.w(), self.h_inputs() - 1,
|
||||||
self.io_ports(fg, Tui::g(32), ||self.inputs_sizes()),
|
self.io_ports(fg, Tui::g(32), ||self.inputs_sizes()),
|
||||||
self.per_track_top(move|t, track|self.io_connections(
|
self.per_track_top(move|t, track|self.io_connections(
|
||||||
|
|
@ -428,7 +422,7 @@ impl Tek {
|
||||||
// OUTPUTS ////////////////////////////////////////////////////////////////////////////////////
|
// OUTPUTS ////////////////////////////////////////////////////////////////////////////////////
|
||||||
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 key = " O";
|
let key = " o";
|
||||||
let label = "midi outs";
|
let label = "midi outs";
|
||||||
let count = self.midi_outs.len();
|
let count = self.midi_outs.len();
|
||||||
Align::n(Bsp::s(
|
Align::n(Bsp::s(
|
||||||
|
|
@ -438,7 +432,10 @@ impl Tek {
|
||||||
),
|
),
|
||||||
Bsp::s(
|
Bsp::s(
|
||||||
self.row_top(self.w(), 1,
|
self.row_top(self.w(), 1,
|
||||||
Fill::x(Align::w(self.button3(key, label, format!("{count}")))),
|
Fill::x(Align::w(Bsp::e(
|
||||||
|
self.button3(" o", "midi outs", format!("{count}")),
|
||||||
|
self.button2(" O", "add midi out"),
|
||||||
|
))),
|
||||||
self.per_track_top(move|t, track|{
|
self.per_track_top(move|t, track|{
|
||||||
let mute = false;
|
let mute = false;
|
||||||
let solo = false;
|
let solo = false;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue