From 0530e43a2ff93dab36be674fa5b4521db07d5a3f Mon Sep 17 00:00:00 2001 From: unspeaker Date: Fri, 27 Dec 2024 09:05:33 +0100 Subject: [PATCH] Phrase -> MidiClip, PhraseEdit -> MidiEdit --- crates/tek/src/midi.rs | 14 +++--- crates/tek/src/midi/midi_clip.rs | 24 +++++----- crates/tek/src/midi/midi_launch.rs | 10 ++-- crates/tek/src/midi/midi_play.rs | 4 +- crates/tek/src/midi/midi_pool.rs | 12 ++--- crates/tek/src/tui/app_arranger.rs | 8 ++-- crates/tek/src/tui/app_sequencer.rs | 10 ++-- crates/tek/src/tui/arranger_command.rs | 4 +- crates/tek/src/tui/arranger_scene.rs | 6 +-- crates/tek/src/tui/arranger_v/v_clips.rs | 2 +- crates/tek/src/tui/phrase_editor.rs | 58 ++++++++++++------------ crates/tek/src/tui/piano_h.rs | 16 +++---- crates/tek/src/tui/pool.rs | 16 +++---- crates/tek/src/tui/status/status_edit.rs | 4 +- 14 files changed, 94 insertions(+), 94 deletions(-) diff --git a/crates/tek/src/midi.rs b/crates/tek/src/midi.rs index e0e4672b..4ca9200b 100644 --- a/crates/tek/src/midi.rs +++ b/crates/tek/src/midi.rs @@ -80,9 +80,9 @@ pub struct MidiPlayer { /// State of clock and playhead pub(crate) clock: ClockModel, /// Start time and phrase being played - pub(crate) play_phrase: Option<(Moment, Option>>)>, + pub(crate) play_phrase: Option<(Moment, Option>>)>, /// Start time and next phrase - pub(crate) next_phrase: Option<(Moment, Option>>)>, + pub(crate) next_phrase: Option<(Moment, Option>>)>, /// Play input through output. pub(crate) monitoring: bool, /// Write input to sequence. @@ -125,7 +125,7 @@ from!(|clock: &ClockModel| MidiPlayer = Self { notes_in: RwLock::new([false;128]).into(), notes_out: RwLock::new([false;128]).into(), }); -from!(|state: (&ClockModel, &Arc>)|MidiPlayer = { +from!(|state: (&ClockModel, &Arc>)|MidiPlayer = { let (clock, phrase) = state; let mut model = Self::from(clock); model.play_phrase = Some((Moment::zero(&clock.timebase), Some(phrase.clone()))); @@ -228,16 +228,16 @@ impl HasPlayPhrase for MidiPlayer { fn reset_mut (&mut self) -> &mut bool { &mut self.reset } - fn play_phrase (&self) -> &Option<(Moment, Option>>)> { + fn play_phrase (&self) -> &Option<(Moment, Option>>)> { &self.play_phrase } - fn play_phrase_mut (&mut self) -> &mut Option<(Moment, Option>>)> { + fn play_phrase_mut (&mut self) -> &mut Option<(Moment, Option>>)> { &mut self.play_phrase } - fn next_phrase (&self) -> &Option<(Moment, Option>>)> { + fn next_phrase (&self) -> &Option<(Moment, Option>>)> { &self.next_phrase } - fn next_phrase_mut (&mut self) -> &mut Option<(Moment, Option>>)> { + fn next_phrase_mut (&mut self) -> &mut Option<(Moment, Option>>)> { &mut self.next_phrase } } diff --git a/crates/tek/src/midi/midi_clip.rs b/crates/tek/src/midi/midi_clip.rs index 1c1f66dd..2ee1c863 100644 --- a/crates/tek/src/midi/midi_clip.rs +++ b/crates/tek/src/midi/midi_clip.rs @@ -1,20 +1,20 @@ use crate::*; -pub trait HasPhrase { - fn phrase (&self) -> &Arc>; +pub trait HasMidiClip { + fn phrase (&self) -> &Arc>; } #[macro_export] macro_rules! has_phrase { (|$self:ident:$Struct:ident$(<$($L:lifetime),*$($T:ident$(:$U:path)?),*>)?|$cb:expr) => { - impl $(<$($L),*$($T $(: $U)?),*>)? HasPhrase for $Struct $(<$($L),*$($T),*>)? { - fn phrase (&$self) -> &Arc> { &$cb } + impl $(<$($L),*$($T $(: $U)?),*>)? HasMidiClip for $Struct $(<$($L),*$($T),*>)? { + fn phrase (&$self) -> &Arc> { &$cb } } } } /// A MIDI sequence. #[derive(Debug, Clone)] -pub struct Phrase { +pub struct MidiClip { pub uuid: uuid::Uuid, /// Name of phrase pub name: String, @@ -23,7 +23,7 @@ pub struct Phrase { /// Length of phrase in pulses pub length: usize, /// Notes in phrase - pub notes: PhraseData, + pub notes: MidiData, /// Whether to loop the phrase or play it once pub looped: bool, /// Start of loop @@ -37,14 +37,14 @@ pub struct Phrase { } /// MIDI message structural -pub type PhraseData = Vec>; +pub type MidiData = Vec>; -impl Phrase { +impl MidiClip { pub fn new ( name: impl AsRef, looped: bool, length: usize, - notes: Option, + notes: Option, color: Option, ) -> Self { Self { @@ -86,7 +86,7 @@ impl Phrase { } } -impl Default for Phrase { +impl Default for MidiClip { fn default () -> Self { Self::new( "Stop", @@ -101,10 +101,10 @@ impl Default for Phrase { } } -impl PartialEq for Phrase { +impl PartialEq for MidiClip { fn eq (&self, other: &Self) -> bool { self.uuid == other.uuid } } -impl Eq for Phrase {} +impl Eq for MidiClip {} diff --git a/crates/tek/src/midi/midi_launch.rs b/crates/tek/src/midi/midi_launch.rs index e680601a..2acabd4a 100644 --- a/crates/tek/src/midi/midi_launch.rs +++ b/crates/tek/src/midi/midi_launch.rs @@ -3,10 +3,10 @@ use crate::*; pub trait HasPlayPhrase: HasClock { fn reset (&self) -> bool; fn reset_mut (&mut self) -> &mut bool; - fn play_phrase (&self) -> &Option<(Moment, Option>>)>; - fn play_phrase_mut (&mut self) -> &mut Option<(Moment, Option>>)>; - fn next_phrase (&self) -> &Option<(Moment, Option>>)>; - fn next_phrase_mut (&mut self) -> &mut Option<(Moment, Option>>)>; + fn play_phrase (&self) -> &Option<(Moment, Option>>)>; + fn play_phrase_mut (&mut self) -> &mut Option<(Moment, Option>>)>; + fn next_phrase (&self) -> &Option<(Moment, Option>>)>; + fn next_phrase_mut (&mut self) -> &mut Option<(Moment, Option>>)>; fn pulses_since_start (&self) -> Option { if let Some((started, Some(_))) = self.play_phrase().as_ref() { let elapsed = self.clock().playhead.pulse.get() - started.pulse.get(); @@ -25,7 +25,7 @@ pub trait HasPlayPhrase: HasClock { None } } - fn enqueue_next (&mut self, phrase: Option<&Arc>>) { + fn enqueue_next (&mut self, phrase: Option<&Arc>>) { let start = self.clock().next_launch_pulse() as f64; let instant = Moment::from_pulse(&self.clock().timebase(), start); let phrase = phrase.map(|p|p.clone()); diff --git a/crates/tek/src/midi/midi_play.rs b/crates/tek/src/midi/midi_play.rs index 8331d30c..5452c7c0 100644 --- a/crates/tek/src/midi/midi_play.rs +++ b/crates/tek/src/midi/midi_play.rs @@ -66,7 +66,7 @@ pub trait MidiPlaybackApi: HasPlayPhrase + HasClock + HasMidiOuts { note_buf: &mut Vec, out: &mut [Vec>], started: &Moment, - phrase: &Option>> + phrase: &Option>> ) -> bool { // First sample to populate. Greater than 0 means that the first // pulse of the phrase falls somewhere in the middle of the chunk. @@ -97,7 +97,7 @@ pub trait MidiPlaybackApi: HasPlayPhrase + HasClock + HasMidiOuts { } fn play_pulse ( - phrase: &RwLock, + phrase: &RwLock, pulse: usize, sample: usize, note_buf: &mut Vec, diff --git a/crates/tek/src/midi/midi_pool.rs b/crates/tek/src/midi/midi_pool.rs index 555059be..f69d0027 100644 --- a/crates/tek/src/midi/midi_pool.rs +++ b/crates/tek/src/midi/midi_pool.rs @@ -1,22 +1,22 @@ use crate::*; pub trait HasPhrases { - fn phrases (&self) -> &Vec>>; - fn phrases_mut (&mut self) -> &mut Vec>>; + fn phrases (&self) -> &Vec>>; + fn phrases_mut (&mut self) -> &mut Vec>>; } #[macro_export] macro_rules! has_phrases { (|$self:ident:$Struct:ident$(<$($L:lifetime),*$($T:ident$(:$U:path)?),*>)?|$cb:expr) => { impl $(<$($L),*$($T $(: $U)?),*>)? HasPhrases for $Struct $(<$($L),*$($T),*>)? { - fn phrases (&$self) -> &Vec>> { &$cb } - fn phrases_mut (&mut $self) -> &mut Vec>> { &mut$cb } + fn phrases (&$self) -> &Vec>> { &$cb } + fn phrases_mut (&mut $self) -> &mut Vec>> { &mut$cb } } } } #[derive(Clone, Debug, PartialEq)] pub enum PhrasePoolCommand { - Add(usize, Phrase), + Add(usize, MidiClip), Delete(usize), Swap(usize, usize), Import(usize, PathBuf), @@ -62,7 +62,7 @@ impl Command for PhrasePoolCommand { } } } - let mut phrase = Phrase::new("imported", true, t as usize + 1, None, None); + let mut phrase = MidiClip::new("imported", true, t as usize + 1, None, None); for event in events.iter() { phrase.notes[event.0 as usize].push(event.2); } diff --git a/crates/tek/src/tui/app_arranger.rs b/crates/tek/src/tui/app_arranger.rs index fe3f91bd..9866c45a 100644 --- a/crates/tek/src/tui/app_arranger.rs +++ b/crates/tek/src/tui/app_arranger.rs @@ -13,7 +13,7 @@ pub struct ArrangerTui { pub size: Measure, pub note_buf: Vec, pub midi_buf: Vec>>, - pub editor: PhraseEditorModel, + pub editor: MidiEditorModel, pub perf: PerfModel, } impl ArrangerTui { @@ -40,7 +40,7 @@ impl ArrangerTui { }; Ok(()) } - pub fn selected_phrase (&self) -> Option>> { + pub fn selected_phrase (&self) -> Option>> { self.selected_scene()?.clips.get(self.selected.track()?)?.clone() } pub fn toggle_loop (&mut self) { @@ -61,7 +61,7 @@ impl ArrangerTui { } from_jack!(|jack| ArrangerTui { let clock = ClockModel::from(jack); - let phrase = Arc::new(RwLock::new(Phrase::new( + let phrase = Arc::new(RwLock::new(MidiClip::new( "New", true, 4 * clock.timebase.ppq.get() as usize, None, Some(ItemColor::random().into()) ))); @@ -97,7 +97,7 @@ render!(|self: ArrangerTui|{ let pool_size = if self.phrases.visible { self.splits[1] } else { 0 }; let with_pool = |x|Split::left(false, pool_size, PoolView(&self.phrases), x); let status = ArrangerStatus::from(self); - let with_editbar = |x|Tui::split_n(false, 3, PhraseEditStatus(&self.editor), x); + let with_editbar = |x|Tui::split_n(false, 3, MidiEditStatus(&self.editor), x); let with_status = |x|Tui::split_n(false, 2, status, x); let with_size = |x|lay!([&self.size, x]); let arranger = ||lay!(|add|{ diff --git a/crates/tek/src/tui/app_sequencer.rs b/crates/tek/src/tui/app_sequencer.rs index 97ec300f..9657cfb2 100644 --- a/crates/tek/src/tui/app_sequencer.rs +++ b/crates/tek/src/tui/app_sequencer.rs @@ -10,7 +10,7 @@ pub struct SequencerTui { pub(crate) clock: ClockModel, pub(crate) phrases: PoolModel, pub(crate) player: MidiPlayer, - pub(crate) editor: PhraseEditorModel, + pub(crate) editor: MidiEditorModel, pub(crate) size: Measure, pub(crate) status: bool, pub(crate) note_buf: Vec, @@ -19,14 +19,14 @@ pub struct SequencerTui { } from_jack!(|jack|SequencerTui { let clock = ClockModel::from(jack); - let phrase = Arc::new(RwLock::new(Phrase::new( + let phrase = Arc::new(RwLock::new(MidiClip::new( "New", true, 4 * clock.timebase.ppq.get() as usize, None, Some(ItemColor::random().into()) ))); Self { _jack: jack.clone(), phrases: PoolModel::from(&phrase), - editor: PhraseEditorModel::from(&phrase), + editor: MidiEditorModel::from(&phrase), player: MidiPlayer::from((&clock, &phrase)), size: Measure::new(), midi_buf: vec![vec![];65536], @@ -44,7 +44,7 @@ render!(|self: SequencerTui|{ let with_pool = move|x|Tui::split_w(false, pool_w, pool, x); let status = SequencerStatus::from(self); let with_status = |x|Tui::split_n(false, if self.status { 2 } else { 0 }, status, x); - let with_editbar = |x|Tui::split_n(false, 3, PhraseEditStatus(&self.editor), x); + let with_editbar = |x|Tui::split_n(false, 3, MidiEditStatus(&self.editor), x); let with_size = |x|lay!([self.size, x]); let editor = with_editbar(with_pool(Fill::wh(&self.editor))); let color = self.player.play_phrase().as_ref().map(|(_,p)| @@ -85,7 +85,7 @@ handle!(|self:SequencerTui,input|SequencerCommand::execute_with_state(self, Clock(ClockCommand), Phrases(PoolCommand), Editor(PhraseCommand), - Enqueue(Option>>), + Enqueue(Option>>), } input_to_command!(SequencerCommand: |state: SequencerTui, input|match input.event() { // TODO: k: toggle on-screen keyboard diff --git a/crates/tek/src/tui/arranger_command.rs b/crates/tek/src/tui/arranger_command.rs index 59370065..731adc59 100644 --- a/crates/tek/src/tui/arranger_command.rs +++ b/crates/tek/src/tui/arranger_command.rs @@ -39,9 +39,9 @@ pub enum ArrangerSceneCommand { #[derive(Clone, Debug)] pub enum ArrangerClipCommand { Get(usize, usize), - Put(usize, usize, Option>>), + Put(usize, usize, Option>>), Enqueue(usize, usize), - Edit(Option>>), + Edit(Option>>), SetLoop(usize, usize, bool), SetColor(usize, usize, ItemPalette), } diff --git a/crates/tek/src/tui/arranger_scene.rs b/crates/tek/src/tui/arranger_scene.rs index 2bdb3a48..67eebc69 100644 --- a/crates/tek/src/tui/arranger_scene.rs +++ b/crates/tek/src/tui/arranger_scene.rs @@ -30,7 +30,7 @@ impl ArrangerTui { /// Name of scene pub(crate) name: Arc>, /// Clips in scene, one per track - pub(crate) clips: Vec>>>, + pub(crate) clips: Vec>>>, /// Identifying color of scene pub(crate) color: ItemPalette, } @@ -38,7 +38,7 @@ impl ArrangerScene { pub fn name (&self) -> &Arc> { &self.name } - pub fn clips (&self) -> &Vec>>> { + pub fn clips (&self) -> &Vec>>> { &self.clips } pub fn color (&self) -> ItemPalette { @@ -85,7 +85,7 @@ impl ArrangerScene { None => true }) } - pub fn clip (&self, index: usize) -> Option<&Arc>> { + pub fn clip (&self, index: usize) -> Option<&Arc>> { match self.clips().get(index) { Some(Some(clip)) => Some(clip), _ => None } } } diff --git a/crates/tek/src/tui/arranger_v/v_clips.rs b/crates/tek/src/tui/arranger_v/v_clips.rs index 41cd38e2..4aee54a9 100644 --- a/crates/tek/src/tui/arranger_v/v_clips.rs +++ b/crates/tek/src/tui/arranger_v/v_clips.rs @@ -41,7 +41,7 @@ impl<'a> ArrangerVClips<'a> { Fixed::wh(w, h, Layers::new(move |add|{ let mut bg = TuiTheme::border_bg(); if let Some(Some(phrase)) = scene.clips.get(index) { - let name = &(phrase as &Arc>).read().unwrap().name; + let name = &(phrase as &Arc>).read().unwrap().name; let name = format!("{}", name); let max_w = name.len().min((w as usize).saturating_sub(2)); let color = phrase.read().unwrap().color; diff --git a/crates/tek/src/tui/phrase_editor.rs b/crates/tek/src/tui/phrase_editor.rs index 01492997..5ec099a2 100644 --- a/crates/tek/src/tui/phrase_editor.rs +++ b/crates/tek/src/tui/phrase_editor.rs @@ -3,13 +3,13 @@ use KeyCode::{Char, Up, Down, Left, Right, Enter}; use PhraseCommand::*; pub trait HasEditor { - fn editor (&self) -> &PhraseEditorModel; + fn editor (&self) -> &MidiEditorModel; } #[macro_export] macro_rules! has_editor { (|$self:ident:$Struct:ident$(<$($L:lifetime),*$($T:ident$(:$U:path)?),*>)?|$cb:expr) => { impl $(<$($L),*$($T $(: $U)?),*>)? HasEditor for $Struct $(<$($L),*$($T),*>)? { - fn editor (&$self) -> &PhraseEditorModel { &$cb } + fn editor (&$self) -> &MidiEditorModel { &$cb } } } } @@ -26,11 +26,11 @@ pub enum PhraseCommand { SetTimeScroll(usize), SetTimeZoom(usize), SetTimeLock(bool), - Show(Option>>), + Show(Option>>), } -event_map_input_to_command!(Tui: PhraseEditorModel: PhraseCommand: PhraseEditorModel::KEYS); +event_map_input_to_command!(Tui: MidiEditorModel: PhraseCommand: MidiEditorModel::KEYS); -impl PhraseEditorModel { +impl MidiEditorModel { const KEYS: [(TuiEvent, &'static dyn Fn(&Self)->PhraseCommand);31] = [ (kexp!(Ctrl-Alt-Up), &|s: &Self|SetNoteScroll(s.note_point() + 3)), (kexp!(Ctrl-Alt-Down), &|s: &Self|SetNoteScroll(s.note_point().saturating_sub(3))), @@ -71,8 +71,8 @@ impl PhraseEditorModel { } } -impl Command for PhraseCommand { - fn execute (self, state: &mut PhraseEditorModel) -> Perhaps { +impl Command for PhraseCommand { + fn execute (self, state: &mut MidiEditorModel) -> Perhaps { use PhraseCommand::*; match self { Show(phrase) => { state.set_phrase(phrase.as_ref()); }, @@ -92,13 +92,13 @@ impl Command for PhraseCommand { } /// Contains state for viewing and editing a phrase -pub struct PhraseEditorModel { +pub struct MidiEditorModel { /// Renders the phrase pub mode: Box, pub size: Measure } -impl Default for PhraseEditorModel { +impl Default for MidiEditorModel { fn default () -> Self { let mut mode = Box::new(PianoHorizontal::new(None)); mode.redraw(); @@ -106,28 +106,28 @@ impl Default for PhraseEditorModel { } } -has_size!(|self:PhraseEditorModel|&self.size); -render!(|self: PhraseEditorModel|{ +has_size!(|self:MidiEditorModel|&self.size); +render!(|self: MidiEditorModel|{ self.autoscroll(); self.autozoom(); &self.mode }); -//render!(|self: PhraseEditorModel|lay!(|add|{add(&self.size)?;add(self.mode)}));//bollocks +//render!(|self: MidiEditorModel|lay!(|add|{add(&self.size)?;add(self.mode)}));//bollocks pub trait PhraseViewMode: Render + HasSize + MidiRange + MidiPoint + Debug + Send + Sync { - fn buffer_size (&self, phrase: &Phrase) -> (usize, usize); + fn buffer_size (&self, phrase: &MidiClip) -> (usize, usize); fn redraw (&mut self); - fn phrase (&self) -> &Option>>; - fn phrase_mut (&mut self) -> &mut Option>>; - fn set_phrase (&mut self, phrase: Option<&Arc>>) { + fn phrase (&self) -> &Option>>; + fn phrase_mut (&mut self) -> &mut Option>>; + fn set_phrase (&mut self, phrase: Option<&Arc>>) { *self.phrase_mut() = phrase.map(|p|p.clone()); self.redraw(); } } -impl MidiView for PhraseEditorModel {} +impl MidiView for MidiEditorModel {} -impl MidiRange for PhraseEditorModel { +impl MidiRange for MidiEditorModel { fn time_len (&self) -> &AtomicUsize { self.mode.time_len() } fn time_zoom (&self) -> &AtomicUsize { self.mode.time_zoom() } fn time_lock (&self) -> &AtomicBool { self.mode.time_lock() } @@ -137,7 +137,7 @@ impl MidiRange for PhraseEditorModel { fn time_axis (&self) -> &AtomicUsize { self.mode.time_axis() } } -impl MidiPoint for PhraseEditorModel { +impl MidiPoint for MidiEditorModel { fn note_len (&self) -> usize { self.mode.note_len()} fn set_note_len (&self, x: usize) { self.mode.set_note_len(x) } fn note_point (&self) -> usize { self.mode.note_point() } @@ -146,25 +146,25 @@ impl MidiPoint for PhraseEditorModel { fn set_time_point (&self, x: usize) { self.mode.set_time_point(x) } } -impl PhraseViewMode for PhraseEditorModel { - fn buffer_size (&self, phrase: &Phrase) -> (usize, usize) { +impl PhraseViewMode for MidiEditorModel { + fn buffer_size (&self, phrase: &MidiClip) -> (usize, usize) { self.mode.buffer_size(phrase) } fn redraw (&mut self) { self.mode.redraw() } - fn phrase (&self) -> &Option>> { + fn phrase (&self) -> &Option>> { self.mode.phrase() } - fn phrase_mut (&mut self) -> &mut Option>> { + fn phrase_mut (&mut self) -> &mut Option>> { self.mode.phrase_mut() } - fn set_phrase (&mut self, phrase: Option<&Arc>>) { + fn set_phrase (&mut self, phrase: Option<&Arc>>) { self.mode.set_phrase(phrase) } } -impl PhraseEditorModel { +impl MidiEditorModel { /// Put note at current position pub fn put_note (&mut self, advance: bool) { let mut redraw = false; @@ -197,22 +197,22 @@ impl PhraseEditorModel { } } -from!(|phrase: &Arc>|PhraseEditorModel = { +from!(|phrase: &Arc>|MidiEditorModel = { let mut model = Self::from(Some(phrase.clone())); model.redraw(); model }); -from!(|phrase: Option>>|PhraseEditorModel = { +from!(|phrase: Option>>|MidiEditorModel = { let mut model = Self::default(); *model.phrase_mut() = phrase; model.redraw(); model }); -impl std::fmt::Debug for PhraseEditorModel { +impl std::fmt::Debug for MidiEditorModel { fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { - f.debug_struct("PhraseEditorModel") + f.debug_struct("MidiEditorModel") .field("mode", &self.mode) .finish() } diff --git a/crates/tek/src/tui/piano_h.rs b/crates/tek/src/tui/piano_h.rs index cde739df..c8c3f774 100644 --- a/crates/tek/src/tui/piano_h.rs +++ b/crates/tek/src/tui/piano_h.rs @@ -12,7 +12,7 @@ pub(crate) fn note_y_iter (note_lo: usize, note_hi: usize, y0: u16) -> impl Iter /// A phrase, rendered as a horizontal piano roll. pub struct PianoHorizontal { - phrase: Option>>, + phrase: Option>>, /// Buffer where the whole phrase is rerendered on change buffer: BigBuffer, /// Size of actual notes area @@ -26,7 +26,7 @@ pub struct PianoHorizontal { } impl PianoHorizontal { - pub fn new (phrase: Option<&Arc>>) -> Self { + pub fn new (phrase: Option<&Arc>>) -> Self { let size = Measure::new(); let mut range = MidiRangeModel::from((24, true)); range.time_axis = size.x.clone(); @@ -64,7 +64,7 @@ render!(|self: PianoHorizontal|{ impl PianoHorizontal { /// Draw the piano roll foreground using full blocks on note on and half blocks on legato: █▄ █▄ █▄ - fn draw_bg (buf: &mut BigBuffer, phrase: &Phrase, zoom: usize, note_len: usize) { + fn draw_bg (buf: &mut BigBuffer, phrase: &MidiClip, zoom: usize, note_len: usize) { for (y, note) in (0..127).rev().enumerate() { for (x, time) in (0..buf.width).map(|x|(x, x*zoom)) { let cell = buf.get_mut(x, y).unwrap(); @@ -85,7 +85,7 @@ impl PianoHorizontal { } } /// Draw the piano roll background using full blocks on note on and half blocks on legato: █▄ █▄ █▄ - fn draw_fg (buf: &mut BigBuffer, phrase: &Phrase, zoom: usize) { + fn draw_fg (buf: &mut BigBuffer, phrase: &MidiClip, zoom: usize) { let style = Style::default().fg(phrase.color.base.rgb);//.bg(Color::Rgb(0, 0, 0)); let mut notes_on = [false;128]; for (x, time_start) in (0..phrase.length).step_by(zoom).enumerate() { @@ -142,14 +142,14 @@ impl MidiPoint for PianoHorizontal { fn set_time_point (&self, x: usize) { self.point.set_time_point(x) } } impl PhraseViewMode for PianoHorizontal { - fn phrase (&self) -> &Option>> { + fn phrase (&self) -> &Option>> { &self.phrase } - fn phrase_mut (&mut self) -> &mut Option>> { + fn phrase_mut (&mut self) -> &mut Option>> { &mut self.phrase } /// Determine the required space to render the phrase. - fn buffer_size (&self, phrase: &Phrase) -> (usize, usize) { + fn buffer_size (&self, phrase: &MidiClip) -> (usize, usize) { (phrase.length / self.range.time_zoom().get(), 128) } fn redraw (&mut self) { @@ -168,7 +168,7 @@ impl PhraseViewMode for PianoHorizontal { }; self.buffer = buffer } - fn set_phrase (&mut self, phrase: Option<&Arc>>) { + fn set_phrase (&mut self, phrase: Option<&Arc>>) { *self.phrase_mut() = phrase.map(|p|p.clone()); self.color = phrase.map(|p|p.read().unwrap().color.clone()) .unwrap_or(ItemPalette::from(ItemColor::from(TuiTheme::g(64)))); diff --git a/crates/tek/src/tui/pool.rs b/crates/tek/src/tui/pool.rs index 91a87d5f..57cff863 100644 --- a/crates/tek/src/tui/pool.rs +++ b/crates/tek/src/tui/pool.rs @@ -12,7 +12,7 @@ use FileBrowserCommand as Browse; pub struct PoolModel { pub(crate) visible: bool, /// Collection of phrases - pub(crate) phrases: Vec>>, + pub(crate) phrases: Vec>>, /// Selected phrase pub(crate) phrase: AtomicUsize, /// Mode switch @@ -149,10 +149,10 @@ fn to_phrases_command (state: &PoolModel, input: &TuiInput) -> Option Cmd::Phrase(Pool::Add(count, Phrase::new( + key_pat!(Char('a')) | key_pat!(Shift-Char('A')) => Cmd::Phrase(Pool::Add(count, MidiClip::new( String::from("(new)"), true, 4 * PPQ, None, Some(ItemPalette::random()) ))), - key_pat!(Char('i')) => Cmd::Phrase(Pool::Add(index + 1, Phrase::new( + key_pat!(Char('i')) => Cmd::Phrase(Pool::Add(index + 1, MidiClip::new( String::from("(new)"), true, 4 * PPQ, None, Some(ItemPalette::random()) ))), key_pat!(Char('d')) | key_pat!(Shift-Char('D')) => { @@ -167,7 +167,7 @@ impl Default for PoolModel { fn default () -> Self { Self { visible: true, - phrases: vec![RwLock::new(Phrase::default()).into()], + phrases: vec![RwLock::new(MidiClip::default()).into()], phrase: 0.into(), scroll: 0, mode: None, @@ -175,7 +175,7 @@ impl Default for PoolModel { } } } -from!(|phrase:&Arc>|PoolModel = { +from!(|phrase:&Arc>|PoolModel = { let mut model = Self::default(); model.phrases.push(phrase.clone()); model.phrase.store(1, Relaxed); @@ -214,7 +214,7 @@ render!(|self: PoolView<'a>|{ Some(PoolMode::Export(_, ref file_picker)) => add(file_picker), _ => Ok(for (i, phrase) in phrases.iter().enumerate() { add(&lay!(|add|{ - let Phrase { ref name, color, length, .. } = *phrase.read().unwrap(); + let MidiClip { ref name, color, length, .. } = *phrase.read().unwrap(); let mut length = PhraseLength::new(length, None); if let Some(PoolMode::Length(phrase, new_length, focus)) = mode { if i == *phrase { @@ -267,7 +267,7 @@ impl PhraseSelector { // beats elapsed pub fn play_phrase (state: &T) -> Self { let (name, color) = if let Some((_, Some(phrase))) = state.play_phrase() { - let Phrase { ref name, color, .. } = *phrase.read().unwrap(); + let MidiClip { ref name, color, .. } = *phrase.read().unwrap(); (name.clone(), color) } else { ("".to_string(), ItemPalette::from(TuiTheme::g(64))) @@ -282,7 +282,7 @@ impl PhraseSelector { // beats until switchover pub fn next_phrase (state: &T) -> Self { let (time, name, color) = if let Some((t, Some(phrase))) = state.next_phrase() { - let Phrase { ref name, color, .. } = *phrase.read().unwrap(); + let MidiClip { ref name, color, .. } = *phrase.read().unwrap(); let time = { let target = t.pulse.get(); let current = state.clock().playhead.pulse.get(); diff --git a/crates/tek/src/tui/status/status_edit.rs b/crates/tek/src/tui/status/status_edit.rs index c45103d8..43263565 100644 --- a/crates/tek/src/tui/status/status_edit.rs +++ b/crates/tek/src/tui/status/status_edit.rs @@ -1,7 +1,7 @@ use crate::*; -pub struct PhraseEditStatus<'a>(pub &'a PhraseEditorModel); -render!(|self:PhraseEditStatus<'a>|{ +pub struct MidiEditStatus<'a>(pub &'a MidiEditorModel); +render!(|self:MidiEditStatus<'a>|{ let (color, name, length, looped) = if let Some(phrase) = self.0.phrase().as_ref().map(|p|p.read().unwrap()) { (phrase.color, phrase.name.clone(), phrase.length, phrase.looped) } else {