From 5b2b04dcf9b1ce86a926e00dba578f1d39406d33 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Tue, 8 Oct 2024 13:56:46 +0300 Subject: [PATCH] wip: phrases by reference instead of index --- crates/tek_sequencer/src/arranger.rs | 218 +++++++++++++---------- crates/tek_sequencer/src/arranger_tui.rs | 42 +++-- 2 files changed, 147 insertions(+), 113 deletions(-) diff --git a/crates/tek_sequencer/src/arranger.rs b/crates/tek_sequencer/src/arranger.rs index 8ef7cf45..1143c543 100644 --- a/crates/tek_sequencer/src/arranger.rs +++ b/crates/tek_sequencer/src/arranger.rs @@ -48,7 +48,7 @@ pub struct ArrangementTrack { #[derive(Default)] pub struct Scene { pub name: Arc>, - pub clips: Vec>, + pub clips: Vec>>>, } #[derive(PartialEq, Clone, Copy)] /// Represents the current user selection in the arranger @@ -89,6 +89,7 @@ pub struct ArrangerRenameModal { pub result: Arc>, pub cursor: usize } +/// General methods for arrangement impl Arrangement { pub fn new (name: &str, phrases: &Arc>>) -> Self { Self { @@ -104,38 +105,18 @@ impl Arrangement { pub fn activate (&mut self) { match self.selected { ArrangementFocus::Scene(s) => { - for (track_index, track) in self.tracks.iter_mut().enumerate() { - track.player.phrase = self.scenes[s].clips[track_index]; + for (t, track) in self.tracks.iter_mut().enumerate() { + track.player.phrase = self.scenes[s].clips[t].clone(); track.player.reset = true; } }, ArrangementFocus::Clip(t, s) => { - self.tracks[t].player.phrase = self.scenes[s].clips[t]; + self.tracks[t].player.phrase = self.scenes[s].clips[t].clone(); self.tracks[t].player.reset = true; }, _ => {} } } - pub fn sequencer (&self) -> Option<&ArrangementTrack> { - self.selected.track() - .map(|track|self.tracks.get(track)) - .flatten() - } - pub fn sequencer_mut (&mut self) -> Option<&mut ArrangementTrack> { - self.selected.track() - .map(|track|self.tracks.get_mut(track)) - .flatten() - } - pub fn show_phrase (&mut self) { - let (scene, track) = (self.selected.scene(), self.selected.track()); - if let (Some(scene_index), Some(track_index)) = (scene, track) { - let scene = self.scenes.get(scene_index); - let track = self.tracks.get_mut(track_index); - if let (Some(scene), Some(track)) = (scene, track) { - track.player.phrase = scene.clips[track_index] - } - } - } pub fn is_first_row (&self) -> bool { let selected = self.selected; selected.is_mix() || selected.is_track() @@ -150,10 +131,13 @@ impl Arrangement { _ => false } } - pub fn track (&self) -> Option<&PhrasePlayer> { +} +/// Methods for tracks in arrangement +impl Arrangement { + pub fn track (&self) -> Option<&ArrangementTrack> { self.selected.track().map(|t|self.tracks.get(t)).flatten() } - pub fn track_mut (&mut self) -> Option<&mut PhrasePlayer> { + pub fn track_mut (&mut self) -> Option<&mut ArrangementTrack> { self.selected.track().map(|t|self.tracks.get_mut(t)).flatten() } pub fn track_next (&mut self) { @@ -164,8 +148,8 @@ impl Arrangement { } pub fn track_add (&mut self, name: Option<&str>) -> Usually<&mut ArrangementTrack> { self.tracks.push(name.map_or_else( - || PhrasePlayer::new(&self.track_default_name()), - |name| PhrasePlayer::new(name), + || ArrangementTrack::new(&self.track_default_name()), + |name| ArrangementTrack::new(name), )); let index = self.tracks.len() - 1; Ok(&mut self.tracks[index]) @@ -176,6 +160,26 @@ impl Arrangement { pub fn track_default_name (&self) -> String { format!("Track {}", self.tracks.len() + 1) } + pub fn track_widths (&self) -> Vec<(usize, usize)> { + let to_len = |track: &ArrangementTrack|track.name.read().unwrap().len(); + let mut lens: Vec = self.tracks.iter().map(to_len).collect(); + for scene in self.scenes.iter() { + for track_index in 0..self.tracks.len() { + if let Some(phrase) = scene.clip(track_index) { + let len = phrase.read().unwrap().name.read().unwrap().len(); + lens[track_index] = lens[track_index].max(len); + } + } + } + let mut total = 0; + let mut to_x_and_w = |len: &usize|{ total = total + *len; (total - *len, *len) }; + let mut lens: Vec<(usize, usize)> = lens.iter().map(to_x_and_w).collect(); + lens.push((0, total)); + lens + } +} +/// Methods for scenes in arrangement +impl Arrangement { pub fn scene (&self) -> Option<&Scene> { self.selected.scene().map(|s|self.scenes.get(s)).flatten() } @@ -203,9 +207,31 @@ impl Arrangement { pub fn scene_default_name (&self) -> String { format!("Scene {}", self.scenes.len() + 1) } - pub fn phrase (&self) -> Option<&Arc>> { - let track_id = self.selected.track()?; - self.tracks.get(track_id)?.phrases.get((*self.scene()?.clips.get(track_id)?)?) +} +/// Methods for phrases in arrangement +impl Arrangement { + pub fn sequencer (&self) -> Option<&ArrangementTrack> { + self.selected.track() + .map(|track|self.tracks.get(track)) + .flatten() + } + pub fn sequencer_mut (&mut self) -> Option<&mut ArrangementTrack> { + self.selected.track() + .map(|track|self.tracks.get_mut(track)) + .flatten() + } + pub fn show_phrase (&mut self) { + let (scene, track) = (self.selected.scene(), self.selected.track()); + if let (Some(scene_index), Some(track_index)) = (scene, track) { + let scene = self.scenes.get(scene_index); + let track = self.tracks.get_mut(track_index); + if let (Some(scene), Some(track)) = (scene, track) { + track.player.phrase = scene.clips[track_index].clone() + } + } + } + pub fn phrase (&self) -> Option>> { + self.scene()?.clips.get(self.selected.track()?)?.clone() } pub fn phrase_del (&mut self) { let track_index = self.selected.track(); @@ -219,72 +245,68 @@ impl Arrangement { }); } pub fn phrase_next (&mut self) { - let track_index = self.selected.track(); - let scene_index = self.selected.scene(); - track_index - .and_then(|index|self.tracks.get_mut(index).map(|track|(index, track))) - .and_then(|(track_index, track)|{ - let phrases = track.phrases.len(); - scene_index - .and_then(|index|self.scenes.get_mut(index)) - .and_then(|scene|{ - if let Some(phrase_index) = scene.clips[track_index] { - if phrase_index >= phrases - 1 { - scene.clips[track_index] = None; - } else { - scene.clips[track_index] = Some(phrase_index + 1); - } - } else if phrases > 0 { - scene.clips[track_index] = Some(0); - } - Some(()) - }) - }); + todo!(); + //let track_index = self.selected.track(); + //let scene_index = self.selected.scene(); + //track_index + //.and_then(|index|self.tracks.get_mut(index).map(|track|(index, track))) + //.and_then(|(track_index, track)|{ + //let phrases = track.phrases.len(); + //scene_index + //.and_then(|index|self.scenes.get_mut(index)) + //.and_then(|scene|{ + //if let Some(phrase_index) = scene.clips[track_index] { + //if phrase_index >= phrases - 1 { + //scene.clips[track_index] = None; + //} else { + //scene.clips[track_index] = Some(phrase_index + 1); + //} + //} else if phrases > 0 { + //scene.clips[track_index] = Some(0); + //} + //Some(()) + //}) + //}); } pub fn phrase_prev (&mut self) { - let track_index = self.selected.track(); - let scene_index = self.selected.scene(); - track_index - .and_then(|index|self.tracks.get_mut(index).map(|track|(index, track))) - .and_then(|(track_index, track)|{ - let phrases = track.phrases.len(); - scene_index - .and_then(|index|self.scenes.get_mut(index)) - .and_then(|scene|{ - if let Some(phrase_index) = scene.clips[track_index] { - scene.clips[track_index] = if phrase_index == 0 { - None - } else { - Some(phrase_index - 1) - }; - } else if phrases > 0 { - scene.clips[track_index] = Some(phrases - 1); - } - Some(()) - }) - }); + todo!(); + //let track_index = self.selected.track(); + //let scene_index = self.selected.scene(); + //track_index + //.and_then(|index|self.tracks.get_mut(index).map(|track|(index, track))) + //.and_then(|(track_index, track)|{ + //let phrases = track.phrases.len(); + //scene_index + //.and_then(|index|self.scenes.get_mut(index)) + //.and_then(|scene|{ + //if let Some(phrase_index) = scene.clips[track_index] { + //scene.clips[track_index] = if phrase_index == 0 { + //None + //} else { + //Some(phrase_index - 1) + //}; + //} else if phrases > 0 { + //scene.clips[track_index] = Some(phrases - 1); + //} + //Some(()) + //}) + //}); } } impl ArrangementTrack { + pub fn new (name: &str) -> Self { + Self { + name: Arc::new(RwLock::new(name.into())), + inputs: vec![], + player: PhrasePlayer::new(name), + outputs: vec![], + } + } pub fn longest_name (tracks: &[Self]) -> usize { tracks.iter() .map(|s|s.name.read().unwrap().len()) .fold(0, usize::max) } - pub fn clip_name_lengths (tracks: &[Self]) -> Vec<(usize, usize)> { - let mut total = 0; - let mut lengths: Vec<(usize, usize)> = tracks.iter().map(|track|{ - let len = 4 + track.phrases - .iter() - .fold(track.name.read().unwrap().len(), |len, phrase|{ - len.max(phrase.read().unwrap().name.read().unwrap().len()) - }); - total = total + len; - (len, total - len) - }).collect(); - lengths.push((0, total)); - lengths - } } /// Focus identification methods impl ArrangementFocus { @@ -309,12 +331,8 @@ impl ArrangementFocus { tracks.get(*t), scenes.get(*s), ) { - if let Some(Some(slot)) = scene.clips.get(*t) { - if let Some(clip) = track.phrases.get(*slot) { - format!("T{t} S{s} C{slot} ({})", &clip.read().unwrap().name.read().unwrap()) - } else { - format!("T{t} S{s}: Empty") - } + if let Some(clip) = scene.clip(*t) { + format!("T{t} S{s} C{}", &clip.read().unwrap().name.read().unwrap()) } else { format!("T{t} S{s}: Empty") } @@ -428,7 +446,10 @@ impl Exit for ArrangerRenameModal { fn exit (&mut self) { self.done = true } } impl Scene { - pub fn new (name: impl AsRef, clips: impl AsRef<[Option]>) -> Self { + pub fn new ( + name: impl AsRef, + clips: impl AsRef<[Option>>]> + ) -> Self { Self { name: Arc::new(RwLock::new(name.as_ref().into())), clips: clips.as_ref().iter().map(|x|x.clone()).collect(), @@ -450,7 +471,7 @@ impl Scene { /// Returns true if all phrases in the scene are currently playing pub fn is_playing (&self, tracks: &[ArrangementTrack]) -> bool { self.clips.iter().enumerate() - .all(|(track_index, phrase_index)|match phrase_index { + .all(|(track_index, clip)|match clip { Some(i) => tracks .get(track_index) .map(|track|track.player.phrase == Some(*i)) @@ -473,4 +494,11 @@ impl Scene { .map(|s|s.name.read().unwrap().len()) .fold(0, usize::max) } + pub fn clip (&self, index: usize) -> Option<&Arc>> { + if let Some(Some(clip)) = self.clips.get(index) { + Some(clip) + } else { + None + } + } } diff --git a/crates/tek_sequencer/src/arranger_tui.rs b/crates/tek_sequencer/src/arranger_tui.rs index 538f45ec..42b5eb5f 100644 --- a/crates/tek_sequencer/src/arranger_tui.rs +++ b/crates/tek_sequencer/src/arranger_tui.rs @@ -58,9 +58,7 @@ impl Handle for Arranger { } else if focus == 1 && is_last_row { self.focus_next(); } else { - return return self.focused_mut().handle(from) - } }, key!(KeyCode::Up) => { @@ -93,12 +91,22 @@ impl Focus<3, Tui> for Arranger { impl Arranger { pub fn rename_selected (&mut self) { let Arrangement { selected, ref name, ref tracks, ref scenes, .. } = self.arrangement; - self.modal = Some(Box::new(ArrangerRenameModal::new(selected, &match selected { - ArrangementFocus::Mix => name.clone(), - ArrangementFocus::Track(t) => tracks[t].name.clone(), - ArrangementFocus::Scene(s) => scenes[s].name.clone(), - ArrangementFocus::Clip(t, s) => tracks[t].phrases[s].read().unwrap().name.clone(), - }))); + self.modal = match selected { + ArrangementFocus::Mix => { + Some(Box::new(ArrangerRenameModal::new(selected, &name))) + }, + ArrangementFocus::Track(t) => { + Some(Box::new(ArrangerRenameModal::new(selected, &tracks[t].name))) + }, + ArrangementFocus::Scene(s) => { + Some(Box::new(ArrangerRenameModal::new(selected, &scenes[s].name))) + }, + ArrangementFocus::Clip(t, s) => if let Some(ref clip) = scenes[s].clips[t] { + Some(Box::new(ArrangerRenameModal::new(selected, &clip.read().unwrap().name))) + } else { + None + } + }; } } impl Focusable for Arrangement { @@ -212,10 +220,12 @@ impl<'a> Content for VerticalArranger<'a, Tui> { fn content (&self) -> impl Widget { let Self(state, factor) = self; let (cols, rows) = if *factor == 0 {( - ArrangementTrack::clip_name_lengths(state.tracks.as_slice()), + state.track_widths(), + //ArrangementTrack::clip_name_lengths(state.tracks.as_slice()), Scene::ppqs(state.tracks.as_slice(), state.scenes.as_slice()), )} else {( - ArrangementTrack::clip_name_lengths(state.tracks.as_slice()), + state.track_widths(), + //ArrangementTrack::clip_name_lengths(state.tracks.as_slice()), (0..=state.scenes.len()).map(|i|(factor*PPQ, factor*PPQ*i)).collect::>(), )}; //let height = rows.last().map(|(w,y)|(y+w)/PPQ).unwrap_or(16); @@ -241,8 +251,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> { (Some(track), Some(Some(clip))) => match track.phrases.get(*clip) { Some(phrase) => { let name = &(phrase as &Arc>).read().unwrap().name; - let name = name.read().unwrap(); - let name = format!("{clip:02} {}", name); + let name = format!("{}", name.read().unwrap()); add(&name.as_str().push_x(1).fixed_x(w))?; if (track as &PhrasePlayer<_>).phrase == Some(*clip) { color = COLOR_PLAYING @@ -262,7 +271,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> { let playing = scene.is_playing(tracks); Stack::right(move |add| { add(&scene_name(scene, playing, height))?; - for (track, (w, _x)) in cols.iter().enumerate() { + for (track, (w, _)) in cols.iter().enumerate() { add(&scene_clip(scene, track, *w as u16, height))?; } Ok(()) @@ -572,10 +581,7 @@ impl<'a> Content for HorizontalArranger<'a, Tui> { let active_track = selected.track() == Some(i); if let Some(clip) = clip { let y2 = y + 2 + i as u16 * 2; - let label = match tracks[i].phrases.get(*clip) { - Some(phrase) => &format!("{}", phrase.read().unwrap().name.read().unwrap()), - None => "...." - }; + let label = format!("{}", clip.read().unwrap().name.read().unwrap()); to.blit(&label, x + x2, y2, Some(if active_track && active_scene { Style::default().not_dim().yellow().bold() } else { @@ -617,7 +623,7 @@ impl Content for ArrangerRenameModal { //to.blit(&"▂", area.x() + 3 + label.len() as u16 + 1 + self.cursor as u16, y, style); //Ok(Some(area)) //Ok(()) - } + } } impl Handle for ArrangerRenameModal { fn handle (&mut self, from: &TuiInput) -> Perhaps {