diff --git a/crates/tek_sequencer/src/arranger.rs b/crates/tek_sequencer/src/arranger.rs index b5fd5f64..34c538c0 100644 --- a/crates/tek_sequencer/src/arranger.rs +++ b/crates/tek_sequencer/src/arranger.rs @@ -17,7 +17,16 @@ pub struct Arranger { } /// Sections in the arranger app that may be focused #[derive(Copy, Clone, PartialEq, Eq)] -pub enum ArrangerFocus { Transport, Arrangement, PhrasePool, PhraseEditor } +pub enum ArrangerFocus { + /// The transport (toolbar) is focused + Transport, + /// The arrangement (grid) is focused + Arrangement, + /// The phrase list (pool) is focused + PhrasePool, + /// The phrase editor (sequencer) is focused + PhraseEditor, +} /// Represents the tracks and scenes of the composition. pub struct Arrangement { /// Name of arranger @@ -76,7 +85,9 @@ pub enum ArrangementFocus { /// Display mode of arranger #[derive(PartialEq)] pub enum ArrangementViewMode { + /// Tracks are rows Horizontal, + /// Tracks are columns Vertical(usize), } /// Arrangement, rendered vertically (session/grid mode). @@ -88,10 +99,7 @@ pub struct HorizontalArranger<'a, E: Engine>( pub &'a Arrangement ); impl Arranger { - pub fn edit_phrase (&mut self) { - self.editor.phrase = self.arrangement.phrase().clone(); - self.focus(ArrangerFocus::PhraseEditor); - } + /// Toggle global play/pause pub fn toggle_play (&mut self) -> Perhaps { match self.transport { Some(ref mut transport) => { transport.write().unwrap().toggle_play()?; }, @@ -99,22 +107,26 @@ impl Arranger { } Ok(Some(true)) } + /// Focus the editor with the current phrase + pub fn edit_phrase (&mut self) { + self.editor.phrase = self.arrangement.phrase().clone(); + self.focus(ArrangerFocus::PhraseEditor); + } + /// Rename the selected track, scene, or clip pub fn rename_selected (&mut self) { - let Self { phrases, arrangement, .. } = self; - let Arrangement { selected, ref name, ref tracks, ref scenes, .. } = arrangement; + let Arrangement { selected, ref scenes, .. } = self.arrangement; match selected { - ArrangementFocus::Track(t) => { todo!("rename track"); }, - ArrangementFocus::Scene(s) => { todo!("rename scene"); }, - ArrangementFocus::Clip(t, s) => - if let Some(ref phrase) = scenes[*s].clips[*t] { - let index = self.phrases.read().unwrap().index_of(&*phrase.read().unwrap()); - if let Some(index) = index { - self.focus(ArrangerFocus::PhrasePool); - self.phrases.write().unwrap().phrase = index; - self.phrases.write().unwrap().begin_rename(); - } - }, - _ => {} + ArrangementFocus::Mix => {}, + ArrangementFocus::Track(_) => { todo!("rename track"); }, + ArrangementFocus::Scene(_) => { todo!("rename scene"); }, + ArrangementFocus::Clip(t, s) => if let Some(ref phrase) = scenes[s].clips[t] { + let index = self.phrases.read().unwrap().index_of(&*phrase.read().unwrap()); + if let Some(index) = index { + self.focus(ArrangerFocus::PhrasePool); + self.phrases.write().unwrap().phrase = index; + self.phrases.write().unwrap().begin_rename(); + } + }, } } } @@ -172,27 +184,27 @@ impl Arrangement { } pub fn delete (&mut self) { match self.selected { - ArrangementFocus::Track(t) => self.track_del(), - ArrangementFocus::Scene(s) => self.scene_del(), - ArrangementFocus::Clip(t, s) => self.phrase_del(), + ArrangementFocus::Track(_) => self.track_del(), + ArrangementFocus::Scene(_) => self.scene_del(), + ArrangementFocus::Clip(_, _) => self.phrase_del(), _ => {} } self.show_phrase() } pub fn increment (&mut self) { match self.selected { - ArrangementFocus::Track(t) => self.track_width_inc(), - ArrangementFocus::Scene(s) => self.scene_next(), - ArrangementFocus::Clip(t, s) => self.phrase_next(), + ArrangementFocus::Track(_) => self.track_width_inc(), + ArrangementFocus::Scene(_) => self.scene_next(), + ArrangementFocus::Clip(_, _) => self.phrase_next(), _ => {} } self.show_phrase() } pub fn decrement (&mut self) { match self.selected { - ArrangementFocus::Track(t) => self.track_width_dec(), - ArrangementFocus::Scene(s) => self.scene_prev(), - ArrangementFocus::Clip(t, s) => self.phrase_prev(), + ArrangementFocus::Track(_) => self.track_width_dec(), + ArrangementFocus::Scene(_) => self.scene_prev(), + ArrangementFocus::Clip(_, _) => self.phrase_prev(), _ => {} } self.show_phrase() @@ -492,7 +504,7 @@ impl ArrangementFocus { } else { format!("S??") }, - Self::Clip(t, s) => if let (Some(track), Some(scene)) = ( + Self::Clip(t, s) => if let (Some(_), Some(scene)) = ( tracks.get(*t), scenes.get(*s), ) { @@ -607,7 +619,7 @@ impl Scene { } } /// Returns the pulse length of the longest phrase in the scene - pub fn pulses (&self, tracks: &[ArrangementTrack]) -> usize { + pub fn pulses (&self) -> usize { self.clips.iter().fold(0, |a, p|a.max(p.as_ref().map(|q|q.read().unwrap().length).unwrap_or(0))) } /// Returns true if all phrases in the scene are currently playing @@ -624,10 +636,10 @@ impl Scene { None => true }) } - pub fn ppqs (tracks: &[ArrangementTrack], scenes: &[Self]) -> Vec<(usize, usize)> { + pub fn ppqs (scenes: &[Self]) -> Vec<(usize, usize)> { let mut total = 0; let mut scenes: Vec<(usize, usize)> = scenes.iter().map(|scene|{ - let pulses = scene.pulses(tracks).max(PPQ); + let pulses = scene.pulses().max(PPQ); total = total + pulses; (pulses, total - pulses) }).collect(); diff --git a/crates/tek_sequencer/src/arranger_cmd.rs b/crates/tek_sequencer/src/arranger_cmd.rs index 9d54eee9..58514bab 100644 --- a/crates/tek_sequencer/src/arranger_cmd.rs +++ b/crates/tek_sequencer/src/arranger_cmd.rs @@ -13,7 +13,7 @@ impl Handle for Arranger { key!(KeyCode::Left) => { self.focus_left(); }, key!(KeyCode::Right) => { self.focus_right(); }, key!(KeyCode::Char('e')) => { self.edit_phrase(); }, - key!(KeyCode::Char(' ')) => { self.toggle_play(); }, + key!(KeyCode::Char(' ')) => { self.toggle_play()?; }, key!(KeyCode::Char('n')) => { self.rename_selected(); }, _ => return Ok(None) } diff --git a/crates/tek_sequencer/src/arranger_tui.rs b/crates/tek_sequencer/src/arranger_tui.rs index 71545e9e..bb07c5d9 100644 --- a/crates/tek_sequencer/src/arranger_tui.rs +++ b/crates/tek_sequencer/src/arranger_tui.rs @@ -45,7 +45,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> { fn content (&self) -> impl Widget { let Self(state, factor) = self; let (cols, rows) = if *factor == 0 {( - state.track_widths(), Scene::ppqs(state.tracks.as_slice(), state.scenes.as_slice()), + state.track_widths(), Scene::ppqs(state.scenes.as_slice()), )} else {( state.track_widths(), (0..=state.scenes.len()).map(|i|(factor*PPQ, factor*PPQ*i)).collect::>(), @@ -77,8 +77,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> { // row separators add(&CustomWidget::new(|_|Ok(Some([0,0])), move|to: &mut TuiOutput|{ - let area = to.area(); - let style = Some(Style::default().fg(COLOR_SEPARATOR)); + let area = to.area(); for y in rows.iter().map(|row|row.1) { let y = area.y() + (y / PPQ) as u16 + 1; if y >= to.buffer.area.height { break } @@ -201,7 +200,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> { impl<'a> Content for HorizontalArranger<'a, Tui> { type Engine = Tui; fn content (&self) -> impl Widget { - let Arrangement { tracks, focused, selected, scenes, .. } = self.0; + let Arrangement { tracks, focused, .. } = self.0; let _tracks = tracks.as_slice(); lay!( focused.then_some(Background(Color::Rgb(40, 50, 30))), @@ -370,7 +369,7 @@ impl<'a> Content for HorizontalArranger<'a, Tui> { CustomWidget::new(|_|{ todo!() }, |to: &mut TuiOutput|{ - let Arrangement { tracks, scenes, selected, .. } = self.0; + let Arrangement { scenes, selected, .. } = self.0; let area = to.area(); let mut x2 = 0; let [x, y, _, height] = area; diff --git a/crates/tek_sequencer/src/lib.rs b/crates/tek_sequencer/src/lib.rs index afe0b914..279b137f 100644 --- a/crates/tek_sequencer/src/lib.rs +++ b/crates/tek_sequencer/src/lib.rs @@ -5,7 +5,7 @@ pub(crate) use tek_core::crossterm::event::KeyCode; pub(crate) use tek_core::midly::{num::u7, live::LiveEvent, MidiMessage}; pub(crate) use tek_core::jack::*; pub(crate) use std::sync::{Arc, RwLock}; -pub(crate) use rand::{thread_rng, prelude::*}; +pub(crate) use rand::thread_rng; pub(crate) use palette::{*, convert::*, okhsl::*}; use rand::distributions::uniform::UniformSampler; diff --git a/crates/tek_sequencer/src/sequencer_cli.rs b/crates/tek_sequencer/src/sequencer_cli.rs index 95f68f3d..ef11b9f9 100644 --- a/crates/tek_sequencer/src/sequencer_cli.rs +++ b/crates/tek_sequencer/src/sequencer_cli.rs @@ -35,17 +35,14 @@ impl SequencerCli { editor: PhraseEditor::new(), phrases: Arc::new(RwLock::new(PhrasePool::new())), }; - if let Some(name) = self.name.as_ref() { - // TODO - //seq.name = Arc::new(RwLock::new(name.clone())); + if let Some(_) = self.name.as_ref() { + // TODO: seq.name = Arc::new(RwLock::new(name.clone())); } - if let Some(ppq) = self.ppq { - // TODO - //seq.ppq = ppq; + if let Some(_) = self.ppq { + // TODO: seq.ppq = ppq; } - if let Some(length) = self.length { - // TODO - //if let Some(phrase) = seq.phrase.as_mut() { + if let Some(_) = self.length { + // TODO: if let Some(phrase) = seq.phrase.as_mut() { //phrase.write().unwrap().length = length; //} } diff --git a/crates/tek_sequencer/src/sequencer_tui.rs b/crates/tek_sequencer/src/sequencer_tui.rs index 5f3676ab..a76f0187 100644 --- a/crates/tek_sequencer/src/sequencer_tui.rs +++ b/crates/tek_sequencer/src/sequencer_tui.rs @@ -76,7 +76,7 @@ impl Content for PhraseEditor { Ok(()) }).fill_y(); let playhead = CustomWidget::new(|_|Ok(Some([32u16,2u16])), move|to: &mut TuiOutput|{ - if let Some(phrase) = phrase { + if let Some(_) = phrase { let time_0 = time_axis.start; let time_z = time_axis.scale; let now = 0; // TODO FIXME: self.now % phrase.read().unwrap().length;