diff --git a/README.md b/README.md index 65fb7107..1245d348 100644 --- a/README.md +++ b/README.md @@ -25,17 +25,17 @@ or [**matrix** `@unspeaker:matrix.org`](https://matrix.to/#/@unspeaker:matrix.or ## keymaps * Arranger: - * [x] `arrows/wasd`: navigate - * [x] `tab`: enter editor + * [x] arrows: navigate + * [x] tab: enter editor * [x] `q`: enqueue clip * [x] space: play/pause * Editor: - * [x] `arrows/wasd`: navigate + * [x] arrows: navigate * [x] `,` / `.`: change note length - * [x] `enter`: write note + * [x] enter: write note * [x] `-` / `=`: zoom midi editor * [ ] `z`: zoom lock/unlock - * [ ] `del`: delete + * [ ] del: delete * Global: * [x] esc: options menu * [x] f1: help/command list diff --git a/config/config_arranger.edn b/config/config_arranger.edn index 8ff9c181..6ee23998 100644 --- a/config/config_arranger.edn +++ b/config/config_arranger.edn @@ -3,25 +3,25 @@ (info "A session grid.") (view - (bsp/a :modal - (bsp/s (fixed/y 1 :transport) - (bsp/n (fixed/y 1 :status) + (bsp/a :view-dialog + (bsp/s (fixed/y 1 :view-transport) + (bsp/n (fixed/y 1 :view-status) (fill/xy (bsp/a - (fill/xy (align/e :pool)) - :arranger)))))) + (fill/xy (align/e :view-pool)) + :view-arranger)))))) (keys - (layer-if :mode-message "./keys_message.edn") - (layer-if :mode-device-add "./keys_device_add.edn") - (layer-if :mode-pool-import "./keys_pool_file.edn") - (layer-if :mode-pool-export "./keys_pool_file.edn") - (layer-if :mode-pool-rename "./keys_clip_rename.edn") - (layer-if :mode-pool-length "./keys_clip_length.edn") - (layer "./keys_global.edn") - (layer-if :mode-editor "./keys_editor.edn") - (layer-if :mode-clip "./keys_clip.edn") - (layer-if :mode-track "./keys_track.edn") - (layer-if :mode-scene "./keys_scene.edn") - (layer-if :mode-mix "./keys_mix.edn") - (layer "./keys_clock.edn") - (layer "./keys_arranger.edn")) + (layer-if :focus-message "./keys_message.edn") + (layer-if :focus-device-add "./keys_device_add.edn") + (layer-if :focus-pool-import "./keys_pool_file.edn") + (layer-if :focus-pool-export "./keys_pool_file.edn") + (layer-if :focus-pool-rename "./keys_clip_rename.edn") + (layer-if :focus-pool-length "./keys_clip_length.edn") + (layer "./keys_global.edn") + (layer-if :focus-editor "./keys_editor.edn") + (layer-if :focus-clip "./keys_clip.edn") + (layer-if :focus-track "./keys_track.edn") + (layer-if :focus-scene "./keys_scene.edn") + (layer-if :focus-mix "./keys_mix.edn") + (layer "./keys_clock.edn") + (layer "./keys_arranger.edn")) diff --git a/config/config_groovebox.edn b/config/config_groovebox.edn index c3815b89..59bc032a 100644 --- a/config/config_groovebox.edn +++ b/config/config_groovebox.edn @@ -1,22 +1,22 @@ -(name "Arranger") +(name "Groovebox") (info "A sequencer with built-in sampler.") (view - (bsp/a :modal - (bsp/s (fixed/y 1 :transport) - (bsp/n (fixed/y 1 :status) - (bsp/n (fixed/y 5 :sample-viewer) - (bsp/w (fixed/x :w-sidebar :pool) - (bsp/e :samples-keys - (fill/y :editor)))))))) + (bsp/a :view-dialog + (bsp/s (fixed/y 1 :view-transport) + (bsp/n (fixed/y 1 :view-status) + (bsp/n (fixed/y 5 :view-sample-viewer) + (bsp/w (fixed/x :w-sidebar :view-pool) + (bsp/e :view-samples-keys + (fill/y :view-editor)))))))) (keys - (layer-if :mode-pool-import "./keys_pool_file.edn") - (layer-if :mode-pool-export "./keys_pool_file.edn") - (layer-if :mode-pool-rename "./keys_clip_rename.edn") - (layer-if :mode-pool-length "./keys_clip_length.edn") - (layer "./keys_global.edn") - (layer-if :mode-editor "./keys_editor.edn") - (layer "./keys_clock.edn") - (layer "./keys_arranger.edn")) + (layer-if :focus-pool-import "./keys_pool_file.edn") + (layer-if :focus-pool-export "./keys_pool_file.edn") + (layer-if :focus-pool-rename "./keys_clip_rename.edn") + (layer-if :focus-pool-length "./keys_clip_length.edn") + (layer "./keys_global.edn") + (layer "./keys_clock.edn") + (layer "./keys_editor.edn") + (layer "./keys_sampler.edn")) diff --git a/config/config_sampler.edn b/config/config_sampler.edn index 4d8fd6cb..8f6c209a 100644 --- a/config/config_sampler.edn +++ b/config/config_sampler.edn @@ -3,10 +3,10 @@ (info "A sampling soundboard.") (view - (bsp/a :modal - (bsp/s (fixed/y 1 :transport) - (bsp/n (fixed/y 1 :status) - (fill/xy :samples-grid))))) + (bsp/a :view-dialog + (bsp/s (fixed/y 1 :view-transport) + (bsp/n (fixed/y 1 :view-status) + (fill/xy :view-samples-grid))))) (keys (layer "./keys_global.edn") diff --git a/config/config_sequencer.edn b/config/config_sequencer.edn index 1c1b6dfd..5a6d4029 100644 --- a/config/config_sequencer.edn +++ b/config/config_sequencer.edn @@ -3,12 +3,12 @@ (info "A MIDI sequencer.") (view - (bsp/a :modal - (bsp/s (fixed/y 1 :transport) - (bsp/n (fixed/y 1 :status) + (bsp/a :view-dialog + (bsp/s (fixed/y 1 :view-transport) + (bsp/n (fixed/y 1 :view-status) (fill/xy (bsp/a - (fill/xy (align/e :pool)) - :editor))))) + (fill/xy (align/e :view-pool)) + :view-editor))))) (keys (layer-if :mode-pool-import "./keys_pool_file.edn") diff --git a/config/config_transport.edn b/config/config_transport.edn index 00f28567..b84f0279 100644 --- a/config/config_transport.edn +++ b/config/config_transport.edn @@ -2,7 +2,7 @@ (info "A JACK transport controller.") -(view :transport) +(view :view-transport) (keys (layer "./keys_global.edn") diff --git a/config/keys_arranger.edn b/config/keys_arranger.edn index 741062e0..2ab14fb8 100644 --- a/config/keys_arranger.edn +++ b/config/keys_arranger.edn @@ -1,6 +1,6 @@ (@c color) (@q launch) -(@t select :track 0) +(@t select :select-track-header) (@tab edit :clip) (@shift-I input add) (@shift-O output add) @@ -8,11 +8,7 @@ (@shift-T track add) (@shift-Z device picker) -(@up select :scene-prev) -(@w select :scene-prev) -(@down select :scene-next) -(@s select :scene-next) -(@left select :track-prev) -(@a select :track-prev) -(@right select :track-next) -(@d select :track-next) +(@up select :select-scene-prev) +(@down select :select-scene-next) +(@left select :select-track-prev) +(@right select :select-track-next) diff --git a/config/keys_clock.edn b/config/keys_clock.edn index 5a0763be..3f707559 100644 --- a/config/keys_clock.edn +++ b/config/keys_clock.edn @@ -1,2 +1,2 @@ -(@space clock toggle) -(@shift-space clock toggle 0) +(@space clock toggle-playback 0) +(@shift-space clock toggle-playback 0) diff --git a/config/keys_editor.edn b/config/keys_editor.edn index 88245b5c..09c225f6 100644 --- a/config/keys_editor.edn +++ b/config/keys_editor.edn @@ -1,30 +1,25 @@ -(@up editor note/pos :note-pos-next) -(@w editor note/pos :note-pos-next) -(@down editor note/pos :note-pos-prev) -(@s editor note/pos :note-pos-prev) +(@up editor note-pos :note-pos-next) +(@down editor note-pos :note-pos-prev) +(@pgup editor note-pos :note-pos-next-octave) +(@pgdn editor note-pos :note-pos-prev-octave) -(@pgup editor note/pos :note-pos-next-octave) -(@pgdn editor note/pos :note-pos-prev-octave) +(@comma editor note-len :note-len-prev) +(@period editor note-len :note-len-next) +(@lt editor note-len :note-len-prev) +(@gt editor note-len :note-len-next) -(@comma editor note/len :note-len-prev) -(@period editor note/len :note-len-next) -(@lt editor note/len :note-len-prev) -(@gt editor note/len :note-len-next) +(@plus editor note-range :note-range-next) +(@underscore editor note-range :note-range-prev) -(@plus editor note/range :note-range-next) -(@underscore editor note/range :note-range-prev) +(@left editor time-pos :time-pos-prev) +(@right editor time-pos :time-pos-next) -(@left editor time/pos :time-pos-prev) -(@a editor time/pos :time-pos-prev) -(@right editor time/pos :time-pos-next) -(@d editor time/pos :time-pos-next) +(@equal editor time-zoom :time-zoom-prev) +(@minus editor time-zoom :time-zoom-next) -(@equal editor time/zoom :time-zoom-prev) -(@minus editor time/zoom :time-zoom-next) +(@z editor time-lock) -(@z editor time/lock) - -(@enter editor note/put) -(@shift-enter editor note/append) -(@del editor note/del) -(@shift-del editor note/del) +(@enter editor note-put) +(@shift-enter editor note-append) +(@del editor note-del) +(@shift-del editor note-del) diff --git a/config/keys_sampler.edn b/config/keys_sampler.edn index 8bfb03c9..1dd4f2dc 100644 --- a/config/keys_sampler.edn +++ b/config/keys_sampler.edn @@ -1,13 +1,5 @@ (@up sampler select :sample-up) -(@w sampler select :sample-up) - (@down sampler select :sample-down) -(@s sampler select :sample-down) - (@left sampler select :sample-left) -(@a sampler select :sample-left) - (@right sampler select :sample-right) -(@d sampler select :sample-right) - (@r sampler record/toggle :sample) diff --git a/crates/app/examples/midi_import.rs b/crates/app/examples/midi_import.rs index 90b848a1..339bb880 100644 --- a/crates/app/examples/midi_import.rs +++ b/crates/app/examples/midi_import.rs @@ -11,7 +11,10 @@ impl HasClips for ExampleClips { } } fn main () -> Result<(), Box> { - let mut clips = ExampleClips(Arc::new(vec![].into())); - PoolClipCommand::Import(0, std::path::PathBuf::from("./example.mid")).execute(&mut clips)?; + let mut clips = MidiPool::default();//ExampleClips(Arc::new(vec![].into())); + PoolClipCommand::Import { + index: 0, + path: std::path::PathBuf::from("./example.mid") + }.execute(&mut clips)?; Ok(()) } diff --git a/crates/app/src/api.rs b/crates/app/src/api.rs index 8f25f108..408f5555 100644 --- a/crates/app/src/api.rs +++ b/crates/app/src/api.rs @@ -18,6 +18,12 @@ handle!(TuiIn: |self: App, input|Ok(if let Some(command) = self.config.keys.comm })); #[tengri_proc::expose] impl App { + fn _todo_isize_stub (&self) -> isize { + todo!() + } + fn _todo_item_theme_stub (&self) -> ItemTheme { + todo!() + } fn focus_editor (&self) -> bool { self.is_editing() } @@ -113,22 +119,25 @@ handle!(TuiIn: |self: App, input|Ok(if let Some(command) = self.config.keys.comm fn scene_selected (&self) -> Option { self.selected.scene() } - fn scene_select_next (&self) -> Selection { - self.selected.scene_next(self.scenes.len()) - } - fn scene_select_prev (&self) -> Selection { - self.selected.scene_prev() - } fn track_count (&self) -> usize { self.tracks.len() } fn track_selected (&self) -> Option { self.selected.track() } - fn track_select_next (&self) -> Selection { + fn select_scene_next (&self) -> Selection { + self.selected.scene_next(self.scenes.len()) + } + fn select_scene_prev (&self) -> Selection { + self.selected.scene_prev() + } + fn select_track_header (&self) -> Selection { + self.selected.track_header(self.tracks.len()) + } + fn select_track_next (&self) -> Selection { self.selected.track_next(self.tracks.len()) } - fn track_select_prev (&self) -> Selection { + fn select_track_prev (&self) -> Selection { self.selected.track_prev() } fn clip_selected (&self) -> Option>> { @@ -161,6 +170,15 @@ handle!(TuiIn: |self: App, input|Ok(if let Some(command) = self.config.keys.comm } #[tengri_proc::expose] impl MidiPool { + fn _todo_bool_stub (&self) -> bool { + todo!() + } + fn _todo_path_buf_stub (&self) -> PathBuf { + todo!() + } + fn _todo_arc_str_stub (&self) -> Arc { + todo!() + } fn clip_new (&self) -> MidiClip { self.new_clip() } @@ -185,6 +203,9 @@ handle!(TuiIn: |self: App, input|Ok(if let Some(command) = self.config.keys.comm } #[tengri_proc::expose] impl MidiEditor { + fn _todo_opt_clip_stub (&self) -> Option>> { + todo!() + } fn time_lock (&self) -> bool { self.get_time_lock() } @@ -289,6 +310,35 @@ handle!(TuiIn: |self: App, input|Ok(if let Some(command) = self.config.keys.comm None }) } + fn color (app: &mut App, theme: ItemTheme) -> Perhaps { + Ok(app.set_color(Some(theme)).map(|theme|Self::Color{theme})) + } + fn enqueue (app: &mut App, clip: Option>>) -> Perhaps { + todo!() + } + fn history (app: &mut App, delta: isize) -> Perhaps { + todo!() + } + fn zoom (app: &mut App, zoom: usize) -> Perhaps { + todo!() + } + fn launch (app: &mut App) -> Perhaps { + app.launch(); + Ok(None) + } + fn select (app: &mut App, selection: Selection) -> Perhaps { + app.select(selection); + Ok(None) + //("select" [t: usize, s: usize] Some(match (t.expect("no track"), s.expect("no scene")) { + //(0, 0) => Self::Select(Selection::Mix), + //(t, 0) => Self::Select(Selection::Track(t)), + //(0, s) => Self::Select(Selection::Scene(s)), + //(t, s) => Self::Select(Selection::TrackClip { track: t, scene: s }) }))) + } + fn stop_all (app: &mut App) -> Perhaps { + app.stop_all(); + Ok(None) + } fn sampler (app: &mut App, command: SamplerCommand) -> Perhaps { Ok(app.sampler_mut() .map(|s|command.delegate(s, |command|Self::Sampler{command})) @@ -319,34 +369,29 @@ handle!(TuiIn: |self: App, input|Ok(if let Some(command) = self.config.keys.comm fn message (app: &mut App, command: MessageCommand) -> Perhaps { Ok(command.delegate(app, |command|Self::Message{command})?) } - fn color (app: &mut App, theme: ItemTheme) -> Perhaps { - Ok(app.set_color(Some(theme)).map(|theme|Self::Color{theme})) +} + +impl<'state> Context<'state, ClockCommand> for App { + fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option { + Context::get(&self.clock, iter) } - fn enqueue (app: &mut App, clip: Option>>) -> Perhaps { - todo!() +} + +impl<'state> Context<'state, MidiEditCommand> for App { + fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option { + self.editor().map(|e|Context::get(e, iter)).flatten() } - fn history (app: &mut App, delta: isize) -> Perhaps { - todo!() +} + +impl<'state> Context<'state, PoolCommand> for App { + fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option { + self.pool().map(|p|Context::get(p, iter)).flatten() } - fn zoom (app: &mut App, zoom: usize) -> Perhaps { - todo!() - } - fn launch (app: &mut App) -> Perhaps { - app.launch(); - Ok(None) - } - fn select (app: &mut App, selection: Selection) -> Perhaps { - app.select(selection); - Ok(None) - //("select" [t: usize, s: usize] Some(match (t.expect("no track"), s.expect("no scene")) { - //(0, 0) => Self::Select(Selection::Mix), - //(t, 0) => Self::Select(Selection::Track(t)), - //(0, s) => Self::Select(Selection::Scene(s)), - //(t, s) => Self::Select(Selection::TrackClip { track: t, scene: s }) }))) - } - fn stop_all (app: &mut App) -> Perhaps { - app.stop_all(); - Ok(None) +} + +impl<'state> Context<'state, SamplerCommand> for App { + fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option { + self.sampler().map(|p|Context::get(p, iter)).flatten() } } diff --git a/crates/app/src/config.rs b/crates/app/src/config.rs index fc996811..10a84445 100644 --- a/crates/app/src/config.rs +++ b/crates/app/src/config.rs @@ -122,8 +122,7 @@ impl Configuration { return Err(format!("(e4) unexpected non-symbol {next:?}").into()) }; - let next = exp.next(); - if let Some(Token { value: Value::Str(path), .. }) = next { + if let Some(Token { value: Value::Str(path), .. }) = exp.peek() { let path = base.as_ref().parent().unwrap().join(unquote(path)); if !std::fs::exists(&path)? { return Err(format!("(e5) not found: {path:?}").into()) @@ -133,8 +132,9 @@ impl Configuration { println!("ok"); let cond = cond.unwrap(); map.add_layer_if( - Box::new(|state|{ - Context::get(state, &Value::Sym(cond)).unwrap_or(false) + Box::new(move |state|{ + let mut exp = exp.clone(); + Context::get(state, &mut exp).unwrap_or(false) }), keys ); diff --git a/crates/app/src/lib.rs b/crates/app/src/lib.rs index c83d835b..f1d59d7f 100644 --- a/crates/app/src/lib.rs +++ b/crates/app/src/lib.rs @@ -42,33 +42,29 @@ mod config; pub use self::config::*; mod model; pub use self::model::*; mod view; pub use self::view::*; -#[cfg(test)] #[test] fn test_model () { +#[cfg(test)] #[test] fn test_model () -> Usually<()> { let mut app = App::default(); let _ = app.clip(); let _ = app.toggle_loop(); -} - -#[cfg(test)] #[test] fn test_model_scene () { - let mut app = App::default(); + //let _ = app.tracks_add(8, None, &[], &[])?; + //let _ = app.track_add_focus()?; let _ = app.scene_longest(); let _ = app.scene(); let _ = app.scene_mut(); - let _ = app.scene_add(None, None); - app.scene_del(0); + let _ = app.scene_add(None, None)?; + let _ = app.scene_add_focus()?; + let scene = app.scene_del(0); let scene = Scene::default(); let _ = scene.pulses(); let _ = scene.is_playing(&[]); -} - -#[cfg(test)] #[test] fn test_view_clock () { - let _ = button_play_pause(true); - let mut app = App::default(); let _ = app.view_transport(); let _ = app.view_status(); let _ = app.update_clock(); + Ok(()) } #[cfg(test)] #[test] fn test_view_layout () { + let _ = button_play_pause(true); let _ = button_2("", "", true); let _ = button_2("", "", false); let _ = button_3("", "", "", true); @@ -122,3 +118,29 @@ mod view; pub use self::view::*; let _ = app.h_outputs(); let _ = app.h_scenes(); } + +#[cfg(test)] #[test] fn test_midi_edit () { + let editor = MidiEditor::default(); + let mut editor = MidiEditor { + mode: PianoHorizontal::new(Some(&Arc::new(RwLock::new(MidiClip::stop_all())))), + size: Default::default(), + //keys: Default::default(), + }; + let _ = editor.put_note(true); + let _ = editor.put_note(false); + let _ = editor.clip_status(); + let _ = editor.edit_status(); + struct TestEditorHost(Option); + has_editor!(|self: TestEditorHost|{ + editor = self.0; + editor_w = 0; + editor_h = 0; + is_editing = false; + }); + let mut host = TestEditorHost(Some(editor)); + let _ = host.editor(); + let _ = host.editor_mut(); + let _ = host.is_editing(); + let _ = host.editor_w(); + let _ = host.editor_h(); +} diff --git a/crates/app/src/model/scene.rs b/crates/app/src/model/scene.rs index 5159eeb0..353133ac 100644 --- a/crates/app/src/model/scene.rs +++ b/crates/app/src/model/scene.rs @@ -46,13 +46,16 @@ pub trait HasScenes: HasSelection + HasEditor + Send + Sync { 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)) + 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)) + 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))); + fn scene_del (&mut self, index: usize) -> Option { + self.selected().scene() + .and_then(|s|Some(self.scenes_mut().remove(index))) } /// Set the color of a scene, returning the previous one. fn scene_set_color (&mut self, index: usize, color: ItemTheme) -> ItemTheme { diff --git a/crates/app/src/model/selection.rs b/crates/app/src/model/selection.rs index 82d588cc..d4560a94 100644 --- a/crates/app/src/model/selection.rs +++ b/crates/app/src/model/selection.rs @@ -53,6 +53,16 @@ impl Selection { _ => None } } + pub fn track_header (&self, track_count: usize) -> Self { + use Selection::*; + match self { + Mix => Track(0), + Scene(_) => Mix, + Track(t) => Track((t + 1) % track_count), + TrackClip { track, .. } => Track(*track), + _ => todo!(), + } + } pub fn track_next (&self, len: usize) -> Self { use Selection::*; match self { diff --git a/crates/app/src/view.rs b/crates/app/src/view.rs index 22bf3d02..271c8251 100644 --- a/crates/app/src/view.rs +++ b/crates/app/src/view.rs @@ -4,10 +4,10 @@ pub(crate) use ::tengri::tui::ratatui::prelude::Position; #[tengri_proc::view(TuiOut)] impl App { - fn view_nil (&self) -> impl Content + use<'_> { + pub fn view_nil (&self) -> impl Content + use<'_> { "nil" } - fn view_status (&self) -> impl Content + use<'_> { + pub fn view_status (&self) -> impl Content + use<'_> { self.update_clock(); let cache = self.view_cache.read().unwrap(); view_status( @@ -15,7 +15,7 @@ impl App { cache.sr.view.clone(), cache.buf.view.clone(), cache.lat.view.clone(), ) } - fn view_transport (&self) -> impl Content + use<'_> { + pub fn view_transport (&self) -> impl Content + use<'_> { self.update_clock(); let cache = self.view_cache.read().unwrap(); view_transport( @@ -23,25 +23,25 @@ impl App { cache.bpm.view.clone(), cache.beat.view.clone(), cache.time.view.clone(), ) } - fn view_arranger (&self) -> impl Content + use<'_> { + pub fn view_arranger (&self) -> impl Content + use<'_> { ArrangerView::new(self) } - fn view_pool (&self) -> impl Content + use<'_> { + pub fn view_pool (&self) -> impl Content + use<'_> { self.pool().map(|p|Fixed::x(self.w_sidebar(), PoolView(self.is_editing(), p))) } - fn view_editor (&self) -> impl Content + use<'_> { + pub fn view_editor (&self) -> impl Content + use<'_> { self.editor().map(|e|Bsp::n(Bsp::e(e.clip_status(), e.edit_status()), e)) } - fn view_samples_keys (&self) -> impl Content + use<'_> { + pub fn view_samples_keys (&self) -> impl Content + use<'_> { self.sampler().map(|s|s.view_list(false, self.editor().unwrap())) } - fn view_samples_grid (&self) -> impl Content + use<'_> { + pub fn view_samples_grid (&self) -> impl Content + use<'_> { self.sampler().map(|s|s.view_grid()) } - fn view_sample_viewer (&self) -> impl Content + use<'_> { + pub fn view_sample_viewer (&self) -> impl Content + use<'_> { self.sampler().map(|s|s.view_sample(self.editor().unwrap().get_note_pos())) } - fn view_dialog (&self) -> impl Content + use<'_> { + pub fn view_dialog (&self) -> impl Content + use<'_> { When::new(self.dialog.is_some(), Bsp::b( Fill::xy(Tui::fg_bg(Rgb(64,64,64), Rgb(32,32,32), "")), Fixed::xy(30, 15, Tui::fg_bg(Rgb(255,255,255), Rgb(16,16,16), Bsp::b( diff --git a/crates/device/src/clock/clock_api.rs b/crates/device/src/clock/clock_api.rs index e9161ec4..e8544525 100644 --- a/crates/device/src/clock/clock_api.rs +++ b/crates/device/src/clock/clock_api.rs @@ -29,11 +29,11 @@ impl ClockCommand { state.pause_at(position)?; Ok(None) } - fn toggle_playback (state: &mut Clock, position: Option) -> Perhaps { + fn toggle_playback (state: &mut Clock, position: u32) -> Perhaps { if state.is_rolling() { - state.pause_at(position)?; + state.pause_at(Some(position))?; } else { - state.play_from(position)?; + state.play_from(Some(position))?; } Ok(None) } diff --git a/crates/device/src/lv2.rs b/crates/device/src/lv2.rs index 47429b87..b1f0b505 100644 --- a/crates/device/src/lv2.rs +++ b/crates/device/src/lv2.rs @@ -2,15 +2,4 @@ mod lv2_model; pub use self::lv2_model::*; mod lv2_audio; pub use self::lv2_audio::*; mod lv2_gui; pub use self::lv2_gui::*; mod lv2_tui; pub use self::lv2_tui::*; - pub(self) use std::thread::JoinHandle; - -pub(self) use ::livi::{ - World, - Instance, - Plugin as LiviPlugin, - Features, - FeaturesBuilder, - Port as LiviPort, - event::LV2AtomSequence, -}; diff --git a/crates/device/src/sequencer.rs b/crates/device/src/sequencer.rs index 8bccc2eb..ba8ab65e 100644 --- a/crates/device/src/sequencer.rs +++ b/crates/device/src/sequencer.rs @@ -13,7 +13,7 @@ mod seq_view; pub use self::seq_view::*; let mut clip = MidiClip::new("clip", true, 1, None, None); clip.set_length(96); clip.toggle_loop(); - clip.record_event(12, midly::MidiMessage::NoteOn { key: 36.into(), vel: 100.into() }); + clip.record_event(12, MidiMessage::NoteOn { key: 36.into(), vel: 100.into() }); assert!(clip.contains_note_on(36.into(), 6, 18)); assert_eq!(&clip.notes, &clip.duplicate().notes); @@ -25,29 +25,3 @@ mod seq_view; pub use self::seq_view::*; let player = MidiPlayer::default(); println!("{player:?}"); } - -#[cfg(test)] #[test] fn test_midi_edit () { - let editor = MidiEditor::default(); - let mut editor = MidiEditor { - mode: PianoHorizontal::new(Some(&Arc::new(RwLock::new(MidiClip::stop_all())))), - size: Default::default(), - keys: Default::default(), - }; - let _ = editor.put_note(true); - let _ = editor.put_note(false); - let _ = editor.clip_status(); - let _ = editor.edit_status(); - struct TestEditorHost(Option); - has_editor!(|self: TestEditorHost|{ - editor = self.0; - editor_w = 0; - editor_h = 0; - is_editing = false; - }); - let mut host = TestEditorHost(Some(editor)); - let _ = host.editor(); - let _ = host.editor_mut(); - let _ = host.is_editing(); - let _ = host.editor_w(); - let _ = host.editor_h(); -} diff --git a/crates/engine/src/jack/jack_client.rs b/crates/engine/src/jack/jack_client.rs index 5adb9a3e..b1200529 100644 --- a/crates/engine/src/jack/jack_client.rs +++ b/crates/engine/src/jack/jack_client.rs @@ -85,7 +85,11 @@ impl Jack { // implements audio and MIDI input and output on a realtime basis. ClosureProcessHandler::new(Box::new({ let app = app.clone(); - move|c: &_, s: &_|app.write().unwrap().process(c, s) + move|c: &_, s: &_|if let Ok(mut app) = app.write() { + app.process(c, s) + } else { + Control::Quit + } }) as BoxedAudioHandler<'j>), )?; *self.state.write().unwrap() = Active(client); diff --git a/crates/engine/src/lib.rs b/crates/engine/src/lib.rs index b4840a09..860178fc 100644 --- a/crates/engine/src/lib.rs +++ b/crates/engine/src/lib.rs @@ -5,8 +5,7 @@ mod note; pub use self::note::*; pub mod jack; pub use self::jack::*; pub mod midi; pub use self::midi::*; -pub(crate) use std::sync::{Arc, RwLock, atomic::{AtomicUsize, AtomicBool, Ordering::Relaxed}}; -pub(crate) use std::path::PathBuf; +pub(crate) use std::sync::{Arc, atomic::{AtomicUsize, AtomicBool, Ordering::Relaxed}}; pub(crate) use std::fmt::Debug; pub(crate) use std::ops::{Add, Sub, Mul, Div, Rem}; @@ -59,14 +58,14 @@ impl InteriorMutable for AtomicUsize { #[cfg(test)] #[test] fn test_midi_range () { let model = MidiRangeModel::from((1, false)); - let _ = model.time_len(); - let _ = model.time_zoom(); - let _ = model.time_lock(); - let _ = model.time_start(); - let _ = model.time_axis(); - let _ = model.time_end(); + let _ = model.get_time_len(); + let _ = model.get_time_zoom(); + let _ = model.get_time_lock(); + let _ = model.get_time_start(); + let _ = model.get_time_axis(); + let _ = model.get_time_end(); - let _ = model.note_lo(); - let _ = model.note_axis(); - let _ = model.note_hi(); + let _ = model.get_note_lo(); + let _ = model.get_note_axis(); + let _ = model.get_note_hi(); } diff --git a/deps/tengri b/deps/tengri index 22d63eed..cb8fd269 160000 --- a/deps/tengri +++ b/deps/tengri @@ -1 +1 @@ -Subproject commit 22d63eed9c9cb5bed5016d851f90773e0f60280d +Subproject commit cb8fd26922fd1cfad4ceadeb89e48544531a178e