diff --git a/src/tek.edn b/src/tek.edn index 66c5d694..48bec674 100644 --- a/src/tek.edn +++ b/src/tek.edn @@ -1,11 +1,11 @@ (mode Menu (name Main Menu) (info Welcome to Tek!) (keys Y Confirm) - (view (bar/s 2 Transport (bar/n 2 Status (align/c (bar/s 2 (align/x (bg (g 12) Logo)) Menu)))))) + (view (bar/s 2 Transport (bar/n 2 StatusBar (align/c (bar/s 2 (align/x (bg (g 12) Logo)) Menu)))))) (mode Transport (name Transport) (info JACK transport controller.) (keys Clock Global) (view Transport)) (mode Arranger (name Arranger) (info Launch grid.) (keys Global Clock Tracks Scenes Clip Launch Color History) - (view (bar/n 2 Status (bar/s 8 (bar/e 16 (align/nw Transport) + (view (bar/n 2 StatusBar (bar/s 8 (bar/e 16 (align/nw Transport) (bar/w 20 (bar/s 2 (bar/w 4 TracksOutputsAdd TracksOutputsCount) (bar/s 2 (bar/w 4 TracksDevicesAdd TracksDevicesCount) (bar/s 2 (bar/w 4 TracksNamesAdd TracksNamesCount) @@ -16,10 +16,10 @@ (bar/w 20 (text) (bar/e 16 ScenesNames ScenesClips)))))) (mode Sequencer (info MIDI sequencer.) (keys Global Clock I IFine Y Page EditorView EditorAdd EditorDel) - (view (bsp/s (exact/h 1 Transport) (bsp/n (exact/h 1 Status) (fill/xy (bsp/a (fill/xy (align/e Pool)) Editor)))))) + (view (bsp/s (exact/h 1 Transport) (bsp/n (exact/h 1 StatusBar) (fill/xy (bsp/a (fill/xy (align/e Pool)) Editor)))))) (mode Sampler (info Sample player.) (keys SamplerDirs SamplerRec SamplerPlay) - (view (bsp/s (exact/h 1 Transport) (bsp/n (exact/h 1 Status) (fill/xy SampleGrid))))) + (view (bsp/s (exact/h 1 Transport) (bsp/n (exact/h 1 StatusBar) (fill/xy SampleGrid))))) (mode Groovebox (info Sequencer with sampler.) (keys Global Clock Sampler I IFine Y Page EditorView EditorAdd EditorDel) (view (bsp/w MetersOut (bsp/e MetersIn (bsp/w GrooveMeta GrooveEditor))))) @@ -32,7 +32,8 @@ (view GrooveEditor (bsp/n GrooveSample GrooveSequence)) (view GrooveSample (exact/h SampleHeight (bsp/e (fill/y (exact/w 20 (align/nw SampleStatus))) SampleViewer))) (view GrooveSequence (bsp/e (fill/y (align/n (bsp/s Status/v EditorStatus))) (bsp/e SamplesKeys Editor))) -(view Status (bar/s 1 (text Mode) ModeList)) +(view StatusBar (bar/e 40 (bg (g 10) (full/x (pad/x 1 (bar/s 1 (text Selected) Selected)))) + (bg (g 20) (full/x (pad/x 1 (bar/s 1 (text Mode) ModeList)))))) (view Transport (bg (g 0) (pad/x 1 (bar/e 4 PlayPause (bar/e 16 Bpm (bar/e 16 Beat Time)))))) (keys Global (@f1 (dialog Help)) diff --git a/src/tek.rs b/src/tek.rs index cc0c0531..90ce4736 100644 --- a/src/tek.rs +++ b/src/tek.rs @@ -2,7 +2,6 @@ mod deps; pub use self::deps::*; - mod midi_octave; pub use self::midi_octave::*; mod midi_piano; pub use self::midi_piano::*; mod midi_point; pub use self::midi_point::*; @@ -358,28 +357,28 @@ fn get_vec_arc_str <'a> (_: &App, _: impl Language) -> Perhaps>> { todo!() } -impl_has!(Clock: |self: App|self.project.clock); -impl_has!(Dialog: |self: App|self.dialog); -impl_has!(Jack<'static>: |self: App|self.jack); -impl_has!(Pool: |self: App|self.project.clips); -impl_has!(Pool: |self: App|self.project.samples); -impl_has!(Selection: |self: App|self.project.selection); -impl_has!(Sizer: |self: App|self.size); +primitive!(u8: try_to_u8); +primitive!(u16: try_to_u16); +primitive!(usize: try_to_usize); +primitive!(isize: try_to_isize); +impl_has!(Clock: |self: App|self.project.clock); +impl_has!(Dialog: |self: App|self.dialog); +impl_has!(Jack<'static>: |self: App|self.jack); +impl_has!(Pool: |self: App|self.project.clips); +impl_has!(Pool: |self: App|self.project.samples); +impl_has!(Selection: |self: App|self.project.selection); +impl_has!(Sizer: |self: App|self.size); impl_as_ref!(Option: |self: App|todo!()); impl_as_mut!(Option: |self: App|todo!()); impl_as_ref!(Option: |self: App|self.project.as_ref()); impl_as_mut!(Option: |self: App|self.project.as_mut()); + impl HasClip for App { fn clip_slot (&self) -> Option> { self.project.clip_slot() } } -primitive!(u8: try_to_u8); -primitive!(u16: try_to_u16); -primitive!(usize: try_to_usize); -primitive!(isize: try_to_isize); - tui_keys!(self: App, input { #[cfg(feature = "prof2")] profiling::scope!("App::tui_keys!"); Self::input_cmd(self, input) @@ -388,13 +387,13 @@ tui_keys!(self: App, input { impl App { fn input_cmd (state: &mut Self, input: &TuiEvent) -> Usually<()> { - if let Some(bindings) = Self::input_cmd_find(state, input) { - return Self::input_cmd_exec(state, bindings) + if let Some(bindings) = Self::input_cmds_find(state, input) { + return Self::input_cmds_exec(state, bindings) } Ok(()) } - fn input_cmd_find (state: &mut Self, input: &TuiEvent) -> Option>]>> { + fn input_cmds_find (state: &mut Self, input: &TuiEvent) -> Option>]>> { for name in state.modes.read().iter().rev() { let mode = state.config.get_mode(name).as_ref().map(Arc::clone); if let Some(mode) = mode { @@ -410,42 +409,30 @@ impl App { None } - fn input_cmd_exec (state: &mut Self, bindings: Arc<[Binding>]>) -> Usually<()> { + fn input_cmds_exec (state: &mut Self, bindings: Arc<[Binding>]>) -> Usually<()> { for binding in bindings.iter() { - for cmd in binding.commands.iter() { - if Self::cmd::(state, cmd)? { - return Ok(()) + for src in binding.commands.iter() { + if let Some(command) = Namespace::::namespace(state, &src)? { + Self::cmd_dispatch(state, command)?; } } } Ok(()) } - fn cmd < - T: Dispatch + Clone + Into - > (state: &mut Self, src: &str) -> Usually where - Self: Namespace, - { - if let Some(cmd) = Namespace::::namespace(state, &src)? { - return Self::cmd_dispatch(state, cmd.into()) - } - Ok(false) - } - - fn cmd_dispatch (state: &mut Self, cmd: AppCmd) -> Usually where - Self: Namespace, - { - match cmd.clone().dispatch(state) { - Err(err) => { - state.history.push((cmd.into(), None)); - return Err(err) - }, + fn cmd_dispatch (state: &mut Self, command: AppCmd) -> Usually<()> { + match command.clone().dispatch(state) { Ok(undo) => { - state.history.push((cmd.into(), undo.map(Into::into))); - return Ok(true) + state.history.push((command, undo)); + Ok(()) + }, + Err(err) => { + state.history.push((command, None)); + Err(err) } } } + } /// A control axis. diff --git a/src/tek_view.rs b/src/tek_view.rs index 1e4c915d..c46c6fb5 100644 --- a/src/tek_view.rs +++ b/src/tek_view.rs @@ -30,10 +30,11 @@ impl App { self.size.0.load(Relaxed), self.size.1.load(Relaxed)).align_w(), ).align_se(), - Split::East.bar(16, - format!("{}", self.modes.read()[0]), - format!("{}", self.modes.read()[0]) - ).align_sw() + () + //Split::East.bar(16, + //format!("{}", self.modes.read()[0]), + //format!("{}", self.modes.read()[0]) + //).align_sw() ).draw(to) } @@ -388,6 +389,7 @@ impl View { Some("ScenesClips") => draw!(|app|view_scenes_clips(app)), Some("ScenesNames") => draw!(|app|app.view_scenes_names()), Some("Sessions") => draw!(|___|view_sessions()), + Some("Selected") => draw!(|app|view_selection(app)), Some("Templates") => draw!(|app|view_templates(app)), Some("Time") => draw!(), Some("Tracks") => draw!("TODO tracks"), @@ -784,58 +786,6 @@ pub trait TracksView: }) } - fn view_outputs (&self, theme: ItemTheme) -> impl Draw { - let height = self.outputs_height(); - let list = south( - button_3("o", "utput", self.midi_outs().len(), false).align_w().full_w().exact_h(1), - bg(Color::Rgb(0, 0, 0), draw(|to: &mut Tui|{ - for (_index, port) in self.midi_outs().iter().enumerate() { - east( - east( - " ● ", - fg(Rgb(255,255,255), bold(true, port.port_name())) - ).align_w(), - east!( - port.port().get_connections().len(), - "/", - port.connections.len(), - " " - ).align_e().full_w().exact_h(1)).full_w().draw(to)?; - for (index, conn) in port.connections.iter().enumerate() { - east!( - " c", - index, - conn.info() - ).align_w().full_w().exact_h(1).draw(to)?; - } - } - todo!(); - })).align_nw().full_wh().exact_h(height - 1).min_h(1) - ); - view_track_row_section(theme, list, self.view_track_output_add(), - bg(theme.darker.term, draw(|to: &mut Tui|{ - for (index, track, _x1, _x2) in self.tracks_with_sizes() { - let _ = draw(|to: &mut Tui|{ - east( - either(true, fg(Green, "play "), "play "), - either(false, fg(Yellow, "solo "), "solo "), - ).align_w().exact_h(1).draw(to)?; - for (_index, port) in self.midi_outs().iter().enumerate() { - east( - either(true, fg(Green, " ● "), " · "), - either(false, fg(Yellow, " ● "), " · "), - ).align_w().exact_h(1).draw(to)?; - for (_index, _conn) in port.connections.iter().enumerate() { - "".full_w().exact_h(1).draw(to)?; - } - } - todo!() - }).exact_w(track_width(index, track)).draw(to)?; - } - todo!() - }).align_w().full_w())).exact_h(height) - } - fn tracks_devices_height (&self) -> u16 { self.tracks().iter().fold(2, |h, t|h.max(t.devices.len() * 2)) as u16 } fn tracks_inputs_height (&self) -> u16 { self.tracks().iter().fold(0, |h, t|h.max(t.sequencer.midi_ins.len())) as u16 } fn outputs_height (&self) -> u16 { self.midi_outs().iter().fold(1, |h, o|h + o.connections.len()) as u16 } @@ -856,36 +806,23 @@ pub trait TracksView: /// Draw outputs per track fn view_track_outputs <'a> (&'a self, theme: ItemTheme, _h: u16) -> impl Draw { - view_track_row_section(theme, - self.view_track_output_count(), - self.view_track_output_add(), - self.view_track_output_cells() - ) + view_track_row_section(theme, self.view_track_output_count(), self.view_track_output_add(), + self.view_track_output_cells()) } - - /// Draw name of each track - fn view_track_names (&self, theme: ItemTheme) -> impl Draw { - view_track_row_section(theme, - self.view_track_names_count(), - self.view_track_names_add(), - self.view_track_names_cells() - ) - } - /// Draw inputs per track fn view_track_inputs <'a> (&'a self, theme: ItemTheme) -> impl Draw { - view_track_row_section(theme, - self.view_track_input_count(), - self.view_track_input_add(), - self.view_track_input_cells(self.tracks_inputs_height()) - ) + view_track_row_section(theme, self.view_track_input_count(), self.view_track_input_add(), + self.view_track_input_cells(self.tracks_inputs_height())) } - + /// Draw devices of track fn view_track_devices (&self, theme: ItemTheme) -> impl Draw { - let height = self.tracks_devices_height(); - let btn1 = self.view_track_device_count(); - let btn2 = self.view_track_device_add(); - view_track_row_section(theme, btn1, btn2, self.view_track_device_cells(height)) + view_track_row_section(theme, self.view_track_device_count(), self.view_track_device_add(), + self.view_track_device_cells(self.tracks_devices_height())) + } + /// Draw name of each track + fn view_track_names (&self, theme: ItemTheme) -> impl Draw { + view_track_row_section(theme, self.view_track_names_count(), self.view_track_names_add(), + self.view_track_names_cells()) } fn view_inputs (&self) -> impl Draw + '_ { @@ -894,6 +831,44 @@ pub trait TracksView: east(title_1, west(title_2, self.view_input_cells())) } + fn view_outputs (&self, theme: ItemTheme) -> impl Draw { + let height = self.outputs_height(); + let list = south( + button_3("o", "utput", self.midi_outs().len(), false).align_w().full_w().exact_h(1), + bg(Color::Rgb(0, 0, 0), draw(|to: &mut Tui|{ + for (_index, port) in self.midi_outs().iter().enumerate() { + east( + east(" ● ", fg(Rgb(255,255,255), bold(true, port.port_name()))) + .align_w(), + east!(port.port().get_connections().len(), "/", port.connections.len(), " ") + .align_e().full_w().exact_h(1)).full_w().draw(to)?; + for (index, conn) in port.connections.iter().enumerate() { + east!(" c", index, conn.info()).align_w().full_w().exact_h(1).draw(to)?; + } + } + todo!(); + })).align_nw().full_wh().exact_h(height - 1).min_h(1) + ); + view_track_row_section(theme, list, self.view_track_output_add(), + bg(theme.darker.term, draw(|to: &mut Tui|{ + for (index, track, _x1, _x2) in self.tracks_with_sizes() { + let _ = draw(|to: &mut Tui|{ + east(either(true, fg(Green, "play "), "play "), + either(false, fg(Yellow, "solo "), "solo ")).align_w().exact_h(1).draw(to)?; + for (_index, port) in self.midi_outs().iter().enumerate() { + east(either(true, fg(Green, " ● "), " · "), + either(false, fg(Yellow, " ● "), " · ")).align_w().exact_h(1).draw(to)?; + for (_index, _conn) in port.connections.iter().enumerate() { + "".full_w().exact_h(1).draw(to)?; + } + } + todo!() + }).exact_w(track_width(index, track)).draw(to)?; + } + todo!() + }).align_w().full_w())).exact_h(height) + } + } fn view_n_of_m (key: &str, name: &str, index: Option, count: usize) -> impl Draw { @@ -1186,17 +1161,9 @@ pub fn view_track_row_section <'a> ( button_add: impl Draw, content: impl Draw, ) -> impl Draw { - bar( - Split::West, - 4u16, - button_add.align_ne().full_wh(), - bar( - Split::East, - 20u16, - button.full_wh().align_nw(), - content.align_c().full_wh() - ) - ) + Split::West.bar(4u16, button_add.align_ne().full_wh(), + Split::East.bar(20u16, button.full_wh().align_nw(), + content.align_c().full_wh())) } pub fn view_track_header <'a> (theme: ItemTheme, content: impl Draw) @@ -1243,6 +1210,10 @@ pub fn view_scene_name_theme (scene: &Scene, track_index: usize) -> (Arc, I }) } +pub fn view_selection <'a> (state: &'a App) -> impl Draw + use<'a> { + format!("{:?}", state.selection()) +} + pub fn view_templates <'a> (state: &'a App) -> impl Draw + use<'a> { let height = (state.config.modes.len() * 2) as u16; draw(move |to: &mut Tui|{ @@ -1401,9 +1372,9 @@ pub fn view_sample_status (sample: Option<&Arc>>) -> impl Draw (key: impl Draw, label: impl Draw, hide: bool) - -> impl Draw -{ +pub fn button_2 <'a> ( + key: impl Draw, label: impl Draw, hide: bool +) -> impl Draw { let c1 = tui_orange(); let c2 = tui_g(0); let c3 = tui_g(96); @@ -1420,10 +1391,7 @@ pub fn button_2 <'a> (key: impl Draw, label: impl Draw, hide: bool) /// let _ = tek::button_3("", "", "", false); /// ``` pub fn button_3 <'a> ( - key: impl Draw, - label: impl Draw, - value: impl Draw, - editing: bool, + key: impl Draw, label: impl Draw, value: impl Draw, editing: bool, ) -> impl Draw { let c1 = tui_orange(); let c2 = tui_g(0); @@ -1431,11 +1399,9 @@ pub fn button_3 <'a> ( let c4 = tui_g(255); let c5 = tui_g(128); bold(true, bar(Split::East, 3u16, - fg_bg(c1, c2, - bar(Split::East, 1u16, fg(c2, "▐"), - bar(Split::East, 1u16, key, fg(if editing { c5 } else { c3 }, "▐")))), - east( - when(!editing, east(fg_bg(c4, c3, label), fg_bg(c5, c3, "▐"),)), + fg_bg(c1, c2, bar(Split::East, 1u16, fg(c2, "▐"), + bar(Split::East, 1u16, key, fg(if editing { c5 } else { c3 }, "▐")))), + east(when(!editing, east(fg_bg(c4, c3, label), fg_bg(c5, c3, "▐"),)), east(fg_bg(tui_g(224), c5, value), fg_bg(c5, Reset, "▌"), )))) } @@ -1615,29 +1581,6 @@ pub trait InteriorMutable: Gettable { } } - //pub fn per_track <'a, T: Draw<'_, Tui> + 'a, U: TracksSizes<'a>> ( - //tracks: impl Fn() -> U + Send + Sync + 'a, - //callback: impl Fn(usize, &'a Track)->T + Send + Sync + 'a - //) -> impl Draw<'_, Tui> + 'a { - //per_track_top(tracks, move|index, track|callback(index, track).full_h().align_y()) - //} - - //pub fn per_track_top <'a, T: Draw<'_, Tui> + 'a, U: TracksSizes<'a>> ( - //tracks: impl Fn() -> U + Send + Sync + 'a, - //callback: impl Fn(usize, &'a Track)->T + Send + Sync + 'a - //) -> impl Draw<'_, Tui> + 'a { - //bg(Reset, iter_east(||tracks() - //.map(move|(index, track, x1, x2): (usize, &'a Track, usize, usize)|{ - //fg_bg( - //track.color.lightest.term, - //track.color.base.term, - //callback(index, track) - //).exact_w((x2 - x1) as u16) - //})).align_x()) - //} - //fn tui (&self) -> impl Draw { - //iter_south_fixed(1, ||self.tui_entries(), |entry, _index|entry.origin_w().full_w()) - //} //impl<'a> Iterator for EntriesIterator<'a, Tui> { //type Item = impl Draw; //fn next (&mut self) -> Option {