diff --git a/crates/tek_sequencer/src/main_sequencer.rs b/crates/tek_sequencer/src/main_sequencer.rs index 2cbcdf16..e96cf319 100644 --- a/crates/tek_sequencer/src/main_sequencer.rs +++ b/crates/tek_sequencer/src/main_sequencer.rs @@ -10,11 +10,11 @@ use tek_core::clap::{self, Parser}; #[command(version, about, long_about = None)] pub struct SequencerCli { /// Name of JACK client - #[arg(short, long)] name: Option, + #[arg(short, long)] name: Option, /// Pulses per quarter note (sequencer resolution; default: 96) - #[arg(short, long)] ppq: Option, + #[arg(short, long)] ppq: Option, /// Default phrase duration (in pulses; default: 4 * PPQ = 1 bar) - #[arg(short, long)] length: Option, + #[arg(short, long)] length: Option, /// Whether to include a transport toolbar (default: true) #[arg(short, long)] transport: Option } @@ -30,9 +30,10 @@ impl Sequencer { seq.ppq = ppq; } if let Some(length) = args.length { - if let Some(phrase) = seq.phrase.as_mut() { - phrase.write().unwrap().length = length; - } + // TODO FIXME WTF + //if let Some(phrase) = seq.phrase.as_mut() { + //phrase.write().unwrap().length = length; + //} } if args.transport == Some(true) { seq.transport = Some(Arc::new(RwLock::new(TransportToolbar::new(None)))); diff --git a/crates/tek_sequencer/src/sequencer.rs b/crates/tek_sequencer/src/sequencer.rs index 976b3b84..0d1b198c 100644 --- a/crates/tek_sequencer/src/sequencer.rs +++ b/crates/tek_sequencer/src/sequencer.rs @@ -452,7 +452,6 @@ pub struct Sequencer { pub mode: bool, pub focused: bool, pub entered: bool, - pub phrase: Option>>, pub transport: Option>>>, /// The full piano roll is rendered to this buffer pub buffer: BigBuffer, @@ -493,7 +492,6 @@ pub struct Sequencer { /// Highlight keys on piano roll. pub notes_out: [bool;128], } - impl Sequencer { pub fn new (name: &str) -> Self { Self { @@ -516,7 +514,6 @@ impl Sequencer { mode: false, keys_in: [false;128], keys_out: [false;128], - phrase: None, now: 0, ppq: 96, transport: None, @@ -620,7 +617,6 @@ impl Sequencer { write_midi_output(&mut out.writer(scope), &self.midi_out_buf, frames); } } - #[inline] fn process_monitor_event (&mut self, frame: usize, event: &LiveEvent, bytes: &[u8]) { match event { @@ -631,11 +627,9 @@ impl Sequencer { _ => {} } } - #[inline] fn write_to_output_buffer (&mut self, frame: usize, bytes: &[u8]) { self.midi_out_buf[frame].push(bytes.to_vec()); } - #[inline] fn process_monitor_message (&mut self, message: &MidiMessage) { match message { diff --git a/crates/tek_sequencer/src/sequencer_tui.rs b/crates/tek_sequencer/src/sequencer_tui.rs index 7675d5a8..dc515fcd 100644 --- a/crates/tek_sequencer/src/sequencer_tui.rs +++ b/crates/tek_sequencer/src/sequencer_tui.rs @@ -93,10 +93,12 @@ impl Handle for Arranger { // increment: use next clip here key!(KeyCode::Char('.')) => { self.phrase_next(); + self.show_phrase(); }, // decrement: use previous next clip here key!(KeyCode::Char(',')) => { self.phrase_prev(); + self.show_phrase(); }, // decrement: use previous clip here key!(KeyCode::Enter) => { @@ -164,13 +166,16 @@ impl<'a> Content for VerticalArranger<'a, Tui> { Layers::new(move |add|{ let rows: &[(usize, usize)] = rows.as_ref(); let cols: &[(usize, usize)] = cols.as_ref(); + let track_titles = row!((track, (w, _)) in tracks.iter().zip(cols) => (&track.name.read().unwrap().as_str() as &dyn Widget) .min_xy(*w as u16, 2).push_x(offset)); + let scene_name = |scene, playing: bool, height|row!( if playing { "▶ " } else { " " }, (scene as &Scene).name.read().unwrap().as_str(), ).fixed_xy(offset.saturating_sub(1), height); + let scene_clip = |scene, track: usize, w: u16, h: u16|Layers::new(move |add|{ let mut color = Color::Rgb(40, 50, 30); match (tracks.get(track), (scene as &Scene).clips.get(track)) { @@ -179,7 +184,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> { let name = &(phrase as &Arc>).read().unwrap().name; let name = name.read().unwrap(); let name = format!("{clip:02} {}", name); - add(&name.as_str().push_x(1))?; + add(&name.as_str().push_x(1).fixed_x(w))?; if (track as &Sequencer<_>).playing_phrase == Some(*clip) { color = COLOR_PLAYING } else { @@ -192,6 +197,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> { }; add(&Background(color)) }).fixed_xy(w, h); + let tracks_clips = col!((scene, (pulses, _)) in scenes.iter().zip(rows) => { let height = 1.max((pulses / 96) as u16); let playing = scene.is_playing(tracks); @@ -203,6 +209,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> { Ok(()) }).fixed_y(height) }); + add(&VerticalArrangerGrid(offset, &rows, &cols))?; add(&VerticalArrangerCursor(state.focused, state.selected, offset, &cols, &rows))?; add(&col!(track_titles, tracks_clips))?; @@ -644,21 +651,21 @@ impl Handle for ArrangerRenameModal { impl Sequencer { const H_KEYS_OFFSET: usize = 5; /// Select which pattern to display. This pre-renders it to the buffer at full resolution. - pub fn show (&mut self, phrase: Option<&Arc>>) -> Usually<()> { - self.phrase = phrase.map(Clone::clone); - if let Some(ref phrase) = self.phrase { + pub fn show (&mut self, index: Option) { + self.viewing_phrase = index; + if let Some(phrase) = index.map(|index|self.phrases.get(index)).flatten() { let width = usize::MAX.min(phrase.read().unwrap().length); let mut buffer = BigBuffer::new(width, 64); let phrase = phrase.read().unwrap(); - Self::fill_seq_bg(&mut buffer, phrase.length, self.ppq)?; - Self::fill_seq_fg(&mut buffer, &phrase)?; + Self::fill_seq_bg(&mut buffer, phrase.length, self.ppq); + Self::fill_seq_fg(&mut buffer, &phrase); self.buffer = buffer; } else { + self.viewing_phrase = None; self.buffer = Default::default(); } - Ok(()) } - fn fill_seq_bg (buf: &mut BigBuffer, length: usize, ppq: usize) -> Usually<()> { + fn fill_seq_bg (buf: &mut BigBuffer, length: usize, ppq: usize) { for x in 0..buf.width { if x as usize >= length { break @@ -684,9 +691,8 @@ impl Sequencer { }); } } - Ok(()) } - fn fill_seq_fg (buf: &mut BigBuffer, phrase: &Phrase) -> Usually<()> { + fn fill_seq_fg (buf: &mut BigBuffer, phrase: &Phrase) { let mut notes_on = [false;128]; for x in 0..buf.width { if x as usize >= phrase.length { @@ -731,7 +737,6 @@ impl Sequencer { } } } - Ok(()) } pub(crate) fn style_focus (&self) -> Option