diff --git a/config/config_arranger.edn b/config/config_arranger.edn index 51932ec3..0a8b2b6d 100644 --- a/config/config_arranger.edn +++ b/config/config_arranger.edn @@ -2,14 +2,6 @@ (info "A session grid.") -(view - (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 :view-pool)) - :view-arranger)))))) - (keys (layer-if :focus-message "./keys_message.edn") (layer-if :focus-device-add "./keys_device_add.edn") @@ -24,3 +16,11 @@ (layer "./keys_clock.edn") (layer "./keys_arranger.edn") (layer "./keys_global.edn")) + +(view + (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 :view-pool)) + :view-arranger)))))) diff --git a/config/config_groovebox.edn b/config/config_groovebox.edn index ce8495fe..318f1d16 100644 --- a/config/config_groovebox.edn +++ b/config/config_groovebox.edn @@ -11,10 +11,8 @@ (layer "./keys_sampler.edn") (layer "./keys_global.edn")) -(view (bsp/a :view-dialog - (bsp/w :view-meters-output (bsp/e :view-meters-input - (bsp/n (fixed/y 6 (bsp/e :view-sample-status :view-sample-viewer)) - (bsp/e - (fill/y (align/n (bsp/s :view-status-v (bsp/s :view-ports-status - (bsp/s :view-editor-status :view-pool))))) - (bsp/e :view-samples-keys :view-editor))))))) +(view (bsp/a :view-dialog (bsp/w :view-meters-output (bsp/e :view-meters-input + (bsp/n (fixed/y 6 (bsp/e :view-sample-status :view-sample-viewer)) + (bsp/e + (fill/y (align/n (bsp/s :view-status-v (bsp/s :view-ports-status (bsp/s :view-editor-status :view-pool))))) + (bsp/e :view-samples-keys :view-editor))))))) diff --git a/config/config_sampler.edn b/config/config_sampler.edn index c2486385..2739e312 100644 --- a/config/config_sampler.edn +++ b/config/config_sampler.edn @@ -2,12 +2,12 @@ (info "A sampling soundboard.") +(keys + (layer "./keys_sampler.edn") + (layer "./keys_global.edn")) + (view (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_sampler.edn") - (layer "./keys_global.edn")) diff --git a/config/config_sequencer.edn b/config/config_sequencer.edn index a267cebd..868bc0ba 100644 --- a/config/config_sequencer.edn +++ b/config/config_sequencer.edn @@ -2,14 +2,6 @@ (info "A MIDI sequencer.") -(view - (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 :view-pool)) - :view-editor))))) - (keys (layer-if :focus-browser "./keys_browser.edn") (layer-if :mode-pool-rename "./keys_rename.edn") @@ -17,3 +9,11 @@ (layer "./keys_editor.edn") (layer "./keys_clock.edn") (layer "./keys_global.edn")) + +(view + (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 :view-pool)) + :view-editor))))) diff --git a/config/config_transport.edn b/config/config_transport.edn index 47324e7b..23ca4f6e 100644 --- a/config/config_transport.edn +++ b/config/config_transport.edn @@ -2,8 +2,8 @@ (info "A JACK transport controller.") -(view :view-transport) - (keys (layer "./keys_clock.edn") (layer "./keys_global.edn")) + +(view :view-transport) diff --git a/config/keys_global.edn b/config/keys_global.edn index 8e9f4233..6ea6d748 100644 --- a/config/keys_global.edn +++ b/config/keys_global.edn @@ -1,9 +1,9 @@ -(@esc dialog :dialog-none) -(@f1 dialog :dialog-help) -(@f6 dialog :dialog-save) -(@f8 dialog :dialog-options) -(@f9 dialog :dialog-load) -(@f10 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/config/keys_sampler.edn b/config/keys_sampler.edn index 0e8aa127..bb4b5b57 100644 --- a/config/keys_sampler.edn +++ b/config/keys_sampler.edn @@ -2,7 +2,11 @@ (@down sampler select :sample-below) (@left sampler select :sample-to-left) (@right sampler select :sample-to-right) + (@r sampler record-toggle :sample-selected) (@shift-R sampler record-cancel) (@p sampler play-sample :sample-selected) (@P sampler stop-sample :sample-selected) + +(@shift-f6 dialog :dialog-import-sample) +(@shift-f9 dialog :dialog-export-sample) diff --git a/crates/app/src/model.rs b/crates/app/src/model.rs index 5a459295..148a7142 100644 --- a/crates/app/src/model.rs +++ b/crates/app/src/model.rs @@ -67,7 +67,7 @@ impl App { } pub fn browser (&self) -> Option<&Browser> { self.dialog.as_ref().and_then(|dialog|match dialog { - Dialog::Save(b) | Dialog::Load(b) => Some(b), + Dialog::Browser(_, b) => Some(b), _ => None }) } @@ -156,11 +156,20 @@ pub enum Dialog { Menu(usize), Device(usize), Message(Message), - Save(Browser), - Load(Browser), + Browser(BrowserTarget, Browser), Options, } +#[derive(Clone, Debug)] +pub enum BrowserTarget { + SaveProject, + LoadProject, + ImportSample(Arc>>), + ExportSample(Arc>>), + ImportClip(Arc>>), + ExportClip(Arc>>), +} + /// Various possible messages #[derive(PartialEq, Clone, Copy, Debug)] pub enum Message { @@ -235,10 +244,22 @@ impl App { Some(Dialog::Menu(0)) } fn dialog_save (&self) -> Option { - Some(Dialog::Save(Default::default())) + Some(Dialog::Browser(BrowserTarget::SaveProject, Default::default())) } fn dialog_load (&self) -> Option { - Some(Dialog::Load(Default::default())) + Some(Dialog::Browser(BrowserTarget::LoadProject, Default::default())) + } + fn dialog_import_clip (&self) -> Option { + Some(Dialog::Browser(BrowserTarget::ImportClip(Default::default()), Default::default())) + } + fn dialog_export_clip (&self) -> Option { + Some(Dialog::Browser(BrowserTarget::ExportClip(Default::default()), Default::default())) + } + fn dialog_import_sample (&self) -> Option { + Some(Dialog::Browser(BrowserTarget::ImportSample(Default::default()), Default::default())) + } + fn dialog_export_sample (&self) -> Option { + Some(Dialog::Browser(BrowserTarget::ExportSample(Default::default()), Default::default())) } fn dialog_options (&self) -> Option { Some(Dialog::Options) diff --git a/crates/app/src/view.rs b/crates/app/src/view.rs index bda57ddb..4c8099c5 100644 --- a/crates/app/src/view.rs +++ b/crates/app/src/view.rs @@ -64,18 +64,19 @@ impl App { } pub fn view_ports_status (&self) -> impl Content + use<'_> { self.project.get_track().map(|track|Bsp::s( - Fixed::y(4.max(track.sequencer.midi_ins.len() as u16), Align::n(Map::south(1, + Fixed::y(2.max(track.sequencer.midi_ins.len() as u16), Align::n(Map::south(1, ||track.sequencer.midi_ins.iter(), |port, index|Fixed::x(20, FieldV( self.color, - format!("IN {index}: "), + format!("MIDI in {index}: "), format!("{}", port.name())))))), - Fixed::y(4.max(track.sequencer.midi_outs.len() as u16), Align::n(Map::south(1, + Fixed::y(2.max(track.sequencer.midi_outs.len() as u16), Align::n(Map::south(1, ||track.sequencer.midi_outs.iter(), |port, index|Fixed::x(20, FieldV( self.color, - format!("OUT {index}: "), - format!("{}", port.name())))))))) + format!("MIDI out {index}:"), + format!("{}", port.name())))))) + )) } pub fn view_arranger (&self) -> impl Content + use<'_> { ArrangerView::new(&self.project, self.editor.as_ref()) @@ -116,10 +117,8 @@ impl App { self.view_dialog_menu().boxed(), Dialog::Help(offset) => self.view_dialog_help(*offset).boxed(), - Dialog::Save(browser) => - self.view_dialog_save(browser).boxed(), - Dialog::Load(browser) => - self.view_dialog_load(browser).boxed(), + Dialog::Browser(target, browser) => + self.view_dialog_browser(target, browser).boxed(), Dialog::Options => self.view_dialog_options().boxed(), Dialog::Device(index) => @@ -162,11 +161,19 @@ impl App { pub fn view_dialog_message <'a> (&'a self, message: &'a Message) -> impl Content + use<'a> { Bsp::s(message, Bsp::s("", "[ OK ]")) } - pub fn view_dialog_save <'a> (&'a self, browser: &'a Browser) -> impl Content + use<'a> { + pub fn view_dialog_browser <'a> (&'a self, target: &BrowserTarget, browser: &'a Browser) -> impl Content + use<'a> { Bsp::s( - Fill::x(Align::w(Margin::xy(1, 1, Bsp::e( - Tui::bold(true, " Save project: "), - Shrink::x(3, Fixed::y(1, RepeatH("🭻"))))))), + Padding::xy(3, 1, Fill::x(Align::w(FieldV( + self.color, + match target { + BrowserTarget::SaveProject => "Save project:", + BrowserTarget::LoadProject => "Load project:", + BrowserTarget::ImportSample(_) => "Import sample:", + BrowserTarget::ExportSample(_) => "Export sample:", + BrowserTarget::ImportClip(_) => "Import clip:", + BrowserTarget::ExportClip(_) => "Export clip:", + }, + Shrink::x(3, Fixed::y(1, Tui::fg(Tui::g(96), RepeatH("🭻")))))))), Outer(true, Style::default().fg(Tui::g(96))) .enclose(Fill::xy(browser))) } @@ -178,6 +185,22 @@ impl App { Outer(true, Style::default().fg(Tui::g(96))) .enclose(Fill::xy(browser))) } + pub fn view_dialog_export <'a> (&'a self, browser: &'a Browser) -> impl Content + use<'a> { + Bsp::s( + Fill::x(Align::w(Margin::xy(1, 1, Bsp::e( + Tui::bold(true, " Export: "), + Shrink::x(3, Fixed::y(1, RepeatH("🭻"))))))), + Outer(true, Style::default().fg(Tui::g(96))) + .enclose(Fill::xy(browser))) + } + pub fn view_dialog_import <'a> (&'a self, browser: &'a Browser) -> impl Content + use<'a> { + Bsp::s( + Fill::x(Align::w(Margin::xy(1, 1, Bsp::e( + Tui::bold(true, " Import: "), + Shrink::x(3, Fixed::y(1, RepeatH("🭻"))))))), + Outer(true, Style::default().fg(Tui::g(96))) + .enclose(Fill::xy(browser))) + } pub fn view_dialog_options <'a> (&'a self) -> impl Content + use<'a> { "TODO" } diff --git a/crates/device/src/sampler/sampler_view.rs b/crates/device/src/sampler/sampler_view.rs index 5875cff4..7b21233d 100644 --- a/crates/device/src/sampler/sampler_view.rs +++ b/crates/device/src/sampler/sampler_view.rs @@ -246,9 +246,9 @@ fn draw_info_v (sample: Option<&Arc>>) -> impl Content + Fill::x(Align::w(FieldH(theme, "Gain ", format!("{}", sample.gain)))), )) }), Thunk::new(move||Tui::fg(Red, col!( - "× No sample.", - "Press record", - "or import.", + Tui::bold(true, "× No sample."), + "[r] record", + "[Shift-F9] import", )))) }