diff --git a/crates/app/src/lib.rs b/crates/app/src/lib.rs index 602ce67a..ee5f836d 100644 --- a/crates/app/src/lib.rs +++ b/crates/app/src/lib.rs @@ -18,7 +18,8 @@ #![feature(closure_lifetime_binder)] pub use ::tek_engine:: *; pub use ::tek_device::{self, *}; -pub use ::tengri::{Usually, Perhaps, Has}; +pub use ::tengri::{Usually, Perhaps, Has, MaybeHas}; +pub use ::tengri::{has, maybe_has}; pub use ::tengri::dsl::*; pub use ::tengri::input::*; pub use ::tengri::output::*; diff --git a/crates/app/src/model.rs b/crates/app/src/model.rs index 1138f078..bbdae9eb 100644 --- a/crates/app/src/model.rs +++ b/crates/app/src/model.rs @@ -36,6 +36,12 @@ has!(Vec: |self: App|self.project.midi_outs); has!(Vec: |self: App|self.project.scenes); has!(Vec: |self: App|self.project.tracks); has!(Measure: |self: App|self.size); +maybe_has!(Track: |self: App| + { MaybeHas::::get(&self.project) }; + { MaybeHas::::get_mut(&mut self.project) }); +maybe_has!(Scene: |self: App| + { MaybeHas::::get(&self.project) }; + { MaybeHas::::get_mut(&mut self.project) }); has_clips!(|self: App|self.project.pool.clips); has_editor!(|self: App|{ diff --git a/crates/app/src/view.rs b/crates/app/src/view.rs index d5723f74..42153fd8 100644 --- a/crates/app/src/view.rs +++ b/crates/app/src/view.rs @@ -61,45 +61,20 @@ impl App { self.editor() } pub fn view_editor_status (&self) -> impl Content + use<'_> { - self.editor().map(|e|Bsp::s(e.clip_status(), e.edit_status())) + self.editor().map(|e|Fixed::x(20, Outer(true, Style::default().fg(Tui::g(96))).enclose( + Fill::y(Align::n(Bsp::s(e.clip_status(), e.edit_status())))))) } pub fn view_midi_ins_status (&self) -> impl Content + use<'_> { - self.project.get_track().map(|track|{ - let ins = track.sequencer.midi_ins.len() as u16; - Fixed::xy(20, 1 + ins, Outer(true, Style::default().fg(Tui::g(96))).enclose( - Fixed::xy(20, 1 + ins, FieldV(self.color, format!("MIDI ins: "), - Map::south(1, ||track.sequencer.midi_ins.iter(), - |port, index|Fill::x(Align::w(format!(" {index} {}", port.name())))))))) - }) + self.project.view_midi_ins_status(self.color) } pub fn view_midi_outs_status (&self) -> impl Content + use<'_> { - self.project.get_track().map(|track|{ - let outs = track.sequencer.midi_outs.len() as u16; - Fixed::xy(20, 1 + outs, Outer(true, Style::default().fg(Tui::g(96))).enclose( - Fixed::xy(20, 1 + outs, FieldV(self.color, format!("MIDI outs: "), - Map::south(1, ||track.sequencer.midi_outs.iter(), - |port, index|Fill::x(Align::w(format!(" {index} {}", port.name())))))))) - }) + self.project.view_midi_outs_status(self.color) } pub fn view_audio_ins_status (&self) -> impl Content + use<'_> { - self.project.get_track() - .and_then(|track|track.devices.get(0)) - .map(|device|{ - let ins = device.audio_ins().len() as u16; - Fixed::xy(20, 1 + ins, Outer(true, Style::default().fg(Tui::g(96))).enclose( - Fixed::xy(20, 1 + ins, FieldV(self.color, format!("Audio ins: "), - Map::south(1, ||device.audio_ins().iter(), - |port, index|Fill::x(Align::w(format!(" {index} {}", port.name()))))))))}) + self.project.view_audio_ins_status(self.color) } pub fn view_audio_outs_status (&self) -> impl Content + use<'_> { - self.project.get_track() - .and_then(|track|track.devices.last()) - .map(|device|{ - let outs = device.audio_outs().len() as u16; - Fixed::xy(20, 1 + outs, Outer(true, Style::default().fg(Tui::g(96))).enclose( - Fixed::xy(20, 1 + outs, FieldV(self.color, format!("Audio outs: "), - Map::south(1, ||device.audio_outs().iter(), - |port, index|Fill::x(Align::w(format!(" {index} {}", port.name()))))))))}) + self.project.view_audio_outs_status(self.color) } pub fn view_arranger (&self) -> impl Content + use<'_> { ArrangerView::new(&self.project, self.editor.as_ref()) @@ -255,7 +230,8 @@ impl App { self.project.sampler().map(|s|s.view_sample_info(self.editor().unwrap().get_note_pos())) } pub fn view_sample_status (&self) -> impl Content + use<'_> { - self.project.sampler().map(|s|s.view_sample_status(self.editor().unwrap().get_note_pos())) + self.project.sampler().map(|s|Outer(true, Style::default().fg(Tui::g(96))).enclose( + Fill::y(Align::n(s.view_sample_status(self.editor().unwrap().get_note_pos()))))) } pub fn view_meters_input (&self) -> impl Content + use<'_> { self.project.sampler().map(|s|s.view_meters_input()) diff --git a/crates/device/src/arranger/arranger_api.rs b/crates/device/src/arranger/arranger_api.rs index daa31c67..1b6343a2 100644 --- a/crates/device/src/arranger/arranger_api.rs +++ b/crates/device/src/arranger/arranger_api.rs @@ -192,6 +192,12 @@ impl ArrangementCommand { } } +impl<'state> Context<'state, TrackCommand> for Arrangement { + fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option { + Context::get(&self, iter) + } +} + impl<'state> Context<'state, MidiInputCommand> for Arrangement { fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option { Context::get(&self, iter) diff --git a/crates/device/src/arranger/arranger_model.rs b/crates/device/src/arranger/arranger_model.rs index a34134d7..32551797 100644 --- a/crates/device/src/arranger/arranger_model.rs +++ b/crates/device/src/arranger/arranger_model.rs @@ -47,6 +47,12 @@ has!(Vec: |self: Arrangement|self.midi_outs); has!(Vec: |self: Arrangement|self.scenes); has!(Vec: |self: Arrangement|self.tracks); has!(Measure: |self: Arrangement|self.size); +maybe_has!(Track: |self: Arrangement| + { Has::::get(self).track().map(|index|Has::>::get(self).get(index)).flatten() }; + { Has::::get(self).track().map(|index|Has::>::get_mut(self).get_mut(index)).flatten() }); +maybe_has!(Scene: |self: Arrangement| + { Has::::get(self).track().map(|index|Has::>::get(self).get(index)).flatten() }; + { Has::::get(self).track().map(|index|Has::>::get_mut(self).get_mut(index)).flatten() }); impl Arrangement { /// Width of display diff --git a/crates/device/src/arranger/arranger_track.rs b/crates/device/src/arranger/arranger_track.rs index 20b1157d..09fb56e2 100644 --- a/crates/device/src/arranger/arranger_track.rs +++ b/crates/device/src/arranger/arranger_track.rs @@ -1,8 +1,11 @@ use crate::*; -impl<'state> Context<'state, TrackCommand> for Arrangement { - fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option { - Context::get(&self, iter) +impl> HasTrack for T { + fn track (&self) -> Option<&Track> { + self.get() + } + fn track_mut (&mut self) -> Option<&mut Track> { + self.get_mut() } } @@ -152,6 +155,38 @@ impl Track { pub trait HasTrack { fn track (&self) -> Option<&Track>; fn track_mut (&mut self) -> Option<&mut Track>; + fn view_midi_ins_status (&self, theme: ItemTheme) -> impl Content { + self.track().map(|track|{ + let ins = track.sequencer.midi_ins.len() as u16; + Fixed::xy(20, 1 + ins, Outer(true, Style::default().fg(Tui::g(96))).enclose( + Fixed::xy(20, 1 + ins, FieldV(theme, format!("MIDI ins: "), + Map::south(1, ||track.sequencer.midi_ins.iter(), + |port, index|Fill::x(Align::w(format!(" {index} {}", port.name()))))))))}) + } + fn view_midi_outs_status (&self, theme: ItemTheme) -> impl Content { + self.track().map(|track|{ + let outs = track.sequencer.midi_outs.len() as u16; + Fixed::xy(20, 1 + outs, Outer(true, Style::default().fg(Tui::g(96))).enclose( + Fixed::xy(20, 1 + outs, FieldV(theme, format!("MIDI outs: "), + Map::south(1, ||track.sequencer.midi_outs.iter(), + |port, index|Fill::x(Align::w(format!(" {index} {}", port.name()))))))))}) + } + fn view_audio_ins_status (&self, theme: ItemTheme) -> impl Content { + self.track().and_then(|track|track.devices.get(0)).map(|device|{ + let ins = device.audio_ins().len() as u16; + Fixed::xy(20, 1 + ins, Outer(true, Style::default().fg(Tui::g(96))).enclose( + Fixed::xy(20, 1 + ins, FieldV(theme, format!("Audio ins: "), + Map::south(1, ||device.audio_ins().iter(), + |port, index|Fill::x(Align::w(format!(" {index} {}", port.name()))))))))}) + } + fn view_audio_outs_status (&self, theme: ItemTheme) -> impl Content { + self.track().and_then(|track|track.devices.last()).map(|device|{ + let outs = device.audio_outs().len() as u16; + Fixed::xy(20, 1 + outs, Outer(true, Style::default().fg(Tui::g(96))).enclose( + Fixed::xy(20, 1 + outs, FieldV(theme, format!("Audio outs: "), + Map::south(1, ||device.audio_outs().iter(), + |port, index|Fill::x(Align::w(format!(" {index} {}", port.name()))))))))}) + } } //impl>> HasTrack for T { @@ -162,14 +197,3 @@ pub trait HasTrack { //self.get_mut().as_mut() //} //} - -impl> + Has> HasTrack for T { - fn track (&self) -> Option<&Track> { - let index = Has::::get(self).track()?; - Has::>::get(self).get(index) - } - fn track_mut (&mut self) -> Option<&mut Track> { - let index = Has::::get(self).track()?; - Has::>::get_mut(self).get_mut(index) - } -} diff --git a/crates/device/src/lib.rs b/crates/device/src/lib.rs index a9f2686e..26131511 100644 --- a/crates/device/src/lib.rs +++ b/crates/device/src/lib.rs @@ -13,7 +13,7 @@ pub(crate) use std::path::PathBuf; pub(crate) use std::error::Error; pub(crate) use std::ffi::OsString; -pub(crate) use ::tengri::{from, Usually, Perhaps, Has}; +pub(crate) use ::tengri::{from, has, maybe_has, Usually, Perhaps, Has, MaybeHas}; pub(crate) use ::tengri::{dsl::*, input::*, output::*, tui::{*, ratatui::prelude::*}}; pub(crate) use ::tek_engine::*; pub(crate) use ::tek_engine::midi::{u7, LiveEvent, MidiMessage}; diff --git a/crates/engine/src/lib.rs b/crates/engine/src/lib.rs index 9acdc1cb..31eb7e92 100644 --- a/crates/engine/src/lib.rs +++ b/crates/engine/src/lib.rs @@ -9,7 +9,7 @@ pub(crate) use std::sync::{Arc, atomic::{AtomicUsize, AtomicBool, Ordering::Rela pub(crate) use std::fmt::Debug; pub(crate) use std::ops::{Add, Sub, Mul, Div, Rem}; -pub(crate) use ::tengri::{from, Usually, Perhaps, Has, tui::*}; +pub(crate) use ::tengri::{from, Usually, Perhaps, Has, has, maybe_has, tui::*}; pub use ::atomic_float; pub(crate) use atomic_float::*; @@ -23,15 +23,6 @@ pub use ::atomic_float; pub(crate) use atomic_float::*; //} //} -#[macro_export] macro_rules! has { - ($T:ty: |$self:ident : $S:ty| $x:expr) => { - impl Has<$T> for $S { - fn get (&$self) -> &$T { &$x } - fn get_mut (&mut $self) -> &mut $T { &mut $x } - } - }; -} - #[macro_export] macro_rules! as_ref { ($T:ty: |$self:ident : $S:ty| $x:expr) => { impl AsRef<$T> for $S {