cleanup; remove tracks/scenes[_mut]() methods

in favor of direct property access
This commit is contained in:
🪞👃🪞 2024-12-24 23:49:46 +01:00
parent bb8e1f14eb
commit f1847b62b8
8 changed files with 125 additions and 154 deletions

View file

@ -36,8 +36,8 @@ impl ArrangerTui {
self.clock().play_from(Some(0))?;
}
} else if let ArrangerSelection::Clip(t, s) = self.selected {
let phrase = self.scenes()[s].clips[t].clone();
self.tracks_mut()[t].player.enqueue_next(phrase.as_ref());
let phrase = self.scenes[s].clips[t].clone();
self.tracks[t].player.enqueue_next(phrase.as_ref());
};
Ok(())
}
@ -51,19 +51,11 @@ impl ArrangerTui {
}
pub fn randomize_color (&mut self) {
match self.selected {
ArrangerSelection::Mix => {
self.color = ItemPalette::random()
},
ArrangerSelection::Track(t) => {
self.tracks_mut()[t].color = ItemPalette::random()
},
ArrangerSelection::Scene(s) => {
self.scenes_mut()[s].color = ItemPalette::random()
},
ArrangerSelection::Clip(t, s) => {
if let Some(phrase) = &self.scenes_mut()[s].clips[t] {
phrase.write().unwrap().color = ItemPalette::random();
}
ArrangerSelection::Mix => { self.color = ItemPalette::random() },
ArrangerSelection::Track(t) => { self.tracks[t].color = ItemPalette::random() },
ArrangerSelection::Scene(s) => { self.scenes[s].color = ItemPalette::random() },
ArrangerSelection::Clip(t, s) => if let Some(phrase) = &self.scenes[s].clips[t] {
phrase.write().unwrap().color = ItemPalette::random();
}
}
}
@ -138,7 +130,7 @@ audio!(|self: ArrangerTui, client, scope|{
// FIXME: one of these per playing track
//self.now.set(0.);
//if let ArrangerSelection::Clip(t, s) = self.selected {
//let phrase = self.scenes().get(s).map(|scene|scene.clips.get(t));
//let phrase = self.scenes.get(s).map(|scene|scene.clips.get(t));
//if let Some(Some(Some(phrase))) = phrase {
//if let Some(track) = self.tracks().get(t) {
//if let Some((ref started_at, Some(ref playing))) = track.player.play_phrase {

View file

@ -20,9 +20,37 @@ use KeyCode::{Char, Delete, Tab};
PutClip(usize, usize, Option<Arc<RwLock<Phrase>>>),
EnqueueClip(usize, usize),
EnqueueScene(usize),
StopTrack(usize),
StopAll,
}
#[derive(Clone, Debug)]
pub enum ArrangerTrackCommand {
Add,
Delete(usize),
Stop(usize),
Swap(usize, usize),
SetSize(usize),
SetZoom(usize),
SetColor(usize, ItemPalette),
}
#[derive(Clone, Debug)]
pub enum ArrangerSceneCommand {
Add,
Delete(usize),
Swap(usize, usize),
SetSize(usize),
SetZoom(usize),
SetColor(usize, ItemPalette),
}
#[derive(Clone, Debug)]
pub enum ArrangerClipCommand {
Play,
Get(usize, usize),
Set(usize, usize, Option<Arc<RwLock<Phrase>>>),
Edit(Option<Arc<RwLock<Phrase>>>),
SetLoop(bool),
SetColor(ItemPalette),
}
input_to_command!(ArrangerCommand: <Tui>|state: ArrangerTui, input|{
use ArrangerSelection as Selected;
use ArrangerSceneCommand as Scene;
@ -186,10 +214,6 @@ command!(|self:ArrangerCommand,state:ArrangerTui|match self {
}
None
},
Self::StopTrack(track) => {
state.tracks[track].player.enqueue_next(None);
None
},
Self::StopAll => {
for track in 0..state.tracks.len() {
state.tracks[track].player.enqueue_next(None);
@ -197,16 +221,30 @@ command!(|self:ArrangerCommand,state:ArrangerTui|match self {
None
},
});
#[derive(Clone, Debug)]
pub enum ArrangerClipCommand {
Play,
Get(usize, usize),
Set(usize, usize, Option<Arc<RwLock<Phrase>>>),
Edit(Option<Arc<RwLock<Phrase>>>),
SetLoop(bool),
SetColor(ItemPalette),
}
command!(|self: ArrangerTrackCommand, state: ArrangerTui|match self {
Self::SetColor(index, color) => {
let old = state.tracks[index].color;
state.tracks[index].color = color;
Some(Self::SetColor(index, old))
},
Self::Stop(track) => {
state.tracks[track].player.enqueue_next(None);
None
},
_ => None
});
command!(|self:ArrangerSceneCommand,state:ArrangerTui|match self {
Self::Delete(index) => {
state.scene_del(index);
None
},
Self::SetColor(index, color) => {
let old = state.scenes[index].color;
state.scenes[index].color = color;
Some(Self::SetColor(index, old))
},
_ => None
});
command!(|self:ArrangerClipCommand, _state:ArrangerTui|match self {
_ => None
});

View file

@ -12,7 +12,7 @@ from!(<'a>|args:(&'a ArrangerTui, usize)|ArrangerVClips<'a> = Self {
size: &args.0.size,
scenes: &args.0.scenes,
tracks: &args.0.tracks,
rows: ArrangerScene::ppqs(args.0.scenes(), args.1),
rows: ArrangerScene::ppqs(&args.0.scenes, args.1),
});
render!(<Tui>|self: ArrangerVClips<'a>|Fill::wh(

View file

@ -11,10 +11,10 @@ pub struct ArrangerVCursor {
}
from!(|args:(&ArrangerTui, usize)|ArrangerVCursor = Self {
cols: ArrangerTrack::widths(args.0.tracks()),
rows: ArrangerScene::ppqs(args.0.scenes(), args.1),
cols: ArrangerTrack::widths(&args.0.tracks),
rows: ArrangerScene::ppqs(&args.0.scenes, args.1),
selected: args.0.selected(),
scenes_w: SCENES_W_OFFSET + ArrangerScene::longest_name(args.0.scenes()) as u16,
scenes_w: SCENES_W_OFFSET + ArrangerScene::longest_name(&args.0.scenes) as u16,
color: args.0.color,
reticle: Reticle(Style {
fg: Some(args.0.color.lighter.rgb),

View file

@ -9,10 +9,10 @@ pub struct ArrangerVHead<'a> {
}
from!(<'a>|state: &'a ArrangerTui|ArrangerVHead<'a> = Self { // A
tracks: state.tracks(),
tracks: &state.tracks,
timebase: state.clock().timebase(),
current: &state.clock().playhead,
scenes_w: SCENES_W_OFFSET + ArrangerScene::longest_name(state.scenes()) as u16,
scenes_w: SCENES_W_OFFSET + ArrangerScene::longest_name(&state.scenes) as u16,
});
render!(<Tui>|self: ArrangerVHead<'a>|Tui::push_x(self.scenes_w, row!(

View file

@ -9,8 +9,8 @@ pub struct ArrangerVColSep {
from!(|state:&ArrangerTui|ArrangerVColSep = Self {
fg: TuiTheme::separator_fg(false),
cols: ArrangerTrack::widths(state.tracks()),
scenes_w: SCENES_W_OFFSET + ArrangerScene::longest_name(state.scenes()) as u16,
cols: ArrangerTrack::widths(&state.tracks),
scenes_w: SCENES_W_OFFSET + ArrangerScene::longest_name(&state.scenes) as u16,
});
render!(<Tui>|self: ArrangerVColSep|render(move|to: &mut TuiOutput|{
@ -30,7 +30,7 @@ pub struct ArrangerVRowSep {
from!(|args:(&ArrangerTui, usize)|ArrangerVRowSep = Self {
fg: TuiTheme::separator_fg(false),
rows: ArrangerScene::ppqs(args.0.scenes(), args.1),
rows: ArrangerScene::ppqs(&args.0.scenes, args.1),
});
render!(<Tui>|self: ArrangerVRowSep|render(move|to: &mut TuiOutput|{

View file

@ -1,22 +1,33 @@
use crate::*;
#[derive(Clone, Debug)]
pub enum ArrangerSceneCommand {
Add,
Delete(usize),
Swap(usize, usize),
SetSize(usize),
SetZoom(usize),
SetColor(usize, ItemPalette),
impl ArrangerTui {
pub fn scene_add (&mut self, name: Option<&str>, color: Option<ItemPalette>)
-> Usually<&mut ArrangerScene>
{
let name = name.map_or_else(||self.scene_default_name(), |x|x.to_string());
let scene = ArrangerScene {
name: Arc::new(name.into()),
clips: vec![None;self.tracks.len()],
color: color.unwrap_or_else(||ItemPalette::random()),
};
self.scenes.push(scene);
let index = self.scenes.len() - 1;
Ok(&mut self.scenes[index])
}
pub fn scene_del (&mut self, index: usize) {
todo!("delete scene");
}
fn scene_default_name (&self) -> String {
format!("S{:3>}", self.scenes.len() + 1)
}
pub fn selected_scene (&self) -> Option<&ArrangerScene> {
self.selected.scene().map(|s|self.scenes.get(s)).flatten()
}
pub fn selected_scene_mut (&mut self) -> Option<&mut ArrangerScene> {
self.selected.scene().map(|s|self.scenes.get_mut(s)).flatten()
}
}
command!(|self:ArrangerSceneCommand,state:ArrangerTui|match self {
//Self::Delete(index) => { state.scene_del(index); },
Self::SetColor(index, color) => {
let old = state.scenes[index].color;
state.scenes[index].color = color;
Some(Self::SetColor(index, old))
},
_ => None
});
#[derive(Default, Debug, Clone)] pub struct ArrangerScene {
/// Name of scene
pub(crate) name: Arc<RwLock<String>>,
@ -25,6 +36,7 @@ command!(|self:ArrangerSceneCommand,state:ArrangerTui|match self {
/// Identifying color of scene
pub(crate) color: ItemPalette,
}
impl ArrangerScene {
pub fn name (&self) -> &Arc<RwLock<String>> {
&self.name
@ -80,33 +92,3 @@ impl ArrangerScene {
match self.clips().get(index) { Some(Some(clip)) => Some(clip), _ => None }
}
}
impl ArrangerTui {
pub fn scenes (&self) -> &Vec<ArrangerScene> {
&self.scenes
}
pub fn scenes_mut (&mut self) -> &mut Vec<ArrangerScene> {
&mut self.scenes
}
pub fn scene_add (&mut self, name: Option<&str>, color: Option<ItemPalette>)
-> Usually<&mut ArrangerScene>
{
let name = name.map_or_else(||self.scene_default_name(), |x|x.to_string());
let scene = ArrangerScene {
name: Arc::new(name.into()),
clips: vec![None;self.tracks().len()],
color: color.unwrap_or_else(||ItemPalette::random()),
};
self.scenes_mut().push(scene);
let index = self.scenes().len() - 1;
Ok(&mut self.scenes_mut()[index])
}
fn scene_default_name (&self) -> String {
format!("S{:3>}", self.scenes().len() + 1)
}
pub fn selected_scene (&self) -> Option<&ArrangerScene> {
self.selected.scene().map(|s|self.scenes().get(s)).flatten()
}
pub fn selected_scene_mut (&mut self) -> Option<&mut ArrangerScene> {
self.selected.scene().map(|s|self.scenes_mut().get_mut(s)).flatten()
}
}

View file

@ -1,32 +1,31 @@
use crate::*;
use KeyCode::{Char, Delete};
pub fn to_arranger_track_command (input: &TuiInput, t: usize, len: usize) -> Option<ArrangerCommand> {
use ArrangerCommand::*;
use ArrangerSelection as Selected;
use ArrangerTrackCommand as Tracks;
Some(match input.event() {
key_pat!(Char('s')) => Select(Selected::Clip(t, 0)),
key_pat!(Char('a')) => Select(if t > 0 { Selected::Track(t - 1) } else { Selected::Mix }),
key_pat!(Char('d')) => Select(Selected::Track((t + 1).min(len.saturating_sub(1)))),
key_pat!(Char('c')) => Track(Tracks::SetColor(t, ItemPalette::random())),
key_pat!(Char(',')) => Track(Tracks::Swap(t, t - 1)),
key_pat!(Char('.')) => Track(Tracks::Swap(t, t + 1)),
key_pat!(Char('<')) => Track(Tracks::Swap(t, t - 1)),
key_pat!(Char('>')) => Track(Tracks::Swap(t, t + 1)),
key_pat!(Delete) => Track(Tracks::Delete(t)),
//key_pat!(Char('c')) => Cmd::Track(Track::Color(t, ItemPalette::random())),
_ => return None
})
impl ArrangerTui {
pub fn track_next_name (&self) -> String {
format!("T{}", self.tracks.len() + 1)
}
pub fn track_add (&mut self, name: Option<&str>, color: Option<ItemPalette>)
-> Usually<&mut ArrangerTrack>
{
let name = name.map_or_else(||self.track_next_name(), |x|x.to_string());
let track = ArrangerTrack {
width: name.len() + 2,
name: Arc::new(name.into()),
color: color.unwrap_or_else(||ItemPalette::random()),
player: PhrasePlayerModel::from(&self.clock),
};
self.tracks.push(track);
let index = self.tracks.len() - 1;
Ok(&mut self.tracks[index])
}
pub fn track_del (&mut self, index: usize) {
self.tracks.remove(index);
for scene in self.scenes.iter_mut() {
scene.clips.remove(index);
}
}
}
command!(|self: ArrangerTrackCommand, state: ArrangerTui|match self {
Self::SetColor(index, color) => {
let old = state.tracks[index].color;
state.tracks[index].color = color;
Some(Self::SetColor(index, old))
},
_ => None
});
#[derive(Debug)] pub struct ArrangerTrack {
/// Name of track
@ -38,8 +37,10 @@ command!(|self: ArrangerTrackCommand, state: ArrangerTui|match self {
/// MIDI player state
pub(crate) player: PhrasePlayerModel,
}
has_clock!(|self:ArrangerTrack|self.player.clock());
has_player!(|self:ArrangerTrack|self.player);
impl ArrangerTrack {
pub fn widths (tracks: &[Self]) -> Vec<(usize, usize)> {
let mut widths = vec![];
@ -92,17 +93,6 @@ impl ArrangerTrack {
}
}
#[derive(Clone, Debug)]
pub enum ArrangerTrackCommand {
Add,
Delete(usize),
Stop,
Swap(usize, usize),
SetSize(usize),
SetZoom(usize),
SetColor(usize, ItemPalette),
}
/// Hosts the JACK callback for a collection of tracks
pub struct TracksAudio<'a>(
// Track collection
@ -126,34 +116,3 @@ impl<'a> Audio for TracksAudio<'a> {
Control::Continue
}
}
impl ArrangerTui {
pub fn tracks (&self) -> &Vec<ArrangerTrack> {
&self.tracks
}
pub fn tracks_mut (&mut self) -> &mut Vec<ArrangerTrack> {
&mut self.tracks
}
pub fn track_next_name (&self) -> String {
format!("T{}", self.tracks().len() + 1)
}
pub fn track_add (&mut self, name: Option<&str>, color: Option<ItemPalette>)
-> Usually<&mut ArrangerTrack>
{
let name = name.map_or_else(||self.track_next_name(), |x|x.to_string());
let track = ArrangerTrack {
width: name.len() + 2,
name: Arc::new(name.into()),
color: color.unwrap_or_else(||ItemPalette::random()),
player: PhrasePlayerModel::from(&self.clock),
};
self.tracks_mut().push(track);
let index = self.tracks().len() - 1;
Ok(&mut self.tracks_mut()[index])
}
pub fn track_del (&mut self, index: usize) {
self.tracks_mut().remove(index);
for scene in self.scenes_mut().iter_mut() {
scene.clips.remove(index);
}
}
}