From 672d81f353d543152692f1a3d0156e940fd6480b Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sat, 6 Jul 2024 21:03:36 +0300 Subject: [PATCH] remove vec allocation from plugin callback --- src/core/time.rs | 4 + src/model/plugin.rs | 13 ++- src/model/plugin/lv2.rs | 26 ++++-- src/view.rs | 32 ++++--- src/view/grid.rs | 191 +++++++++++++++++++++------------------- 5 files changed, 150 insertions(+), 116 deletions(-) diff --git a/src/core/time.rs b/src/core/time.rs index cadda8d4..e70a283d 100644 --- a/src/core/time.rs +++ b/src/core/time.rs @@ -1,6 +1,7 @@ use crate::core::*; use atomic_float::AtomicF64; #[derive(Debug)] +/// Keeps track of global time units. pub struct Timebase { /// Frames per second rate: AtomicF64, @@ -98,14 +99,17 @@ impl Timebase { } +/// Defines frames per tick. pub struct Ticks(pub f64); impl Ticks { + /// Iterate over ticks between start and end. pub fn between_frames (&self, start: usize, end: usize) -> TicksIterator { TicksIterator(self.0, start, start, end) } } +/// Iterator that emits subsequent ticks within a range. pub struct TicksIterator(f64, usize, usize, usize); impl Iterator for TicksIterator { diff --git a/src/model/plugin.rs b/src/model/plugin.rs index 2554919b..bbc2cfd2 100644 --- a/src/model/plugin.rs +++ b/src/model/plugin.rs @@ -40,9 +40,14 @@ impl Plugin { } pub fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control { match self.plugin.as_mut() { - Some(PluginKind::LV2(LV2Plugin { features, ref mut instance, .. })) => { + Some(PluginKind::LV2(LV2Plugin { + features, + ref mut instance, + ref mut input_buffer, + .. + })) => { let urid = features.midi_urid(); - let mut inputs = vec![]; + input_buffer.clear(); for port in self.ports.midi_ins.values() { let mut atom = ::livi::event::LV2AtomSequence::new( &features, @@ -58,7 +63,7 @@ impl Plugin { _ => {} } } - inputs.push(atom); + input_buffer.push(atom); } let mut outputs = vec![]; for _ in self.ports.midi_outs.iter() { @@ -69,7 +74,7 @@ impl Plugin { } let ports = ::livi::EmptyPortConnections::new() .with_atom_sequence_inputs( - inputs.iter() + input_buffer.iter() ) .with_atom_sequence_outputs( outputs.iter_mut() diff --git a/src/model/plugin/lv2.rs b/src/model/plugin/lv2.rs index 1e7dc9c5..3002ee39 100644 --- a/src/model/plugin/lv2.rs +++ b/src/model/plugin/lv2.rs @@ -1,18 +1,29 @@ use crate::core::*; +use ::livi::{ + World, + Instance, + Plugin, + Features, + FeaturesBuilder, + Port, + event::LV2AtomSequence, +}; + pub struct LV2Plugin { - pub world: ::livi::World, - pub instance: ::livi::Instance, - pub plugin: ::livi::Plugin, - pub features: Arc<::livi::Features>, - pub port_list: Vec<::livi::Port>, + pub world: World, + pub instance: Instance, + pub plugin: Plugin, + pub features: Arc, + pub port_list: Vec, + pub input_buffer: Vec } impl LV2Plugin { pub fn new (uri: &str) -> Usually { // Get 1st plugin at URI - let world = ::livi::World::with_load_bundle(&uri); - let features = ::livi::FeaturesBuilder { min_block_length: 1, max_block_length: 65536 }; + let world = World::with_load_bundle(&uri); + let features = FeaturesBuilder { min_block_length: 1, max_block_length: 65536 }; let features = world.build_features(features); let mut plugin = None; for p in world.iter_plugins() { @@ -39,6 +50,7 @@ impl LV2Plugin { }, plugin, features, + input_buffer: Vec::with_capacity(1024) }) } } diff --git a/src/view.rs b/src/view.rs index 6b721a40..fa08cec6 100644 --- a/src/view.rs +++ b/src/view.rs @@ -9,7 +9,7 @@ pub mod plugin; pub use self::layout::*; pub use self::transport::TransportView; -pub use self::grid::SceneGridView; +pub use self::grid::*; pub use self::chain::ChainView; pub use self::sequencer::SequencerView; @@ -17,7 +17,6 @@ use crate::{render, App, core::*}; render!(App |self, buf, area| { let Rect { x, mut y, width, height } = area; - return Ok(area); y = y + TransportView { timebase: &self.timebase, @@ -29,16 +28,25 @@ render!(App |self, buf, area| { quant: self.quant, }.render(buf, area)?.height; - y = y + SceneGridView { - buf, - area: Rect { x, y, width, height: height / 3 }, - name: "", - mode: self.grid_mode, - focused: self.section == 0, - scenes: &self.scenes, - tracks: &self.tracks, - cursor: &(self.track_cursor, self.scene_cursor), - }.draw()?.height; + y = y + if self.grid_mode { + SceneGridViewHorizontal { + buf, + area: Rect { x, y, width, height: height / 3 }, + focused: self.section == 0, + scenes: &self.scenes, + tracks: &self.tracks, + cursor: &(self.track_cursor, self.scene_cursor), + }.draw()? + } else { + SceneGridViewVertical { + buf, + area: Rect { x, y, width, height: height / 3 }, + focused: self.section == 0, + scenes: &self.scenes, + tracks: &self.tracks, + cursor: &(self.track_cursor, self.scene_cursor), + }.draw()? + }.height; if self.track_cursor > 0 { diff --git a/src/view/grid.rs b/src/view/grid.rs index da46497f..3506a16f 100644 --- a/src/view/grid.rs +++ b/src/view/grid.rs @@ -1,25 +1,22 @@ use crate::core::*; use crate::model::*; use crate::view::*; -pub struct SceneGridView<'a> { +pub struct SceneGridViewHorizontal<'a> { pub buf: &'a mut Buffer, pub area: Rect, - pub name: &'a str, - pub focused: bool, pub scenes: &'a[Scene], pub tracks: &'a[Track], pub cursor: &'a(usize, usize), - pub mode: bool, + pub focused: bool } -impl<'a> SceneGridView<'a> { - fn longest_scene_name (&self) -> u16 { - let mut w = 3u16; - for scene in self.scenes.iter() { - w = w.max(scene.name.len() as u16); - } - w +impl<'a> SceneGridViewHorizontal<'a> { + pub fn size (&self) -> (u16, u16) { + let (mut w, mut h) = (4, 2); + w = w + self.longest_track_name(); + w = w + self.scenes.len() as u16 * 10; + h = h + self.tracks.len(); + (w as u16, h as u16) } - fn longest_track_name (&self) -> u16 { let mut w = 3u16; for track in self.tracks.iter() { @@ -27,75 +24,72 @@ impl<'a> SceneGridView<'a> { } w } - - pub fn size_horizontal (&mut self) -> (u16, u16) { - let (mut w, mut h) = (4, 2); - w = w + self.longest_track_name(); - w = w + self.scenes.len() as u16 * 10; - h = h + self.tracks.len(); - (w as u16, h as u16) - } - pub fn draw (&mut self) -> Usually { - match self.mode { - true => self.draw_horizontal(), - false => self.draw_vertical(), - } - } - - pub fn draw_horizontal (&mut self) -> Usually { //let (w, h) = self.size_horizontal(); //self.area.x = self.area.x + self.area.width.saturating_sub(w) / 2; self.area.height = self.tracks.len() as u16 + 2; //self.area.width = w; let style = Some(Style::default().green().dim()); + let Rect { x, y, width, height } = self.area; if self.focused { - let Rect { x, y, width, height } = self.area; lozenge_left(self.buf, x, y, height, style); lozenge_right(self.buf, x + width - 1, y, height, style); } - " Mix ".blit(self.buf,self.area.x+1,self.area.y,Some(Style::default().bold().not_dim().white())); + let style = Some(Style::default().bold().not_dim().white()); + "Mix".blit(self.buf, x + 1, y, style); let mut x2 = 0; + let style = Some(Style::default().bold()); for (i, track) in self.tracks.iter().enumerate() { - let label = format!(" {} ", &track.name); - label.blit(self.buf, self.area.x+1, self.area.y+1+i as u16, Some(Style::default().bold())); + let label = format!(" {:8} [R] [D] [M] ", &track.name); + label.blit(self.buf, x + 1, y + 1 + i as u16, style); x2 = x2.max(label.len() as u16 + 1); } - "╷".blit(self.buf, self.area.x + x2, self.area.y, style); - for y in self.area.y+1..self.area.y+self.area.height-1 { - "│".blit(self.buf, self.area.x + x2, y, style); + "╷".blit(self.buf, x + x2, y, style); + for y in y+1..y+height-1 { + "│".blit(self.buf, x + x2, y, style); } - //"╵".blit(self.buf, self.area.x + x2, self.area.y+self.area.height-1, style); + //"╵".blit(self.buf, x + x2, y+height-1, style); x2 = x2 + 1; for scene in self.scenes.iter() { - let label = format!("{}", &scene.name); - let mut x3 = label.len() as u16; - label.blit(self.buf, self.area.x + x2, self.area.y, Some(Style::default().bold())); + let mut x3 = 10.max(scene.name.len() as u16); + scene.name.blit(self.buf, x + x2, y, Some(Style::default().bold())); for (i, clip) in scene.clips.iter().enumerate() { if let Some(clip) = clip { if let Some(phrase) = self.tracks[i].phrases.get(*clip) { let label = format!("{}", &phrase.name); - label.blit(self.buf, self.area.x + x2, self.area.y + 1 + i as u16, None); + label.blit(self.buf, x + x2, y + 1 + i as u16, None); x3 = x3.max(label.len() as u16) } } } x2 = x2 + x3; - "╷".blit(self.buf, self.area.x + x2, self.area.y, style); - for y in self.area.y+1..self.area.y+self.area.height-1 { - "┊".blit(self.buf, self.area.x + x2, y, style); + "╷".blit(self.buf, x + x2, y, style); + for y in y+1..y+height-1 { + "┊".blit(self.buf, x + x2, y, style); } - //"╵".blit(self.buf, self.area.x + x2, self.area.y+self.area.height-1, style); + //"╵".blit(self.buf, x + x2, y+height-1, style); x2 = x2 + 1; } if self.focused { - HELP.blit(self.buf, self.area.x + 2, self.area.y + self.area.height - 1, Some(Style::default().dim())); + HELP.blit(self.buf, x + 2, y + height - 1, Some(Style::default().dim())); } Ok(self.area) } - - pub fn draw_vertical (&mut self) -> Usually { +} +pub struct SceneGridViewVertical<'a> { + pub buf: &'a mut Buffer, + pub area: Rect, + pub scenes: &'a[Scene], + pub tracks: &'a[Track], + pub cursor: &'a(usize, usize), + pub focused: bool +} +impl<'a> SceneGridViewVertical<'a> { + pub fn size (&self) -> (u16, u16) { + unimplemented!(); + } + pub fn draw (&mut self) -> Usually { let width = self.area.width.min(4 + HELP.len() as u16); self.area.height = self.scenes.len() as u16 + 2; //self.area.x = self.area.x + self.area.width.saturating_sub(width) / 2; @@ -120,9 +114,8 @@ impl<'a> SceneGridView<'a> { if x >= self.area.x + self.area.width { break } - title.blit( - self.buf, x+1, y, Some(self.highlight(i == self.cursor.0).bold()) - ); + let style = Some(highlight(self.focused, i == self.cursor.0).bold()); + title.blit(self.buf, x+1, y, style); if i == 0 { self.scenes(x+1, y + 1); } else if i < columns.len() { @@ -136,7 +129,6 @@ impl<'a> SceneGridView<'a> { } Ok(self.area) } - fn track_names (&self) -> Vec<&'a str> { let mut track_names = vec!["Mix"]; for track in self.tracks.iter() { @@ -146,7 +138,10 @@ impl<'a> SceneGridView<'a> { } fn track_widths (&self) -> Vec { - self.track_names().iter().map(|name|(name.len() as u16).max(10) + 3).collect() + self.track_names() + .iter() + .map(|name|(name.len() as u16).max(10) + 3) + .collect() } fn scenes (&mut self, x: u16, y: u16) -> u16 { @@ -158,18 +153,23 @@ impl<'a> SceneGridView<'a> { if y + index as u16 >= self.area.height { break } - if let Some(scene) = self.scenes.get(index) { - let style = Some(self.highlight( - (0 == self.cursor.0) && (index + 1 == self.cursor.1) - ).bold()); - "⯈".blit(self.buf, x, y + index as u16, style); - scene.name.blit(self.buf, x+1, y + index as u16, style); - } + self.scene(x, y + index as u16, index); index = index + 1; } index as u16 } + fn scene (&mut self, x: u16, y: u16, index: usize) { + if let Some(scene) = self.scenes.get(index) { + let style = Some(highlight( + self.focused, + (0 == self.cursor.0) && (index + 1 == self.cursor.1) + ).bold()); + "⯈".blit(self.buf, x, y, style); + scene.name.blit(self.buf, x + 1, y, style); + } + } + fn clips (&mut self, x: u16, y: u16, track: usize) -> u16 { let mut index = 0; loop { @@ -179,53 +179,58 @@ impl<'a> SceneGridView<'a> { if y + index as u16 >= self.area.height { break } - if let Some(scene) = self.scenes.get(index) { - let hi = (track + 1 == self.cursor.0) && - (index + 1 == self.cursor.1); - let style = Some(self.highlight(hi)); - let clip = scene.clips.get(track); - let index = index as u16; - let label = if let Some(Some(clip)) = clip { - if let Some(phrase) = self.tracks[track].phrases.get(*clip) { - format!("⯈{}", phrase.name) - } else { - format!("????") - } - } else { - format!(" ·········") - }; - label.blit(self.buf, x, y + index, style); - } + self.clip(x, y, track, index); index = index + 1; } - //let hi = (track + 1 == self.cursor.0) && - //(self.scenes.len() + 1 == self.cursor.1); - //"[Add clip…]".blit(self.buf, x, y + index as u16, Some(if hi { - //self.highlight(true) - //} else { - //Style::default().dim() - //})); index as u16 } - fn highlight (&self, highlight: bool) -> Style { - if highlight { - if self.focused { - Style::default().green().not_dim() + fn clip (&mut self, x: u16, y: u16, track: usize, index: usize) { + if let Some(scene) = self.scenes.get(index) { + let hi = (track + 1 == self.cursor.0) && + (index + 1 == self.cursor.1); + let style = Some(highlight(self.focused, hi)); + let clip = scene.clips.get(track); + let index = index as u16; + let label = if let Some(Some(clip)) = clip { + if let Some(phrase) = self.tracks[track].phrases.get(*clip) { + format!("⯈{}", phrase.name) + } else { + format!("????") + } } else { - Style::default().green().dim() - } - } else { - Style::default() + format!(" ·········") + }; + label.blit(self.buf, x, y + index, style); } } - fn separator_v (&mut self, x: u16, highlight: bool) { - let style = Some(self.highlight(highlight)); + fn separator_v (&mut self, x: u16, hi: bool) { + let style = Some(highlight(self.focused, hi)); for y in self.area.y+1..self.area.y+self.area.height-1 { "┊".blit(self.buf, x, y, style); } } + fn longest_scene_name (&self) -> u16 { + let mut w = 3u16; + for scene in self.scenes.iter() { + w = w.max(scene.name.len() as u16); + } + w + } + } const HELP: &'static str = "[C-t] Add track [C-a] Add scene [v] Show/hide track"; + +fn highlight (focused: bool, highlight: bool) -> Style { + if highlight { + if focused { + Style::default().green().not_dim() + } else { + Style::default().green().dim() + } + } else { + Style::default() + } +}