From ea3edec96b7b4273f0ffc967c31cd47f52b74892 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sat, 5 Oct 2024 10:02:55 +0300 Subject: [PATCH] replace Phrase::looped with separate fields; draw them with backgrounds --- crates/tek_sequencer/src/sequencer.rs | 25 +++++++++++++-------- crates/tek_sequencer/src/sequencer_tui.rs | 27 +++++++++++++---------- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/crates/tek_sequencer/src/sequencer.rs b/crates/tek_sequencer/src/sequencer.rs index b0ebf36b..3dffe3e6 100644 --- a/crates/tek_sequencer/src/sequencer.rs +++ b/crates/tek_sequencer/src/sequencer.rs @@ -691,12 +691,14 @@ pub type PhraseData = Vec>; /// A MIDI sequence. #[derive(Debug)] pub struct Phrase { - pub name: Arc>, - pub length: usize, - pub notes: PhraseData, - pub looped: Option<(usize, usize)>, + pub name: Arc>, + pub length: usize, + pub notes: PhraseData, + pub loop_on: bool, + pub loop_start: usize, + pub loop_length: usize, /// All notes are displayed with minimum length - pub percussive: bool + pub percussive: bool, } impl Default for Phrase { fn default () -> Self { Self::new("", 0, None) } @@ -704,13 +706,18 @@ impl Default for Phrase { impl Phrase { pub fn new (name: &str, length: usize, notes: Option) -> Self { Self { - name: Arc::new(RwLock::new(name.into())), + name: Arc::new(RwLock::new(name.into())), length, - notes: notes.unwrap_or(vec![Vec::with_capacity(16);length]), - looped: Some((0, length)), - percussive: true, + notes: notes.unwrap_or(vec![Vec::with_capacity(16);length]), + loop_on: true, + loop_start: 0, + loop_length: length, + percussive: true, } } + pub fn toggle_loop (&mut self) { + self.loop_on = !self.loop_on; + } pub fn record_event (&mut self, pulse: usize, message: MidiMessage) { if pulse >= self.length { panic!("extend phrase first") diff --git a/crates/tek_sequencer/src/sequencer_tui.rs b/crates/tek_sequencer/src/sequencer_tui.rs index ee8f6e0e..78db48d8 100644 --- a/crates/tek_sequencer/src/sequencer_tui.rs +++ b/crates/tek_sequencer/src/sequencer_tui.rs @@ -122,8 +122,8 @@ impl Handle for Arranger { self.rename_selected(); }, // length: add a new scene - key!(KeyCode::Char('l')) => { - todo!(); + key!(KeyCode::Char('l')) => if let Some(phrase) = self.phrase() { + phrase.write().unwrap().toggle_loop() }, // color: set color of item at cursor key!(KeyCode::Char('c')) => { @@ -774,22 +774,25 @@ impl Sequencer { impl Content for Sequencer { type Engine = Tui; fn content (&self) -> impl Widget { + let field_bg = Color::Rgb(28, 35, 25); let toolbar = Stack::down(move|add|{ - add(&col!("Name:", self.name.read().unwrap().as_str()))?; + let name = format!("{:>9}", self.name.read().unwrap().as_str()); + add(&col!("Track:", TuiStyle::bg(name.as_str(), field_bg)))?; if let Some(phrase) = self.viewing_phrase .map(|index|self.phrases.get(index)) .flatten() { - let phrase = phrase.read().unwrap(); - let length = phrase.length; - let looped = phrase.looped; + let phrase = phrase.read().unwrap(); + let length = format!("{}q{}p", phrase.length / 96, phrase.length % 96); + let length = format!("{:>9}", &length); + let loop_on = format!("{:>9}", if phrase.loop_on { "on" } else { "off" }); + let loop_start = format!("{:>9}", phrase.loop_start); + let loop_end = format!("{:>9}", phrase.loop_length); add(&"")?; - add(&col!("Length: ", format!("{}q{}p", length / 96, length % 96).as_str()))?; - add(&"")?; - add(&col!("Loop [ ]", "From: ", " 1.1.1", "Length: ", " 1.0.0"))?; - add(&"")?; - add(&col!("Notes: ", "C#0-C#9 ", "[ /2 ]", "[ x2 ]", - "[ Rev ]", "[ Inv ]", "[ Dup ]"))?; + add(&col!("Length:", TuiStyle::bg(length.as_str(), field_bg)))?; + add(&col!("Loop:", TuiStyle::bg(loop_on.as_str(), field_bg)))?; + add(&col!("L. start:", TuiStyle::bg(loop_start.as_str(), field_bg)))?; + add(&col!("L. length:", TuiStyle::bg(loop_end.as_str(), field_bg)))?; } Ok(()) }).min_x(10);