diff --git a/config/config_groovebox.edn b/config/config_groovebox.edn index d6d72f4d..7afce303 100644 --- a/config/config_groovebox.edn +++ b/config/config_groovebox.edn @@ -3,16 +3,16 @@ (info "A sequencer with built-in sampler.") (view - (bsp/a :view-dialog - (bsp/s (fixed/y 1 :view-transport) - (bsp/n (fixed/y 1 :view-status) - (bsp/w :view-meters-output - (bsp/e :view-meters-input - (bsp/n :view-sample-info - (bsp/n (fixed/y 5 :view-sample-viewer) - (bsp/w :view-pool - (bsp/e :view-samples-keys - (fill/y :view-editor))))))))))) + (bsp/a :view-dialog + (bsp/s (fixed/y 1 :view-transport) + (bsp/n (fixed/y 1 :view-status) + (bsp/w :view-meters-output + (bsp/e :view-meters-input + (bsp/n :view-sample-info + (bsp/n (fixed/y 5 :view-sample-viewer) + (bsp/w :view-pool + (bsp/e :view-samples-keys + (fill/y :view-editor))))))))))) (keys (layer-if :focus-browser "./keys_browser.edn") diff --git a/config/keys_global.edn b/config/keys_global.edn index af89f616..8e9f4233 100644 --- a/config/keys_global.edn +++ b/config/keys_global.edn @@ -1,9 +1,9 @@ -(@esc cancel-dialog) -(@f1 toggle-dialog :dialog-help) -(@f6 toggle-dialog :dialog-save) -(@f8 toggle-dialog :dialog-options) -(@f9 toggle-dialog :dialog-load) -(@f10 toggle-dialog :dialog-quit) +(@esc dialog :dialog-none) +(@f1 dialog :dialog-help) +(@f6 dialog :dialog-save) +(@f8 dialog :dialog-options) +(@f9 dialog :dialog-load) +(@f10 dialog :dialog-quit) (@u undo 1) (@r redo 1) diff --git a/crates/app/src/api.rs b/crates/app/src/api.rs index 90b086a0..6b04fe75 100644 --- a/crates/app/src/api.rs +++ b/crates/app/src/api.rs @@ -18,8 +18,8 @@ handle!(TuiIn: |self: App, input|Ok(if let Some(command) = self.config.keys.comm })); #[tengri_proc::command(App)] impl AppCommand { - fn toggle_dialog (app: &mut App, dialog: Dialog) -> Perhaps { - app.toggle_dialog(Some(dialog)); + fn dialog (app: &mut App, dialog: Option) -> Perhaps { + app.toggle_dialog(dialog); Ok(None) } fn cancel_dialog (app: &mut App) -> Perhaps { diff --git a/crates/app/src/lib.rs b/crates/app/src/lib.rs index f1d59d7f..602ce67a 100644 --- a/crates/app/src/lib.rs +++ b/crates/app/src/lib.rs @@ -16,12 +16,9 @@ #![feature(type_changing_struct_update)] #![feature(let_chains)] #![feature(closure_lifetime_binder)] -/// Standard result type. -pub type Usually = std::result::Result>; -/// Standard optional result type. -pub type Perhaps = std::result::Result, Box>; pub use ::tek_engine:: *; pub use ::tek_device::{self, *}; +pub use ::tengri::{Usually, Perhaps, 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 8c39ba87..5a459295 100644 --- a/crates/app/src/model.rs +++ b/crates/app/src/model.rs @@ -35,8 +35,8 @@ has!(Vec: |self: App|self.project.midi_ins); 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); -has_size!(|self: App|&self.size); has_clips!(|self: App|self.project.pool.clips); has_editor!(|self: App|{ editor = self.editor; @@ -152,8 +152,8 @@ impl App { /// Various possible dialog overlays #[derive(Clone, Debug)] pub enum Dialog { - Help, - Menu, + Help(usize), + Menu(usize), Device(usize), Message(Message), Save(Browser), @@ -216,29 +216,32 @@ impl App { fn focus_pool_length (&self) -> bool { matches!(self.project.pool.mode, Some(PoolMode::Length(..))) } - fn dialog_device (&self) -> Dialog { - Dialog::Device(0) // TODO + fn dialog_none (&self) -> Option { + None } - fn dialog_device_prev (&self) -> Dialog { - Dialog::Device(0) // TODO + fn dialog_device (&self) -> Option { + Some(Dialog::Device(0)) // TODO } - fn dialog_device_next (&self) -> Dialog { - Dialog::Device(0) // TODO + fn dialog_device_prev (&self) -> Option { + Some(Dialog::Device(0)) // TODO } - fn dialog_help (&self) -> Dialog { - Dialog::Help + fn dialog_device_next (&self) -> Option { + Some(Dialog::Device(0)) // TODO } - fn dialog_menu (&self) -> Dialog { - Dialog::Menu + fn dialog_help (&self) -> Option { + Some(Dialog::Help(0)) } - fn dialog_save (&self) -> Dialog { - Dialog::Save(Default::default()) + fn dialog_menu (&self) -> Option { + Some(Dialog::Menu(0)) } - fn dialog_load (&self) -> Dialog { - Dialog::Load(Default::default()) + fn dialog_save (&self) -> Option { + Some(Dialog::Save(Default::default())) } - fn dialog_options (&self) -> Dialog { - Dialog::Options + fn dialog_load (&self) -> Option { + Some(Dialog::Load(Default::default())) + } + fn dialog_options (&self) -> Option { + Some(Dialog::Options) } fn editor_pitch (&self) -> Option { Some((self.editor().as_ref().map(|e|e.get_note_pos()).unwrap() as u8).into()) diff --git a/crates/app/src/view.rs b/crates/app/src/view.rs index 2d682638..3ffbd439 100644 --- a/crates/app/src/view.rs +++ b/crates/app/src/view.rs @@ -58,10 +58,10 @@ impl App { Fixed::xy(70, 23, Tui::fg_bg(Rgb(255,255,255), Rgb(16,16,16), Bsp::b( Repeat(" "), Outer(true, Style::default().fg(Tui::g(96))) .enclose(self.dialog.as_ref().map(|dialog|match dialog { - Dialog::Menu => + Dialog::Menu(_) => self.view_dialog_menu().boxed(), - Dialog::Help => - self.view_dialog_help().boxed(), + Dialog::Help(offset) => + self.view_dialog_help(*offset).boxed(), Dialog::Save(browser) => self.view_dialog_save().boxed(), Dialog::Load(browser) => @@ -84,12 +84,13 @@ impl App { let option = |a,i|Tui::fg(Rgb(255,255,255), format!("{}", a)); Bsp::s(Tui::bold(true, "tek!"), Bsp::s("", Map::south(1, options, option))) } - pub fn view_dialog_help <'a> (&'a self) -> impl Content + use<'a> { + pub fn view_dialog_help <'a> (&'a self, offset: usize) -> impl Content + use<'a> { Bsp::s(Tui::bold(true, "Help"), Bsp::s("", Map::south(1, - ||self.config.keys.layers.iter() + move||self.config.keys.layers.iter() .filter_map(|a|(a.0)(self).then_some(a.1)) .flat_map(|a|a) .filter_map(|x|if let Value::Exp(_, iter)=x.value{ Some(iter) } else { None }) + .skip(offset) .take(20), |mut b,i|Fixed::x(60, Align::w(Bsp::e("(", Bsp::e( b.next().map(|t|Fixed::x(16, Align::w(Tui::fg(Rgb(64,224,0), format!("{}", t.value))))), diff --git a/crates/device/src/arranger/arranger_model.rs b/crates/device/src/arranger/arranger_model.rs index 4e3113c4..46687ab1 100644 --- a/crates/device/src/arranger/arranger_model.rs +++ b/crates/device/src/arranger/arranger_model.rs @@ -46,6 +46,7 @@ has!(Vec: |self: Arrangement|self.midi_ins); 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); impl Arrangement { /// Width of display diff --git a/crates/device/src/arranger/arranger_port.rs b/crates/device/src/arranger/arranger_port.rs index c98b0807..152edc73 100644 --- a/crates/device/src/arranger/arranger_port.rs +++ b/crates/device/src/arranger/arranger_port.rs @@ -18,7 +18,7 @@ impl<'a> ArrangerView<'a> { pub(crate) fn input_ports (&'a self) -> impl Content + 'a { Tryptich::top(1) .left(self.width_side, - button_3("i", "midi ins", format!("{}", self.inputs_count), self.is_editing)) + button_3("i", "midi ins", format!("{}", self.arrangement.midi_ins().len()), self.is_editing)) .right(self.width_side, button_2("I", "add midi in", self.is_editing)) .middle(self.width_mid, @@ -96,7 +96,12 @@ impl<'a> ArrangerView<'a> { } pub(crate) fn output_count (&'a self) -> impl Content + 'a { - button_3("o", "midi outs", format!("{}", self.outputs_count), self.is_editing) + button_3( + "o", + "midi outs", + format!("{}", self.arrangement.midi_outs().len()), + self.is_editing + ) } pub(crate) fn output_add (&'a self) -> impl Content + 'a { diff --git a/crates/device/src/arranger/arranger_view.rs b/crates/device/src/arranger/arranger_view.rs index 7e5edc22..a903d26f 100644 --- a/crates/device/src/arranger/arranger_view.rs +++ b/crates/device/src/arranger/arranger_view.rs @@ -9,20 +9,15 @@ pub struct ArrangerView<'a> { pub width_mid: u16, pub width_side: u16, - pub inputs_count: usize, pub inputs_height: u16, - - pub outputs_count: usize, pub outputs_height: u16, pub scene_last: usize, - pub scene_count: usize, pub scene_scroll: Fill>, pub scene_selected: Option, pub scenes_height: u16, pub track_scroll: Fill>, - pub track_count: usize, pub track_selected: Option, pub tracks_height: u16, @@ -47,14 +42,10 @@ impl<'a> ArrangerView<'a> { width_side: arrangement.w_sidebar(is_editing), inputs_height: arrangement.h_inputs(), - inputs_count: arrangement.midi_ins.len(), - outputs_height: arrangement.h_outputs(), - outputs_count: arrangement.midi_outs.len(), scenes_height: h_scenes_area, scene_selected: arrangement.selection().scene(), - scene_count: arrangement.scenes.len(), scene_last: arrangement.scenes.len().saturating_sub(1), scene_scroll: Fill::y(Fixed::x(1, ScrollbarV { offset: arrangement.scene_scroll, @@ -63,7 +54,6 @@ impl<'a> ArrangerView<'a> { })), tracks_height: h_tracks_area, - track_count: arrangement.tracks.len(), track_selected: arrangement.selection().track(), track_scroll: Fill::x(Fixed::y(1, ScrollbarH { offset: arrangement.track_scroll, @@ -108,9 +98,9 @@ impl<'a> ArrangerView<'a> { /// Render track headers pub(crate) fn tracks (&'a self) -> impl Content + 'a { - let Self { width_side, width_mid, track_count, track_selected, is_editing, .. } = self; + let Self { width_side, width_mid, track_selected, is_editing, .. } = self; Tryptich::center(3) - .left(*width_side, button_3("t", "track", format!("{}", *track_count), *is_editing)) + .left(*width_side, button_3("t", "track", format!("{}", self.arrangement.tracks.len()), *is_editing)) .right(*width_side, button_2("T", "add track", *is_editing)) .middle(*width_mid, per_track(*width_mid, ||self.tracks_with_sizes_scrolled(), |index, track|wrap( @@ -126,7 +116,7 @@ impl<'a> ArrangerView<'a> { /// Render device switches. pub(crate) fn devices (&'a self) -> impl Content + 'a { - let Self { width_side, width_mid, track_count, track_selected, is_editing, .. } = self; + let Self { width_side, width_mid, track_selected, is_editing, .. } = self; Tryptich::top(1) .left(*width_side, button_3("d", "devices", format!("{}", 0), *is_editing)) .right(*width_side, button_2("D", "add device", *is_editing)) diff --git a/crates/device/src/editor/editor_model.rs b/crates/device/src/editor/editor_model.rs index 9d8d31f6..c0444a9b 100644 --- a/crates/device/src/editor/editor_model.rs +++ b/crates/device/src/editor/editor_model.rs @@ -8,6 +8,8 @@ pub struct MidiEditor { pub mode: PianoHorizontal, } +has!(Measure: |self: MidiEditor|self.size); + impl std::fmt::Debug for MidiEditor { fn fmt (&self, f: &mut Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { f.debug_struct("MidiEditor") diff --git a/crates/device/src/editor/editor_view.rs b/crates/device/src/editor/editor_view.rs index 7828d416..c91de260 100644 --- a/crates/device/src/editor/editor_view.rs +++ b/crates/device/src/editor/editor_view.rs @@ -1,7 +1,5 @@ use crate::*; -has_size!(|self: MidiEditor|&self.size); - content!(TuiOut: |self: MidiEditor| { self.autoscroll(); //self.autozoom(); diff --git a/crates/device/src/editor/editor_view_h.rs b/crates/device/src/editor/editor_view_h.rs index b9bf650b..35f430bd 100644 --- a/crates/device/src/editor/editor_view_h.rs +++ b/crates/device/src/editor/editor_view_h.rs @@ -18,6 +18,8 @@ pub struct PianoHorizontal { pub keys_width: u16, } +has!(Measure:|self:PianoHorizontal|self.size); + impl PianoHorizontal { pub fn new (clip: Option<&Arc>>) -> Self { let size = Measure::new(); @@ -227,8 +229,6 @@ impl PianoHorizontal { } } -has_size!(|self:PianoHorizontal|&self.size); - impl TimeRange for PianoHorizontal { fn time_len (&self) -> &AtomicUsize { self.range.time_len() } fn time_zoom (&self) -> &AtomicUsize { self.range.time_zoom() } diff --git a/crates/device/src/lib.rs b/crates/device/src/lib.rs index 7c2a0c01..5079ccd0 100644 --- a/crates/device/src/lib.rs +++ b/crates/device/src/lib.rs @@ -12,7 +12,8 @@ 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, dsl::*, input::*, output::*, tui::{*, ratatui::prelude::*}}; +pub(crate) use ::tengri::{from, Usually, Perhaps, Has}; +pub(crate) use ::tengri::{dsl::*, input::*, output::*, tui::{*, ratatui::prelude::*}}; pub(crate) use ::tek_engine::*; pub(crate) use ::tek_engine::midi::{u7, LiveEvent, MidiMessage}; pub(crate) use ::tek_engine::jack::{Control, ProcessScope, MidiWriter, RawMidi}; diff --git a/crates/engine/src/lib.rs b/crates/engine/src/lib.rs index 8f891e4c..9acdc1cb 100644 --- a/crates/engine/src/lib.rs +++ b/crates/engine/src/lib.rs @@ -9,24 +9,19 @@ 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, tui::*}; +pub(crate) use ::tengri::{from, Usually, Perhaps, Has, tui::*}; pub use ::atomic_float; pub(crate) use atomic_float::*; -pub trait Has: Send + Sync { - fn get (&self) -> &T; - fn get_mut (&mut self) -> &mut T; -} +//pub trait MaybeHas: Send + Sync { + //fn get (&self) -> Option<&T>; +//} -pub trait MaybeHas: Send + Sync { - fn get (&self) -> Option<&T>; -} - -impl>> MaybeHas for U { - fn get (&self) -> Option<&T> { - Has::>::get(self).as_ref() - } -} +//impl>> MaybeHas for U { + //fn get (&self) -> Option<&T> { + //Has::>::get(self).as_ref() + //} +//} #[macro_export] macro_rules! has { ($T:ty: |$self:ident : $S:ty| $x:expr) => { diff --git a/deps/tengri b/deps/tengri index a9619ab9..8bfd1a23 160000 --- a/deps/tengri +++ b/deps/tengri @@ -1 +1 @@ -Subproject commit a9619ab9cea40aed3ec30483f4a7db03ca7fec9d +Subproject commit 8bfd1a23a1f880a1d2fb104a158fc51f244acd6e