From ea5bc2e3b1bc981e40fb869a4ad649bbca16e36e Mon Sep 17 00:00:00 2001 From: unspeaker Date: Thu, 5 Sep 2024 17:38:32 +0300 Subject: [PATCH] wip: 21 errors! --- Cargo.lock | 10 ++ crates/tek_core/src/component/collect.rs | 2 +- crates/tek_core/src/engine.rs | 27 +++- crates/tek_core/src/engine/handle.rs | 46 +++++++ crates/tek_core/src/engine/render.rs | 69 ++++++++++ crates/tek_core/src/event.rs | 16 --- crates/tek_core/src/handle.rs | 45 ------- crates/tek_core/src/jack_core.rs | 2 +- crates/tek_core/src/jack_device.rs | 4 +- crates/tek_core/src/keymap.rs | 4 +- crates/tek_core/src/lib.rs | 3 - crates/tek_core/src/render.rs | 68 ---------- crates/tek_core/src/tui.rs | 54 ++++++-- crates/tek_mixer/src/mixer_cli.rs | 2 +- crates/tek_mixer/src/mixer_handle.rs | 16 +-- crates/tek_mixer/src/plugin.rs | 18 ++- crates/tek_mixer/src/plugin_lv2.rs | 2 +- crates/tek_mixer/src/sampler.rs | 10 +- crates/tek_mixer/src/track_handle.rs | 12 +- crates/tek_mixer/src/track_view.rs | 4 +- crates/tek_sequencer/src/arranger_handle.rs | 128 +++++++++---------- crates/tek_sequencer/src/arranger_rename.rs | 12 +- crates/tek_sequencer/src/arranger_track.rs | 2 +- crates/tek_sequencer/src/arranger_view_h.rs | 14 +- crates/tek_sequencer/src/arranger_view_v.rs | 71 +++++----- crates/tek_sequencer/src/scene.rs | 2 +- crates/tek_sequencer/src/sequencer_handle.rs | 2 +- crates/tek_sequencer/src/sequencer_view_h.rs | 80 +++++------- crates/tek_sequencer/src/transport_handle.rs | 9 +- crates/tek_sequencer/src/transport_render.rs | 20 +-- 30 files changed, 392 insertions(+), 362 deletions(-) create mode 100644 crates/tek_core/src/engine/handle.rs create mode 100644 crates/tek_core/src/engine/render.rs delete mode 100644 crates/tek_core/src/event.rs diff --git a/Cargo.lock b/Cargo.lock index 43013a91..a1cde1cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2524,16 +2524,26 @@ dependencies = [ "suil-rs", "symphonia", "tek_core", + "tek_proc", "vst", "wavers", "winit", ] +[[package]] +name = "tek_proc" +version = "0.1.0" +dependencies = [ + "quote", + "syn 2.0.60", +] + [[package]] name = "tek_sequencer" version = "0.1.0" dependencies = [ "tek_core", + "tek_proc", ] [[package]] diff --git a/crates/tek_core/src/component/collect.rs b/crates/tek_core/src/component/collect.rs index 05ef4971..39d0c02c 100644 --- a/crates/tek_core/src/component/collect.rs +++ b/crates/tek_core/src/component/collect.rs @@ -6,7 +6,7 @@ pub enum Collected<'a, E: Engine> { } impl<'a, E: Engine> Render for Collected<'a, E> { - fn render (&self, to: &mut E) -> Perhaps { + fn render (&self, to: &mut E::RenderInput) -> Perhaps { match self { Self::Box(item) => (*item).render(to), Self::Ref(item) => (*item).render(to), diff --git a/crates/tek_core/src/engine.rs b/crates/tek_core/src/engine.rs index 191bc643..114d5c97 100644 --- a/crates/tek_core/src/engine.rs +++ b/crates/tek_core/src/engine.rs @@ -6,12 +6,25 @@ pub trait App { } /// Platform backend. -pub trait Engine { - type Handled; - type Rendered; - fn setup (&mut self) -> Usually<()> { Ok(()) } +pub trait Engine: Sized { + fn setup (&mut self) -> Usually<()> { Ok(()) } + fn exited (&self) -> bool; fn teardown (&mut self) -> Usually<()> { Ok(()) } - fn handle (&self, _: &mut impl Handle) -> Usually<()> where Self: Sized; - fn render (&mut self, _: &impl Render) -> Usually<()> where Self: Sized; - fn exited (&self) -> bool; + + type HandleInput; + fn handle (&self, _: &mut impl Handle) -> Usually<()> where Self: Sized; + type Handled; + + type RenderInput; + fn render (&mut self, _: &impl Render) -> Usually<()> where Self: Sized; + type Rendered; +} + +pub trait HandleContext {} + +pub trait RenderContext {} + +submod! { + render + handle } diff --git a/crates/tek_core/src/engine/handle.rs b/crates/tek_core/src/engine/handle.rs new file mode 100644 index 00000000..0478b259 --- /dev/null +++ b/crates/tek_core/src/engine/handle.rs @@ -0,0 +1,46 @@ +use crate::*; + +/// Handle input +pub trait Handle: Send + Sync { + fn handle (&mut self, context: &E::HandleInput) -> Perhaps; +} + +impl Handle for &mut H where H: Handle { + fn handle (&mut self, context: &E::HandleInput) -> Perhaps { + (*self).handle(context) + } +} + +impl Handle for Option where H: Handle { + fn handle (&mut self, context: &E::HandleInput) -> Perhaps { + if let Some(ref mut handle) = self { + handle.handle(context) + } else { + Ok(None) + } + } +} + +impl Handle for Mutex where H: Handle { + fn handle (&mut self, context: &E::HandleInput) -> Perhaps { + self.lock().unwrap().handle(context) + } +} + +impl Handle for Arc> where H: Handle { + fn handle (&mut self, context: &E::HandleInput) -> Perhaps { + self.lock().unwrap().handle(context) + } +} + +impl Handle for RwLock where H: Handle { + fn handle (&mut self, context: &E::HandleInput) -> Perhaps { + self.write().unwrap().handle(context) + } +} + +impl Handle for Arc> where H: Handle { + fn handle (&mut self, context: &E::HandleInput) -> Perhaps { + self.write().unwrap().handle(context) + } +} diff --git a/crates/tek_core/src/engine/render.rs b/crates/tek_core/src/engine/render.rs new file mode 100644 index 00000000..7c9aaaf1 --- /dev/null +++ b/crates/tek_core/src/engine/render.rs @@ -0,0 +1,69 @@ +use crate::*; + +/// Render to output. +pub trait Render: Send + Sync { + fn render (&self, to: &mut E::RenderInput) -> Perhaps; +} + +/// Options can be rendered optionally. +impl Render for Option where R: Render { + fn render (&self, to: &mut E::RenderInput) -> Perhaps { + match self { + Some(component) => component.render(to), + None => Ok(None) + } + } +} + +/// Boxed references can be rendered. +impl<'a, E: Engine> Render for Box + 'a> { + fn render (&self, to: &mut E::RenderInput) -> Perhaps { + (**self).render(to) + } +} + +/// Immutable references can be rendered. +impl Render for &R where R: Render { + fn render (&self, to: &mut E::RenderInput) -> Perhaps { + (*self).render(to) + } +} + +/// Mutable references can be rendered. +impl Render for &mut R where R: Render { + fn render (&self, to: &mut E::RenderInput) -> Perhaps { + (**self).render(to) + } +} + +/// Counted references can be rendered. +impl Render for Arc where R: Render { + fn render (&self, to: &mut E::RenderInput) -> Perhaps { + self.as_ref().render(to) + } +} + +/// References behind a [Mutex] can be rendered. +impl Render for Mutex where R: Render { + fn render (&self, to: &mut E::RenderInput) -> Perhaps { + self.lock().unwrap().render(to) + } +} + +/// References behind a [RwLock] can be rendered. +impl Render for RwLock where R: Render { + fn render (&self, to: &mut E::RenderInput) -> Perhaps { + self.read().unwrap().render(to) + } +} + +/// Boxed closures can be rendered. +/// +/// Rendering unboxed closures should also be possible; +/// but in practice implementing the trait for an unboxed +/// `Fn` closure causes an impl conflict. +impl<'a, E: Engine> Render for Box Perhaps + Send + Sync + 'a> { + fn render (&self, to: &mut E::RenderInput) -> Perhaps { + (*self)(to) + } +} diff --git a/crates/tek_core/src/event.rs b/crates/tek_core/src/event.rs deleted file mode 100644 index ceeff4fb..00000000 --- a/crates/tek_core/src/event.rs +++ /dev/null @@ -1,16 +0,0 @@ -#[derive(Debug)] -pub enum AppEvent { - /// Terminal input - Input(::crossterm::event::Event), - /// Update values but not the whole form. - Update, - /// Update the whole form. - Redraw, - /// Device gains focus - Focus, - /// Device loses focus - Blur, - // /// JACK notification - // Jack(JackEvent) -} - diff --git a/crates/tek_core/src/handle.rs b/crates/tek_core/src/handle.rs index 24767959..c7b7e813 100644 --- a/crates/tek_core/src/handle.rs +++ b/crates/tek_core/src/handle.rs @@ -1,46 +1 @@ use crate::*; - -/// Handle input -pub trait Handle: Send + Sync { - fn handle (&mut self, context: &E) -> Perhaps; -} - -impl Handle for &mut H where H: Handle { - fn handle (&mut self, context: &E) -> Perhaps { - (*self).handle(context) - } -} - -impl Handle for Option where H: Handle { - fn handle (&mut self, context: &E) -> Perhaps { - if let Some(ref mut handle) = self { - handle.handle(context) - } else { - Ok(None) - } - } -} - -impl Handle for Mutex where H: Handle { - fn handle (&mut self, context: &E) -> Perhaps { - self.lock().unwrap().handle(context) - } -} - -impl Handle for Arc> where H: Handle { - fn handle (&mut self, context: &E) -> Perhaps { - self.lock().unwrap().handle(context) - } -} - -impl Handle for RwLock where H: Handle { - fn handle (&mut self, context: &E) -> Perhaps { - self.write().unwrap().handle(context) - } -} - -impl Handle for Arc> where H: Handle { - fn handle (&mut self, context: &E) -> Perhaps { - self.write().unwrap().handle(context) - } -} diff --git a/crates/tek_core/src/jack_core.rs b/crates/tek_core/src/jack_core.rs index 14ea9568..a742722d 100644 --- a/crates/tek_core/src/jack_core.rs +++ b/crates/tek_core/src/jack_core.rs @@ -12,7 +12,7 @@ pub trait Device: Component + Process { impl Device for D where D: Component + Process {} impl Render for Box> { - fn render (&self, to: &mut E) -> Perhaps { + fn render (&self, to: &mut E::RenderInput) -> Perhaps { (**self).render(to) } } diff --git a/crates/tek_core/src/jack_device.rs b/crates/tek_core/src/jack_device.rs index f2772a7e..24049bc2 100644 --- a/crates/tek_core/src/jack_device.rs +++ b/crates/tek_core/src/jack_device.rs @@ -16,12 +16,12 @@ impl std::fmt::Debug for JackDevice { } } impl Render for JackDevice { - fn render (&self, to: &mut E) -> Perhaps { + fn render (&self, to: &mut E::RenderInput) -> Perhaps { self.state.read().unwrap().render(to) } } impl Handle for JackDevice { - fn handle (&mut self, from: &E) -> Perhaps { + fn handle (&mut self, from: &E::HandleInput) -> Perhaps { self.state.write().unwrap().handle(from) } } diff --git a/crates/tek_core/src/keymap.rs b/crates/tek_core/src/keymap.rs index db5fd05c..191d97ea 100644 --- a/crates/tek_core/src/keymap.rs +++ b/crates/tek_core/src/keymap.rs @@ -9,10 +9,10 @@ pub type KeyBinding = ( pub type KeyMap = [KeyBinding]; pub fn handle_keymap ( - state: &mut T, event: &AppEvent, keymap: &KeyMap, + state: &mut T, event: &TuiEvent, keymap: &KeyMap, ) -> Usually { match event { - AppEvent::Input(crossterm::event::Event::Key(event)) => { + TuiEvent::Input(crossterm::event::Event::Key(event)) => { for (code, modifiers, _, _, command) in keymap.iter() { if *code == event.code && modifiers.bits() == event.modifiers.bits() { return command(state) diff --git a/crates/tek_core/src/lib.rs b/crates/tek_core/src/lib.rs index 74958ee6..c0163643 100644 --- a/crates/tek_core/src/lib.rs +++ b/crates/tek_core/src/lib.rs @@ -30,17 +30,14 @@ submod! { component edn engine - event exit focus - handle jack_core jack_device jack_event jack_ports keymap space - render time tui } diff --git a/crates/tek_core/src/render.rs b/crates/tek_core/src/render.rs index e0c54f6a..c7b7e813 100644 --- a/crates/tek_core/src/render.rs +++ b/crates/tek_core/src/render.rs @@ -1,69 +1 @@ use crate::*; - -/// Render to output. -pub trait Render: Send + Sync { - fn render (&self, to: &mut E) -> Perhaps; -} - -/// Options can be rendered optionally. -impl Render for Option where R: Render { - fn render (&self, to: &mut E) -> Perhaps { - match self { - Some(component) => component.render(to), - None => Ok(None) - } - } -} - -/// Boxed references can be rendered. -impl<'a, E: Engine> Render for Box + 'a> { - fn render (&self, to: &mut E) -> Perhaps { - (**self).render(to) - } -} - -/// Immutable references can be rendered. -impl Render for &R where R: Render { - fn render (&self, to: &mut E) -> Perhaps { - (*self).render(to) - } -} - -/// Mutable references can be rendered. -impl Render for &mut R where R: Render { - fn render (&self, to: &mut E) -> Perhaps { - (**self).render(to) - } -} - -/// Counted references can be rendered. -impl Render for Arc where R: Render { - fn render (&self, to: &mut E) -> Perhaps { - self.as_ref().render(to) - } -} - -/// References behind a [Mutex] can be rendered. -impl Render for Mutex where R: Render { - fn render (&self, to: &mut E) -> Perhaps { - self.lock().unwrap().render(to) - } -} - -/// References behind a [RwLock] can be rendered. -impl Render for RwLock where R: Render { - fn render (&self, to: &mut E) -> Perhaps { - self.read().unwrap().render(to) - } -} - -/// Boxed closures can be rendered. -/// -/// Rendering unboxed closures should also be possible; -/// but in practice implementing the trait for an unboxed -/// `Fn` closure causes an impl conflict. -impl<'a, E: Engine> Render for Box Perhaps + Send + Sync + 'a> { - fn render (&self, to: &mut E) -> Perhaps { - (*self)(to) - } -} diff --git a/crates/tek_core/src/tui.rs b/crates/tek_core/src/tui.rs index f7440725..79649fa5 100644 --- a/crates/tek_core/src/tui.rs +++ b/crates/tek_core/src/tui.rs @@ -15,12 +15,15 @@ pub struct Tui { buffer: usize, buffers: [Buffer;2], backend: CrosstermBackend, + event: RwLock>, area: Rect, sleep: Duration, poll: Duration, } impl Engine for Tui { + type HandleInput = Self; type Handled = bool; + type RenderInput = Self; type Rendered = Rect; fn exited (&self) -> bool { self.exited.fetch_and(true, Ordering::Relaxed) @@ -46,8 +49,12 @@ impl Engine for Tui { code: KeyCode::Char('c'), modifiers: KeyModifiers::CONTROL, .. }) = event { self.exited.store(true, Ordering::Relaxed); - } else if let Err(e) = state.handle(self) { - panic!("{e}") + } else { + *self.event.write().unwrap() = Some(TuiEvent::Input(event)); + let result = state.handle(self); + if let Err(e) = result { + panic!("{e}") + } } } Ok(()) @@ -69,6 +76,7 @@ impl Tui { sleep: Duration::from_millis(20), poll: Duration::from_millis(100), exited: Arc::new(AtomicBool::new(false)), + event: RwLock::new(None), buffer: 0, buffers: [Buffer::empty(area), Buffer::empty(area)], backend, @@ -102,6 +110,15 @@ impl Tui { main_thread.join().expect("main thread failed"); Ok(state) } + pub fn event (&self) -> TuiEvent { + self.event.read().unwrap().clone().unwrap() + } + pub fn area (&self) -> Rect { + self.area + } + pub fn buffer (&mut self) -> &mut Buffer { + &mut self.buffers[self.buffer] + } fn flip (&mut self) { let previous_buffer = &self.buffers[1 - self.buffer]; let current_buffer = &self.buffers[self.buffer]; @@ -110,12 +127,6 @@ impl Tui { self.buffers[1 - self.buffer].reset(); self.buffer = 1 - self.buffer; } - pub fn area (&self) -> Rect { - self.area - } - pub fn buffer (&mut self) -> &mut Buffer { - &mut self.buffers[self.buffer] - } pub fn buffer_update (&mut self, area: Rect, callback: &impl Fn(&mut Cell, u16, u16)) { buffer_update(self.buffer(), area, callback) } @@ -151,15 +162,40 @@ impl Tui { } Ok(Some(Rect { x, y, width: text.len() as u16, height: 1 })) } + #[inline] pub fn alter_area ( &mut self, alter: impl Fn(u16, u16, u16, u16)->(u16, u16, u16, u16) ) -> &mut Self { let (x, y, width, height) = alter( self.area.x, self.area.y, self.area.width, self.area.height ); - self.area = Rect { x, y, width, height }; + self.with_area(x, y, width, height) + } + #[inline] + pub fn with_area (&mut self, x: u16, y: u16, w: u16, h: u16) -> &mut Self { + self.with_rect(Rect { x, y, width: w, height: h }); self } + #[inline] + pub fn with_rect (&mut self, area: Rect) -> &mut Self { + self.area = area; + self + } +} +#[derive(Debug, Clone)] +pub enum TuiEvent { + /// Terminal input + Input(::crossterm::event::Event), + /// Update values but not the whole form. + Update, + /// Update the whole form. + Redraw, + /// Device gains focus + Focus, + /// Device loses focus + Blur, + // /// JACK notification + // Jack(JackEvent) } /// Rendering unit struct to Ratatui returns zero-sized [Rect] at render coordinates. diff --git a/crates/tek_mixer/src/mixer_cli.rs b/crates/tek_mixer/src/mixer_cli.rs index e927b091..46b179b2 100644 --- a/crates/tek_mixer/src/mixer_cli.rs +++ b/crates/tek_mixer/src/mixer_cli.rs @@ -8,7 +8,7 @@ pub struct MixerCli { /// Number of tracks #[arg(short, long)] channels: Option, } -impl Mixer { +impl Mixer { pub fn from_args () -> Usually { let args = MixerCli::parse(); let mut mix = Self::new("")?; diff --git a/crates/tek_mixer/src/mixer_handle.rs b/crates/tek_mixer/src/mixer_handle.rs index 7bdbf785..425033ac 100644 --- a/crates/tek_mixer/src/mixer_handle.rs +++ b/crates/tek_mixer/src/mixer_handle.rs @@ -1,8 +1,8 @@ use crate::*; -impl Handle for Mixer { - fn handle (&mut self, event: &AppEvent) -> Usually { - if let AppEvent::Input(crossterm::event::Event::Key(event)) = event { +impl Handle for Mixer { + fn handle (&mut self, engine: &Tui) -> Perhaps { + if let TuiEvent::Input(crossterm::event::Event::Key(event)) = engine.event() { match event.code { //KeyCode::Char('c') => { @@ -13,7 +13,7 @@ impl Handle for Mixer { KeyCode::Down => { self.selected_track = (self.selected_track + 1) % self.tracks.len(); println!("{}", self.selected_track); - return Ok(true) + return Ok(Some(true)) }, KeyCode::Up => { if self.selected_track == 0 { @@ -22,7 +22,7 @@ impl Handle for Mixer { self.selected_track -= 1; } println!("{}", self.selected_track); - return Ok(true) + return Ok(Some(true)) }, KeyCode::Left => { if self.selected_column == 0 { @@ -30,7 +30,7 @@ impl Handle for Mixer { } else { self.selected_column -= 1; } - return Ok(true) + return Ok(Some(true)) }, KeyCode::Right => { if self.selected_column == 6 { @@ -38,7 +38,7 @@ impl Handle for Mixer { } else { self.selected_column += 1; } - return Ok(true) + return Ok(Some(true)) }, _ => { println!("\n{event:?}"); @@ -46,7 +46,7 @@ impl Handle for Mixer { } } - Ok(false) + Ok(None) } } diff --git a/crates/tek_mixer/src/plugin.rs b/crates/tek_mixer/src/plugin.rs index 413246a9..6bfe3a87 100644 --- a/crates/tek_mixer/src/plugin.rs +++ b/crates/tek_mixer/src/plugin.rs @@ -9,7 +9,11 @@ pub struct Plugin { pub mapping: bool, pub ports: JackPorts, } -handle!(Plugin |self, e| handle_keymap(self, e, KEYMAP_PLUGIN)); +impl Handle for Plugin { + fn handle (&mut self, e: &Tui) -> Perhaps { + handle_keymap(self, event, KEYMAP_PLUGIN) + } +} process!(Plugin = Plugin::process); impl Render for Plugin { fn render (&self, to: &mut Tui) -> Perhaps { @@ -36,7 +40,7 @@ impl Render for Plugin { } else { None } ; - label.blit(to.buffer(), x + 2, y + 1 + i as u16 - start as u16, style)?; + to.blit(&label, x + 2, y + 1 + i as u16 - start as u16, style)?; } else { break } @@ -44,7 +48,7 @@ impl Render for Plugin { }, _ => {} }; - draw_header(self, to.buffer(), area.x, area.y, width)?; + draw_header(self, to, area.x, area.y, width)?; Ok(Some(Rect { width, ..to.area() })) } } @@ -58,7 +62,7 @@ pub enum PluginKind { VST3, } impl Plugin { - pub fn new_lv2 (name: &str, path: &str) -> Usually> { + pub fn new_lv2 (name: &str, path: &str) -> Usually> { let plugin = LV2Plugin::new(path)?; jack_from_lv2(name, &plugin.plugin)? .run(|ports|Box::new(Self { @@ -137,13 +141,13 @@ impl Plugin { Control::Continue } } -fn draw_header (state: &Plugin, buf: &mut Buffer, x: u16, y: u16, w: u16) -> Usually { +fn draw_header (state: &Plugin, to: &mut Tui, x: u16, y: u16, w: u16) -> Usually { let style = Style::default().gray(); let label1 = format!(" {}", state.name); - label1.blit(buf, x + 1, y, Some(style.white().bold()))?; + to.blit(&label1, x + 1, y, Some(style.white().bold()))?; if let Some(ref path) = state.path { let label2 = format!("{}…", &path[..((w as usize - 10).min(path.len()))]); - label2.blit(buf, x + 2 + label1.len() as u16, y, Some(style.not_dim()))?; + to.blit(&label2, x + 2 + label1.len() as u16, y, Some(style.not_dim()))?; } Ok(Rect { x, y, width: w, height: 1 }) } diff --git a/crates/tek_mixer/src/plugin_lv2.rs b/crates/tek_mixer/src/plugin_lv2.rs index febccc95..ba645e5f 100644 --- a/crates/tek_mixer/src/plugin_lv2.rs +++ b/crates/tek_mixer/src/plugin_lv2.rs @@ -22,7 +22,7 @@ pub struct LV2Plugin { } impl LV2Plugin { - pub fn from_edn <'e, T, U> (args: &[Edn<'e>]) -> Usually> { + pub fn from_edn <'e, E: Engine> (args: &[Edn<'e>]) -> Usually> { let mut name = String::new(); let mut path = String::new(); edn!(edn in args { diff --git a/crates/tek_mixer/src/sampler.rs b/crates/tek_mixer/src/sampler.rs index 6df1b95b..f7c7a6ab 100644 --- a/crates/tek_mixer/src/sampler.rs +++ b/crates/tek_mixer/src/sampler.rs @@ -13,8 +13,8 @@ pub struct Sampler { pub modal: Arc>>>, pub output_gain: f32 } -impl Handle for Sampler { - fn handle (&mut self, e: &E) -> Usually { +impl Handle for Sampler { + fn handle (&mut self, e: &Tui) -> Perhaps { handle_keymap(self, event, KEYMAP_SAMPLER) } } @@ -69,7 +69,7 @@ pub const KEYMAP_SAMPLER: &'static [KeyBinding] = keymap!(Sampler { }); impl Sampler { - pub fn from_edn <'e, E: Engine> (args: &[Edn<'e>]) -> Usually> { + pub fn from_edn <'e> (args: &[Edn<'e>]) -> Usually> { let mut name = String::new(); let mut dir = String::new(); let mut samples = BTreeMap::new(); @@ -98,9 +98,9 @@ impl Sampler { Self::new(&name, Some(samples)) } - pub fn new ( + pub fn new ( name: &str, mapped: Option>>> - ) -> Usually> { + ) -> Usually> { Jack::new(name)? .midi_in("midi") .audio_in("recL") diff --git a/crates/tek_mixer/src/track_handle.rs b/crates/tek_mixer/src/track_handle.rs index 0d30772b..1add38d3 100644 --- a/crates/tek_mixer/src/track_handle.rs +++ b/crates/tek_mixer/src/track_handle.rs @@ -1,9 +1,9 @@ use crate::*; -impl Handle for Track { - fn handle (&mut self, event: &AppEvent) -> Usually { - match event { - AppEvent::Input(crossterm::event::Event::Key(event)) => { +impl Handle for Track { + fn handle (&mut self, from: &Tui) -> Perhaps { + match from.event() { + TuiEvent::Input(crossterm::event::Event::Key(event)) => { for (code, modifiers, _, _, command) in [ key!(Up, NONE, "chain_cursor_up", "move cursor up", || { Ok(true) @@ -34,9 +34,9 @@ impl Handle for Track { return command() } } - return Ok(false) + return Ok(None) }, - _ => Ok(false) + _ => Ok(None) } } } diff --git a/crates/tek_mixer/src/track_view.rs b/crates/tek_mixer/src/track_view.rs index 746e6b02..28aa47d4 100644 --- a/crates/tek_mixer/src/track_view.rs +++ b/crates/tek_mixer/src/track_view.rs @@ -46,7 +46,7 @@ impl<'a> Render for TrackView<'a, Tui> { } let (area, areas) = split.render_areas(to)?; if self.focused && self.entered && areas.len() > 0 { - Corners(Style::default().green().not_dim()).draw(to.buffer, areas[0])?; + Corners(Style::default().green().not_dim()).draw(to.with_rect(areas[0]))?; } Ok(Some(area)) } else { @@ -54,7 +54,7 @@ impl<'a> Render for TrackView<'a, Tui> { let label = "No chain selected"; let x = x + (width - label.len() as u16) / 2; let y = y + height / 2; - label.blit(to.buffer(), x, y, Some(Style::default().dim().bold()))?; + to.blit(&label, x, y, Some(Style::default().dim().bold()))?; Ok(Some(area)) } } diff --git a/crates/tek_sequencer/src/arranger_handle.rs b/crates/tek_sequencer/src/arranger_handle.rs index d8e48866..772d4b5d 100644 --- a/crates/tek_sequencer/src/arranger_handle.rs +++ b/crates/tek_sequencer/src/arranger_handle.rs @@ -1,71 +1,69 @@ use crate::*; -impl Handle for Arranger { - fn handle (&mut self, event: &AppEvent) -> Usually { - match self.modal.as_mut() { - Some(modal) => { - let result = modal.handle(event)?; - if modal.exited() { - self.modal = None; - } - Ok(result) - }, - None => match event { - AppEvent::Input(crossterm::event::Event::Key(event)) => { - for (code, modifiers, _, _, command) in [ - key!(Char('`'), NONE, "mode_switch", "switch the display mode", || { - self.mode.to_next(); - Ok(true) - }), - key!(Up, NONE, "cursor_up", "move cursor up", || { - match self.mode { - ArrangerViewMode::Horizontal => self.track_prev(), - _ => self.scene_prev(), - }; - self.show_phrase()?; - Ok(true) - }), - key!(Down, NONE, "cursor_down", "move cursor down", || { - match self.mode { - ArrangerViewMode::Horizontal => self.track_next(), - _ => self.scene_next(), - }; - self.show_phrase()?; - Ok(true) - }), - key!(Left, NONE, "cursor_left", "move cursor left", || { - match self.mode { - ArrangerViewMode::Horizontal => self.scene_prev(), - _ => self.track_prev(), - }; - self.show_phrase()?; - Ok(true) - }), - key!(Right, NONE, "cursor_right", "move cursor right", || { - match self.mode { - ArrangerViewMode::Horizontal => self.scene_next(), - _ => self.track_next(), - }; - self.show_phrase()?; - Ok(true) - }), - key!(Char('.'), NONE, "increment", "set next clip at cursor", || { self.phrase_next(); Ok(true) }), - key!(Char(','), NONE, "decrement", "set previous clip at cursor", || { self.phrase_prev(); Ok(true) }), - key!(Enter, NONE, "activate", "activate item at cursor", || { self.activate(); Ok(true) }), - key!(Char('a'), CONTROL, "scene_add", "add a new scene", || { self.scene_add(None)?; Ok(true) }), - key!(Char('t'), CONTROL, "track_add", "add a new track", || { self.track_add(None)?; Ok(true) }), - key!(Char('n'), NONE, "rename", "rename item at cursor", || { self.rename_selected(); Ok(true) }), - key!(Char('l'), NONE, "length", "set length of item at cursor", || { todo!(); Ok(true) }), - key!(Char('c'), NONE, "color", "set color of item at cursor", || { todo!(); Ok(true) }) - ].iter() { - if *code == event.code && modifiers.bits() == event.modifiers.bits() { - return command() - } - } - return Ok(false) - }, - _ => Ok(false) +impl Handle for Arranger { + fn handle (&mut self, from: &Tui) -> Perhaps { + if let Some(modal) = self.modal.as_mut() { + let result = modal.handle(from)?; + if modal.exited() { + self.modal = None; } + return Ok(result) + } + match from.event() { + TuiEvent::Input(crossterm::event::Event::Key(event)) => { + for (code, modifiers, _, _, command) in [ + key!(Char('`'), NONE, "mode_switch", "switch the display mode", || { + self.mode.to_next(); + Ok(true) + }), + key!(Up, NONE, "cursor_up", "move cursor up", || { + match self.mode { + ArrangerViewMode::Horizontal => self.track_prev(), + _ => self.scene_prev(), + }; + self.show_phrase()?; + Ok(true) + }), + key!(Down, NONE, "cursor_down", "move cursor down", || { + match self.mode { + ArrangerViewMode::Horizontal => self.track_next(), + _ => self.scene_next(), + }; + self.show_phrase()?; + Ok(true) + }), + key!(Left, NONE, "cursor_left", "move cursor left", || { + match self.mode { + ArrangerViewMode::Horizontal => self.scene_prev(), + _ => self.track_prev(), + }; + self.show_phrase()?; + Ok(true) + }), + key!(Right, NONE, "cursor_right", "move cursor right", || { + match self.mode { + ArrangerViewMode::Horizontal => self.scene_next(), + _ => self.track_next(), + }; + self.show_phrase()?; + Ok(true) + }), + key!(Char('.'), NONE, "increment", "set next clip at cursor", || { self.phrase_next(); Ok(true) }), + key!(Char(','), NONE, "decrement", "set previous clip at cursor", || { self.phrase_prev(); Ok(true) }), + key!(Enter, NONE, "activate", "activate item at cursor", || { self.activate(); Ok(true) }), + key!(Char('a'), CONTROL, "scene_add", "add a new scene", || { self.scene_add(None)?; Ok(true) }), + key!(Char('t'), CONTROL, "track_add", "add a new track", || { self.track_add(None)?; Ok(true) }), + key!(Char('n'), NONE, "rename", "rename item at cursor", || { self.rename_selected(); Ok(true) }), + key!(Char('l'), NONE, "length", "set length of item at cursor", || { todo!(); Ok(true) }), + key!(Char('c'), NONE, "color", "set color of item at cursor", || { todo!(); Ok(true) }) + ].iter() { + if *code == event.code && modifiers.bits() == event.modifiers.bits() { + return command() + } + } + return Ok(None) + }, + _ => Ok(None) } } } diff --git a/crates/tek_sequencer/src/arranger_rename.rs b/crates/tek_sequencer/src/arranger_rename.rs index e6c1c11c..fcd2fe4e 100644 --- a/crates/tek_sequencer/src/arranger_rename.rs +++ b/crates/tek_sequencer/src/arranger_rename.rs @@ -42,7 +42,7 @@ impl Render for ArrangerRenameModal { height: 3 }; to.fill_bg(bg_area, Nord::BG0); - Lozenge(Style::default().bold().white().dim()).draw(to.buffer, bg_area)?; + Lozenge(Style::default().bold().white().dim()).draw(to.with_rect(bg_area)); let label = match self.target { ArrangerFocus::Mix => "Rename project:", ArrangerFocus::Track(_) => "Rename track:", @@ -58,10 +58,10 @@ impl Render for ArrangerRenameModal { Ok(Some(area)) } } -impl Handle for TransportQuantize { +impl Handle for ArrangerRenameModal { fn handle (&mut self, from: &Tui) -> Perhaps { - match e { - AppEvent::Input(Event::Key(k)) => { + match from.event() { + TuiEvent::Input(Event::Key(k)) => { match k.code { KeyCode::Esc => { self.exit(); @@ -90,9 +90,9 @@ impl Handle for TransportQuantize { }, _ => {} } - Ok(true) + Ok(Some(true)) }, - _ => Ok(false), + _ => Ok(None), } } } diff --git a/crates/tek_sequencer/src/arranger_track.rs b/crates/tek_sequencer/src/arranger_track.rs index fd899605..267009b2 100644 --- a/crates/tek_sequencer/src/arranger_track.rs +++ b/crates/tek_sequencer/src/arranger_track.rs @@ -3,7 +3,7 @@ use crate::*; use super::Arranger; /// Track management methods -impl Arranger { +impl Arranger { pub fn track (&self) -> Option<&Sequencer> { self.selected.track().map(|t|self.tracks.get(t)).flatten() } diff --git a/crates/tek_sequencer/src/arranger_view_h.rs b/crates/tek_sequencer/src/arranger_view_h.rs index bcd4130f..50b4ca33 100644 --- a/crates/tek_sequencer/src/arranger_view_h.rs +++ b/crates/tek_sequencer/src/arranger_view_h.rs @@ -29,14 +29,14 @@ impl<'a> Render for TrackNameColumn<'a> { let offset = 0; // track scroll offset for y in 0..area.height { if y == 0 { - "Mixer".blit(to.buffer, area.x + 1, area.y + y, Some(DIM))?; + to.blit(&"Mixer", area.x + 1, area.y + y, Some(DIM))?; } else if y % 2 == 0 { let index = (y as usize - 2) / 2 + offset; if let Some(track) = tracks.get(index) { let selected = selected.track() == Some(index); let style = if selected { yellow } else { white }; - format!(" {index:>02} ").blit(to.buffer, area.x, area.y + y, style)?; - track.name.read().unwrap().blit(to.buffer, area.x + 4, area.y + y, style)?; + to.blit(&format!(" {index:>02} "), area.x, area.y + y, style)?; + to.blit(&*track.name.read().unwrap(), area.x + 4, area.y + y, style)?; } } } @@ -60,7 +60,7 @@ impl<'a> Render for TrackMonitorColumn<'a> { let index = (y as usize - 2) / 2; if let Some(track) = tracks.get(index) { let style = if track.monitoring { on } else { off }; - " MON ".blit(to.buffer, area.x, area.y + y, style)?; + to.blit(&" MON ", area.x, area.y + y, style)?; } else { area.height = y; break @@ -88,7 +88,7 @@ impl<'a> Render for TrackRecordColumn<'a> { let index = (y as usize - 2) / 2; if let Some(track) = tracks.get(index) { let style = if track.recording { on } else { off }; - " REC ".blit(to.buffer, area.x, area.y + y, style)?; + to.blit(&" REC ", area.x, area.y + y, style)?; } else { area.height = y; break @@ -115,7 +115,7 @@ impl<'a> Render for TrackOverdubColumn<'a> { } else if y % 2 == 0 { let index = (y as usize - 2) / 2; if let Some(track) = tracks.get(index) { - " OVR ".blit(to.buffer, area.x, area.y + y, if track.overdub { + to.blit(&" OVR ", area.x, area.y + y, if track.overdub { on } else { off @@ -203,7 +203,7 @@ impl<'a> Render for TrackScenesColumn<'a> { } let name = scene.name.read().unwrap(); let mut x3 = name.len() as u16; - to.blit(&name, x + x2, y, sep)?; + to.blit(&*name, x + x2, y, sep)?; for (i, clip) in scene.clips.iter().enumerate() { let active_track = selected.track() == Some(i); if let Some(clip) = clip { diff --git a/crates/tek_sequencer/src/arranger_view_v.rs b/crates/tek_sequencer/src/arranger_view_v.rs index 6db5b19a..0c06b4c3 100644 --- a/crates/tek_sequencer/src/arranger_view_v.rs +++ b/crates/tek_sequencer/src/arranger_view_v.rs @@ -33,7 +33,7 @@ pub fn draw <'a, 'b> ( cols: &'b [(usize, usize)], rows: &'b [(usize, usize)], ) -> Perhaps { - let mut area = to.area; + let mut area = to.area(); area.height = 2 + (rows[rows.len() - 1].1 / 96) as u16; let offset = 3 + scene_name_max_len(state.scenes.as_ref()) as u16; let tracks = state.tracks.as_ref(); @@ -53,13 +53,13 @@ struct ColumnSeparators<'a>(u16, &'a [(usize, usize)]); impl<'a> Render for ColumnSeparators<'a> { fn render (&self, to: &mut Tui) -> Perhaps { - let area = to.area; + let area = to.area(); let Self(offset, cols) = self; let style = Some(Style::default().fg(Nord::SEPARATOR)); for (_, x) in cols.iter() { let x = offset + area.x + *x as u16 - 1; for y in area.y..area.height+area.y { - "▎".blit(to.buffer, x, y, style)?; + to.blit(&"▎", x, y, style)?; } } Ok(Some(area)) @@ -70,15 +70,15 @@ struct RowSeparators<'a>(&'a [(usize, usize)]); impl<'a> Render for RowSeparators<'a> { fn render (&self, to: &mut Tui) -> Perhaps { - let mut area = to.area; + let area = to.area(); let Self(rows) = self; for (_, y) in rows.iter() { let y = area.y + (*y / 96) as u16 + 1; - if y >= to.buffer.area.height { + if y >= to.buffer().area.height { break } for x in area.x..area.width+area.y-2 { - let cell = to.buffer.get_mut(x, y); + let cell = to.buffer().get_mut(x, y); cell.modifier = Modifier::UNDERLINED; cell.underline_color = Nord::SEPARATOR; } @@ -93,7 +93,7 @@ struct CursorFocus<'a>( impl<'a> Render for CursorFocus<'a> { fn render (&self, to: &mut Tui) -> Perhaps { - let mut area = to.area; + let mut area = to.area(); let Self(selected, offset, cols, rows) = *self; let get_track_area = |t: usize| Rect { x: offset + area.x + cols[t].1 as u16 - 1, @@ -118,7 +118,7 @@ impl<'a> Render for CursorFocus<'a> { let mut clip_area: Option = None; let area = match selected { ArrangerFocus::Mix => { - fill_bg(to.buffer, area, COLOR_BG0); + to.fill_bg(area, COLOR_BG0); area }, ArrangerFocus::Track(t) => { @@ -137,21 +137,21 @@ impl<'a> Render for CursorFocus<'a> { }, }; if let Some(Rect { x, y, width, height }) = track_area { - fill_fg(to.buffer, Rect { x, y, width: 1, height }, COLOR_BG5); - fill_fg(to.buffer, Rect { x: x + width, y, width: 1, height }, COLOR_BG5); + to.fill_fg(Rect { x, y, width: 1, height }, COLOR_BG5); + to.fill_fg(Rect { x: x + width, y, width: 1, height }, COLOR_BG5); } if let Some(Rect { y, height, .. }) = scene_area { - fill_ul(to.buffer, Rect { x: area.x, y: y - 1, width: area.width, height: 1 }, COLOR_BG5); - fill_ul(to.buffer, Rect { x: area.x, y: y + height - 1, width: area.width, height: 1 }, COLOR_BG5); + to.fill_ul(Rect { x: area.x, y: y - 1, width: area.width, height: 1 }, COLOR_BG5); + to.fill_ul(Rect { x: area.x, y: y + height - 1, width: area.width, height: 1 }, COLOR_BG5); } if let Some(clip_area) = clip_area { - fill_bg(to.buffer, clip_area, COLOR_BG0); + to.fill_bg(clip_area, COLOR_BG0); } else if let Some(track_area) = track_area { - fill_bg(to.buffer, track_area, COLOR_BG0); + to.fill_bg(track_area, COLOR_BG0); } else if let Some(scene_area) = scene_area { - fill_bg(to.buffer, scene_area, COLOR_BG0); + to.fill_bg(scene_area, COLOR_BG0); } - Ok(area) + Ok(Some(area)) } } @@ -159,7 +159,7 @@ struct TracksHeader<'a>(u16, &'a[(usize, usize)], &'a [Sequencer]); impl<'a> Render for TracksHeader<'a> { fn render (&self, to: &mut Tui) -> Perhaps { - let mut area = to.area; + let area = to.area(); let Self(offset, track_cols, tracks) = *self; let Rect { y, width, .. } = area; for (track, (w, x)) in tracks.iter().zip(track_cols) { @@ -168,8 +168,8 @@ impl<'a> Render for TracksHeader<'a> { break } let name = track.name.read().unwrap(); - fill_bg(to.buffer, Rect { x: offset + x, y, width: *w as u16, height: 2 }, COLOR_BG1); - name.blit(to.buffer, offset + x + 1, y, Some(Style::default().white()))?; + to.fill_bg(Rect { x: offset + x, y, width: *w as u16, height: 2 }, COLOR_BG1); + to.blit(&*name, offset + x + 1, y, Some(Style::default().white()))?; } Ok(Some(Rect { x: area.x, y, width, height: 2 })) } @@ -179,15 +179,15 @@ struct SceneRows<'a>(u16, &'a[(usize, usize)], &'a[(usize, usize)], &'a[Sequence impl<'a> Render for SceneRows<'a> { fn render (&self, to: &mut Tui) -> Perhaps { - let area = to.area; + let area = to.area(); let Self(offset, track_cols, scene_rows, tracks, scenes) = *self; let black = Some(Style::default().fg(Nord::SEPARATOR)); - let Rect { mut y, height, .. } = area; + let Rect { mut y, height: _height, .. } = area; for (_, x) in track_cols.iter() { let x = *x as u16; if x > 0 { for y in area.y-2..y-2 { - "▎".blit(to.buffer, x - 1, y, black)?; + to.blit(&"▎", x - 1, y, black)?; } } } @@ -196,10 +196,8 @@ impl<'a> Render for SceneRows<'a> { //break //} let h = 1.max((pulses / 96) as u16); - SceneRow(tracks, scene, track_cols, offset).render(&mut TuiOutput { - buffer: to.buffer, - area: Rect { x: area.x, y, width: area.width, height: h, } - })?; + SceneRow(tracks, scene, track_cols, offset) + .render(to.with_area(area.x, y, area.width, h))?; y = y + h } Ok(Some(area)) @@ -210,29 +208,24 @@ struct SceneRow<'a>(&'a[Sequencer], &'a Scene, &'a[(usize, usize)], u16); impl<'a> Render for SceneRow<'a> { fn render (&self, to: &mut Tui) -> Perhaps { - let mut area = to.area(); + let area = to.area(); let Self(tracks, scene, track_cols, offset) = self; let Rect { x, y, width, .. } = area; let playing = scene.is_playing(tracks); - (if playing { "▶" } else { " " }).blit(to.buffer(), x, y, None)?; - scene.name.read().unwrap().blit(to.buffer(), x + 1, y, Some(Style::default().white()))?; + to.blit(&if playing { "▶" } else { " " }, x, y, None)?; + to.blit(&*scene.name.read().unwrap(), x + 1, y, Some(Style::default().white()))?; to.fill_bg(Rect { x: x, y, width: offset.saturating_sub(1), height: area.height }, COLOR_BG1); for (track, (w, x)) in track_cols.iter().enumerate() { let x = *x as u16 + offset; if x > width { break } - if let (Some(track), Some(Some(clip))) = ( tracks.get(track), scene.clips.get(track) ) { - SceneClip(track, *clip).render(&mut TuiOutput { - buffer: to.buffer, - area: Rect { x, y, width: *w as u16, height: area.height, } - })?; + SceneClip(track, *clip).render(to.with_area(x, y, *w as u16, area.height))?; } } - Ok(Some(area)) } } @@ -241,20 +234,20 @@ struct SceneClip<'a>(&'a Sequencer, usize); impl<'a> Render for SceneClip<'a> { fn render (&self, to: &mut Tui) -> Perhaps { - let area = to.area; + let area = to.area(); let Self(track, clip) = self; let style = Some(Style::default().white()); if let Some(phrase) = track.phrases.get(*clip) { let phrase = phrase.read().unwrap(); let name = phrase.name.read().unwrap(); - format!("{clip:02} {name}").blit(to.buffer, area.x + 1, area.y, style)?; - fill_bg(to.buffer, area, if track.sequence == Some(*clip) { + to.blit(&format!("{clip:02} {name}"), area.x + 1, area.y, style)?; + to.fill_bg(area, if track.sequence == Some(*clip) { Nord::PLAYING } else { COLOR_BG1 }); } else { - fill_bg(to.buffer, area, COLOR_BG0) + to.fill_bg(area, COLOR_BG0) } Ok(Some(area)) } diff --git a/crates/tek_sequencer/src/scene.rs b/crates/tek_sequencer/src/scene.rs index 1edf8266..e8c6b76e 100644 --- a/crates/tek_sequencer/src/scene.rs +++ b/crates/tek_sequencer/src/scene.rs @@ -79,7 +79,7 @@ pub fn scene_ppqs (tracks: &[Sequencer], scenes: &[Scene]) -> Vec<(usize, usize) scenes } -impl Arranger { +impl Arranger { pub fn scene (&self) -> Option<&Scene> { self.selected.scene().map(|s|self.scenes.get(s)).flatten() } diff --git a/crates/tek_sequencer/src/sequencer_handle.rs b/crates/tek_sequencer/src/sequencer_handle.rs index 5b93e418..b43a8695 100644 --- a/crates/tek_sequencer/src/sequencer_handle.rs +++ b/crates/tek_sequencer/src/sequencer_handle.rs @@ -2,7 +2,7 @@ use crate::*; impl Handle for TransportQuantize { fn handle (&mut self, from: &Tui) -> Perhaps { - handle_keymap(self, e, KEYMAP_SEQUENCER) + handle_keymap(self, &from.event(), KEYMAP_SEQUENCER) } } diff --git a/crates/tek_sequencer/src/sequencer_view_h.rs b/crates/tek_sequencer/src/sequencer_view_h.rs index 2db221a1..53f302cc 100644 --- a/crates/tek_sequencer/src/sequencer_view_h.rs +++ b/crates/tek_sequencer/src/sequencer_view_h.rs @@ -11,19 +11,11 @@ impl Sequencer { .add_ref(&SequenceRange) .add_ref(&SequenceLoopRange) .add_ref(&SequenceNoteRange) - .render(&mut TuiOutput { - buffer: to.buffer, - area: Rect { - x: area.x, - y: area.y, - height: area.height, - width: 10, - } - })?; + .render(to.with_area(area.x, area.y, area.height, 10))?; area.x = area.x + 10; area.width = area.width.saturating_sub(10); area.height = area.height.min(66); - Lozenge(Style::default().fg(Nord::BG2)).draw(to.buffer, area)?; + Lozenge(Style::default().fg(Nord::BG2)).draw(to.with_rect(area))?; area.x = area.x + 1; area.width = area.width.saturating_sub(1); Layered::new() @@ -32,10 +24,7 @@ impl Sequencer { .add_ref(&SequenceNotes(&self)) .add_ref(&SequenceCursor(&self)) .add_ref(&SequenceZoom(&self)) - .render(&mut TuiOutput { - buffer: to.buffer, - area: area - })?; + .render(to.with_rect(area))?; Ok(()) } @@ -63,9 +52,9 @@ impl<'a> Render for SequenceName<'a> { fn render (&self, to: &mut Tui) -> Perhaps { let Rect { x, y, .. } = to.area(); let frame = Rect { x, y, width: 10, height: 4 }; - Lozenge(Style::default().fg(Nord::BG2)).draw(to.buffer, frame)?; - "Name:".blit(to.buffer, x + 1, y + 1, STYLE_LABEL)?; - self.0.name.read().unwrap().blit(to.buffer, x + 1, y + 2, STYLE_VALUE)?; + Lozenge(Style::default().fg(Nord::BG2)).draw(to.with_rect(frame))?; + to.blit(&"Name:", x + 1, y + 1, STYLE_LABEL)?; + to.blit(&*self.0.name.read().unwrap(), x + 1, y + 2, STYLE_VALUE)?; Ok(Some(frame)) } } @@ -76,11 +65,11 @@ impl<'a> Render for SequenceRange { fn render (&self, to: &mut Tui) -> Perhaps { let Rect { x, y, .. } = to.area(); let frame = Rect { x, y, width: 10, height: 6 }; - Lozenge(Style::default().fg(Nord::BG2)).draw(to.buffer, frame)?; - "Start: ".blit(to.buffer, x + 1, y + 1, STYLE_LABEL)?; - " 1.1.1".blit(to.buffer, x + 1, y + 2, STYLE_VALUE)?; - "End: ".blit(to.buffer, x + 1, y + 3, STYLE_LABEL)?; - " 2.1.1".blit(to.buffer, x + 1, y + 4, STYLE_VALUE)?; + Lozenge(Style::default().fg(Nord::BG2)).draw(to.with_rect(frame))?; + to.blit(&"Start: ", x + 1, y + 1, STYLE_LABEL)?; + to.blit(&" 1.1.1", x + 1, y + 2, STYLE_VALUE)?; + to.blit(&"End: ", x + 1, y + 3, STYLE_LABEL)?; + to.blit(&" 2.1.1", x + 1, y + 4, STYLE_VALUE)?; Ok(Some(frame)) } } @@ -91,12 +80,12 @@ impl<'a> Render for SequenceLoopRange { fn render (&self, to: &mut Tui) -> Perhaps { let Rect { x, y, .. } = to.area(); let range = Rect { x, y, width: 10, height: 7 }; - Lozenge(Style::default().fg(Nord::BG2)).draw(to.buffer, range)?; - "Loop [ ]".blit(to.buffer, x + 1, y + 1, STYLE_LABEL)?; - "From: ".blit(to.buffer, x + 1, y + 2, STYLE_LABEL)?; - " 1.1.1".blit(to.buffer, x + 1, y + 3, STYLE_VALUE)?; - "Length: ".blit(to.buffer, x + 1, y + 4, STYLE_LABEL)?; - " 1.0.0".blit(to.buffer, x + 1, y + 5, STYLE_VALUE)?; + Lozenge(Style::default().fg(Nord::BG2)).draw(to.with_rect(range))?; + to.blit(&"Loop [ ]", x + 1, y + 1, STYLE_LABEL)?; + to.blit(&"From: ", x + 1, y + 2, STYLE_LABEL)?; + to.blit(&" 1.1.1", x + 1, y + 3, STYLE_VALUE)?; + to.blit(&"Length: ", x + 1, y + 4, STYLE_LABEL)?; + to.blit(&" 1.0.0", x + 1, y + 5, STYLE_VALUE)?; Ok(Some(range)) } } @@ -107,15 +96,15 @@ impl<'a> Render for SequenceNoteRange { fn render (&self, to: &mut Tui) -> Perhaps { let Rect { x, y, .. } = to.area(); let range = Rect { x, y, width: 10, height: 9 }; - Lozenge(Style::default().fg(Nord::BG2)).draw(to.buffer, range)?; - "Notes: ".blit(to.buffer, x + 1, y + 1, STYLE_LABEL)?; - "C#0-C#9 ".blit(to.buffer, x + 1, y + 2, STYLE_VALUE)?; - "[ /2 ]".blit(to.buffer, x + 1, y + 3, STYLE_LABEL)?; - "[ x2 ]".blit(to.buffer, x + 1, y + 4, STYLE_LABEL)?; - "[ Rev ]".blit(to.buffer, x + 1, y + 5, STYLE_LABEL)?; - "[ Inv ]".blit(to.buffer, x + 1, y + 6, STYLE_LABEL)?; - "[ Dup ]".blit(to.buffer, x + 1, y + 7, STYLE_LABEL)?; - Ok(Some(to.area)) + Lozenge(Style::default().fg(Nord::BG2)).draw(to.with_rect(range))?; + to.blit(&"Notes: ", x + 1, y + 1, STYLE_LABEL)?; + to.blit(&"C#0-C#9 ", x + 1, y + 2, STYLE_VALUE)?; + to.blit(&"[ /2 ]", x + 1, y + 3, STYLE_LABEL)?; + to.blit(&"[ x2 ]", x + 1, y + 4, STYLE_LABEL)?; + to.blit(&"[ Rev ]", x + 1, y + 5, STYLE_LABEL)?; + to.blit(&"[ Inv ]", x + 1, y + 6, STYLE_LABEL)?; + to.blit(&"[ Dup ]", x + 1, y + 7, STYLE_LABEL)?; + Ok(Some(to.area())) } } @@ -123,22 +112,23 @@ struct SequenceKeys<'a>(&'a Sequencer); impl<'a> Render for SequenceKeys<'a> { fn render (&self, to: &mut Tui) -> Perhaps { - if to.area.height < 2 { - return Ok(Some(to.area)) + let area = to.area(); + if area.height < 2 { + return Ok(Some(area)) } let area = Rect { - x: to.area.x, - y: to.area.y + 1, + x: area.x, + y: area.y + 1, width: 5, - height: to.area.height - 2 + height: area.height - 2 }; - buffer_update(to.buffer, area, &|cell, x, y|{ + buffer_update(to.buffer(), area, &|cell, x, y|{ let y = y + self.0.note_axis.start as u16; if x < self.0.keys.area.width && y < self.0.keys.area.height { *cell = self.0.keys.get(x, y).clone() } }); - Ok(Some(to.area)) + Ok(Some(area)) } } @@ -195,7 +185,7 @@ impl<'a> Render for SequenceZoom<'a> { let quant = ppq_to_name(self.0.time_axis.scale); let quant_x = area.x + area.width - 1 - quant.len() as u16; let quant_y = area.y + area.height - 2; - buffer.blit(&quant, quant_x, quant_y, self.0.style_focus()) + to.blit(&quant, quant_x, quant_y, self.0.style_focus()) } } diff --git a/crates/tek_sequencer/src/transport_handle.rs b/crates/tek_sequencer/src/transport_handle.rs index cf69bd5a..4e28de32 100644 --- a/crates/tek_sequencer/src/transport_handle.rs +++ b/crates/tek_sequencer/src/transport_handle.rs @@ -14,7 +14,7 @@ impl Handle for TransportToolbar { impl Handle for TransportPlayPauseButton { fn handle (&mut self, from: &Tui) -> Perhaps { - Ok(false) + Ok(None) } } @@ -26,7 +26,7 @@ impl Handle for TransportBPM { //TransportFocus::BPM => { //transport.timebase.bpm.fetch_sub(1.0, Ordering::Relaxed); //}, - Ok(false) + Ok(None) } } @@ -38,7 +38,7 @@ impl Handle for TransportQuantize { //TransportFocus::Quant => { //transport.quant.value = prev_note_length(transport.quant); //}, - Ok(false) + Ok(None) } } @@ -50,6 +50,7 @@ impl Handle for TransportSync { //TransportFocus::Sync => { //transport.sync.value = prev_note_length(transport.sync); //}, + Ok(None) } } @@ -61,6 +62,6 @@ impl Handle for TransportClock { //TransportFocus::Sync => { //transport.sync.value = prev_note_length(transport.sync); //}, - Ok(false) + Ok(None) } } diff --git a/crates/tek_sequencer/src/transport_render.rs b/crates/tek_sequencer/src/transport_render.rs index b5e5bb6a..ac030cf9 100644 --- a/crates/tek_sequencer/src/transport_render.rs +++ b/crates/tek_sequencer/src/transport_render.rs @@ -71,11 +71,12 @@ impl Render for TransportBPM { impl Render for TransportQuantize { fn render (&self, to: &mut Tui) -> Perhaps { - let area = to.area(); - let Rect { x, y, .. } = to.area; + let Rect { x, y, .. } = to.area(); let Self { value, focused } = self; - "QUANT".blit(to.buffer, x, y, Some(NOT_DIM))?; - let width = ppq_to_name(*value as usize).blit(to.buffer, x, y + 1, Some(NOT_DIM_BOLD))?.width; + to.blit(&"QUANT", x, y, Some(NOT_DIM))?; + let name = ppq_to_name(*value as usize); + let width = name.len() as u16; + to.blit(&name, x, y + 1, Some(NOT_DIM_BOLD))?; let area = Rect { x, y, width: (width + 2).max(10), height: 2 }; if *focused { let area = Rect { x: area.x - 1, width: area.width - 1, ..area }; @@ -88,11 +89,12 @@ impl Render for TransportQuantize { impl Render for TransportSync { fn render (&self, to: &mut Tui) -> Perhaps { - let area = to.area(); - let Rect { x, y, .. } = to.area; + let Rect { x, y, .. } = to.area(); let Self { value, focused } = self; - "SYNC".blit(to.buffer, x, y, Some(NOT_DIM))?; - let width = ppq_to_name(*value as usize).blit(to.buffer, x, y + 1, Some(NOT_DIM_BOLD))?.width; + to.blit(&"SYNC", x, y, Some(NOT_DIM))?; + let name = ppq_to_name(*value as usize); + let width = name.len() as u16; + to.blit(&name, x, y + 1, Some(NOT_DIM_BOLD))?; let area = Rect { x, y, width: (width + 2).max(10), height: 2 }; if *focused { let area = Rect { x: area.x - 1, width: area.width - 1, ..area }; @@ -106,7 +108,7 @@ impl Render for TransportSync { impl Render for TransportClock { fn render (&self, to: &mut Tui) -> Perhaps { let Rect { x, y, width, .. } = to.area(); - let Self { frame, pulse, ppq, usecs, focused } = self; + let Self { frame: _frame, pulse, ppq, usecs, focused } = self; let (beats, pulses) = if *ppq > 0 { (pulse / ppq, pulse % ppq) } else { (0, 0) }; let (bars, beats) = ((beats / 4) + 1, (beats % 4) + 1); let (seconds, msecs) = (usecs / 1000000, usecs / 1000 % 1000);