mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-04-28 21:40:14 +02:00
put phrase
This commit is contained in:
parent
e80b9419ae
commit
9bed07451f
62
.scratch.rs
62
.scratch.rs
|
@ -311,3 +311,65 @@
|
||||||
//)
|
//)
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
//impl Command<ArrangerModel> for ArrangerSceneCommand {
|
||||||
|
//}
|
||||||
|
//Edit(phrase) => { state.state.phrase = phrase.clone() },
|
||||||
|
//ToggleViewMode => { state.state.mode.to_next(); },
|
||||||
|
//Delete => { state.state.delete(); },
|
||||||
|
//Activate => { state.state.activate(); },
|
||||||
|
//ZoomIn => { state.state.zoom_in(); },
|
||||||
|
//ZoomOut => { state.state.zoom_out(); },
|
||||||
|
//MoveBack => { state.state.move_back(); },
|
||||||
|
//MoveForward => { state.state.move_forward(); },
|
||||||
|
//RandomColor => { state.state.randomize_color(); },
|
||||||
|
//Put => { state.state.phrase_put(); },
|
||||||
|
//Get => { state.state.phrase_get(); },
|
||||||
|
//AddScene => { state.state.scene_add(None, None)?; },
|
||||||
|
//AddTrack => { state.state.track_add(None, None)?; },
|
||||||
|
//ToggleLoop => { state.state.toggle_loop() },
|
||||||
|
//pub fn zoom_in (&mut self) {
|
||||||
|
//if let ArrangerEditorMode::V(factor) = self.mode {
|
||||||
|
//self.mode = ArrangerEditorMode::V(factor + 1)
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
//pub fn zoom_out (&mut self) {
|
||||||
|
//if let ArrangerEditorMode::V(factor) = self.mode {
|
||||||
|
//self.mode = ArrangerEditorMode::V(factor.saturating_sub(1))
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
//pub fn move_back (&mut self) {
|
||||||
|
//match self.selected {
|
||||||
|
//ArrangerEditorFocus::Scene(s) => {
|
||||||
|
//if s > 0 {
|
||||||
|
//self.scenes.swap(s, s - 1);
|
||||||
|
//self.selected = ArrangerEditorFocus::Scene(s - 1);
|
||||||
|
//}
|
||||||
|
//},
|
||||||
|
//ArrangerEditorFocus::Track(t) => {
|
||||||
|
//if t > 0 {
|
||||||
|
//self.tracks.swap(t, t - 1);
|
||||||
|
//self.selected = ArrangerEditorFocus::Track(t - 1);
|
||||||
|
//// FIXME: also swap clip order in scenes
|
||||||
|
//}
|
||||||
|
//},
|
||||||
|
//_ => todo!("arrangement: move forward")
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
//pub fn move_forward (&mut self) {
|
||||||
|
//match self.selected {
|
||||||
|
//ArrangerEditorFocus::Scene(s) => {
|
||||||
|
//if s < self.scenes.len().saturating_sub(1) {
|
||||||
|
//self.scenes.swap(s, s + 1);
|
||||||
|
//self.selected = ArrangerEditorFocus::Scene(s + 1);
|
||||||
|
//}
|
||||||
|
//},
|
||||||
|
//ArrangerEditorFocus::Track(t) => {
|
||||||
|
//if t < self.tracks.len().saturating_sub(1) {
|
||||||
|
//self.tracks.swap(t, t + 1);
|
||||||
|
//self.selected = ArrangerEditorFocus::Track(t + 1);
|
||||||
|
//// FIXME: also swap clip order in scenes
|
||||||
|
//}
|
||||||
|
//},
|
||||||
|
//_ => todo!("arrangement: move forward")
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
|
@ -177,7 +177,8 @@ handle!(<Tui>|self: ArrangerTui, input|ArrangerCommand::execute_with_state(self,
|
||||||
Zoom(usize),
|
Zoom(usize),
|
||||||
Phrases(PhrasesCommand),
|
Phrases(PhrasesCommand),
|
||||||
Editor(PhraseCommand),
|
Editor(PhraseCommand),
|
||||||
ShowPool(bool)
|
ShowPool(bool),
|
||||||
|
Put(usize, usize, Option<Arc<RwLock<Phrase>>>),
|
||||||
}
|
}
|
||||||
input_to_command!(ArrangerCommand: <Tui>|state: ArrangerTui, input|{
|
input_to_command!(ArrangerCommand: <Tui>|state: ArrangerTui, input|{
|
||||||
use ArrangerSelection as Selected;
|
use ArrangerSelection as Selected;
|
||||||
|
@ -205,25 +206,10 @@ input_to_command!(ArrangerCommand: <Tui>|state: ArrangerTui, input|{
|
||||||
key_pat!(Ctrl-Char('t')) =>
|
key_pat!(Ctrl-Char('t')) =>
|
||||||
Self::Track(ArrangerTrackCommand::Add),
|
Self::Track(ArrangerTrackCommand::Add),
|
||||||
key_pat!(Char('0')) => match state.selected() {
|
key_pat!(Char('0')) => match state.selected() {
|
||||||
Selected::Mix => StopAll,
|
Selected::Mix => StopAll,
|
||||||
Selected::Track(t) => return None,
|
Selected::Track(_t) => return None,
|
||||||
Selected::Scene(s) => return None,
|
Selected::Scene(_s) => return None,
|
||||||
Selected::Clip(t, s) => return None,
|
Selected::Clip(_t, _s) => return None,
|
||||||
},
|
|
||||||
key_pat!(Char('g')) => if let Selected::Clip(t, s) = state.selected() {
|
|
||||||
Self::Phrases(PhrasesCommand::Select(0))
|
|
||||||
} else {
|
|
||||||
return None
|
|
||||||
},
|
|
||||||
key_pat!(Char('p')) => if let Selected::Clip(t, s) = state.selected() {
|
|
||||||
Self::Clip(ArrangerClipCommand::Select(0))
|
|
||||||
} else {
|
|
||||||
return None
|
|
||||||
},
|
|
||||||
key_pat!(Char('q')) => if let Selected::Clip(t, s) = state.selected() {
|
|
||||||
todo!("enqueue clip")
|
|
||||||
} else {
|
|
||||||
return None
|
|
||||||
},
|
},
|
||||||
// Tab: Toggle visibility of phrase pool column
|
// Tab: Toggle visibility of phrase pool column
|
||||||
key_pat!(Tab) =>
|
key_pat!(Tab) =>
|
||||||
|
@ -232,10 +218,23 @@ input_to_command!(ArrangerCommand: <Tui>|state: ArrangerTui, input|{
|
||||||
let t_len = state.tracks.len();
|
let t_len = state.tracks.len();
|
||||||
let s_len = state.scenes.len();
|
let s_len = state.scenes.len();
|
||||||
match state.selected() {
|
match state.selected() {
|
||||||
Selected::Mix => to_arranger_mix_command(input),
|
Selected::Clip(t, s) => match input.event() {
|
||||||
Selected::Track(t) => to_arranger_track_command(input, t, t_len),
|
key_pat!(Char('g')) => Some(Self::Phrases(PhrasesCommand::Select(0))),
|
||||||
|
key_pat!(Char('p')) => Some(Self::Put(t, s, Some(state.phrases.phrase().clone()))),
|
||||||
|
key_pat!(Char('q')) => { todo!("enqueue") },
|
||||||
|
_ => to_arranger_clip_command(input, t, t_len, s, s_len)
|
||||||
|
},
|
||||||
Selected::Scene(s) => to_arranger_scene_command(input, s, s_len),
|
Selected::Scene(s) => to_arranger_scene_command(input, s, s_len),
|
||||||
Selected::Clip(t, s) => to_arranger_clip_command(input, t, t_len, s, s_len),
|
Selected::Track(t) => to_arranger_track_command(input, t, t_len),
|
||||||
|
Selected::Mix => match input.event() {
|
||||||
|
// 0: Enqueue phrase 0 (stop all)
|
||||||
|
key_pat!(Char('0')) => Some(Self::StopAll),
|
||||||
|
key_pat!(Char('s')) => Some(Self::Select(Selected::Scene(0))),
|
||||||
|
key_pat!(Char('d')) => Some(Self::Select(Selected::Track(0))),
|
||||||
|
key_pat!(Delete) => Some(Self::Clear),
|
||||||
|
key_pat!(Char('c')) => Some(Self::Color(ItemPalette::random())),
|
||||||
|
_ => None
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}.or_else(||if let Some(command) = PhraseCommand::input_to_command(&state.editor, input) {
|
}.or_else(||if let Some(command) = PhraseCommand::input_to_command(&state.editor, input) {
|
||||||
Some(Self::Editor(command))
|
Some(Self::Editor(command))
|
||||||
|
@ -246,23 +245,6 @@ input_to_command!(ArrangerCommand: <Tui>|state: ArrangerTui, input|{
|
||||||
})?
|
})?
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fn to_arranger_mix_command (input: &TuiInput) -> Option<ArrangerCommand> {
|
|
||||||
use ArrangerCommand as Cmd;
|
|
||||||
use ArrangerSelection as Select;
|
|
||||||
Some(match input.event() {
|
|
||||||
// 0: Enqueue phrase 0 (stop all)
|
|
||||||
key_pat!(Char('0')) => Cmd::StopAll,
|
|
||||||
key_pat!(Char('s')) => Cmd::Select(Select::Scene(0)),
|
|
||||||
key_pat!(Char('d')) => Cmd::Select(Select::Track(0)),
|
|
||||||
key_pat!(Char(',')) => Cmd::Zoom(0),
|
|
||||||
key_pat!(Char('.')) => Cmd::Zoom(0),
|
|
||||||
key_pat!(Char('<')) => Cmd::Zoom(0),
|
|
||||||
key_pat!(Char('>')) => Cmd::Zoom(0),
|
|
||||||
key_pat!(Delete) => Cmd::Clear,
|
|
||||||
key_pat!(Char('c')) => Cmd::Color(ItemPalette::random()),
|
|
||||||
_ => return None
|
|
||||||
})
|
|
||||||
}
|
|
||||||
command!(|self:ArrangerCommand,state:ArrangerTui|{
|
command!(|self:ArrangerCommand,state:ArrangerTui|{
|
||||||
use ArrangerCommand::*;
|
use ArrangerCommand::*;
|
||||||
match self {
|
match self {
|
||||||
|
@ -305,38 +287,17 @@ command!(|self:ArrangerCommand,state:ArrangerTui|{
|
||||||
_ => default(cmd)?
|
_ => default(cmd)?
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => { todo!() }
|
Undo => { todo!() },
|
||||||
|
Redo => { todo!() },
|
||||||
|
Clear => { todo!() },
|
||||||
|
StopAll => { todo!() },
|
||||||
|
Put(track, scene, phrase) => {
|
||||||
|
let old = state.scenes[scene].clips[track].clone();
|
||||||
|
state.scenes[scene].clips[track] = phrase;
|
||||||
|
Some(Put(track, scene, old))
|
||||||
|
},
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
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
|
|
||||||
});
|
|
||||||
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
|
|
||||||
});
|
|
||||||
command!(|self:ArrangerClipCommand, _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),
|
|
||||||
RandomColor,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Display mode of arranger
|
/// Display mode of arranger
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
|
|
|
@ -21,3 +21,17 @@ pub fn to_arranger_clip_command (input: &TuiInput, t: usize, len_t: usize, s: us
|
||||||
_ => return None
|
_ => return None
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
command!(|self:ArrangerClipCommand, _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),
|
||||||
|
RandomColor,
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,44 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum ArrangerSceneCommand {
|
||||||
|
Add,
|
||||||
|
Delete(usize),
|
||||||
|
RandomColor,
|
||||||
|
Play(usize),
|
||||||
|
Swap(usize, usize),
|
||||||
|
SetSize(usize),
|
||||||
|
SetZoom(usize),
|
||||||
|
SetColor(usize, ItemPalette),
|
||||||
|
}
|
||||||
|
pub fn to_arranger_scene_command (input: &TuiInput, s: usize, len: usize) -> Option<ArrangerCommand> {
|
||||||
|
use KeyCode::{Char, Delete};
|
||||||
|
use ArrangerCommand as Cmd;
|
||||||
|
use ArrangerSelection as Select;
|
||||||
|
use ArrangerSceneCommand as Scene;
|
||||||
|
Some(match input.event() {
|
||||||
|
key_pat!(Char('w')) => Cmd::Select(if s > 0 { Select::Scene(s - 1) } else { Select::Mix }),
|
||||||
|
key_pat!(Char('s')) => Cmd::Select(Select::Scene((s + 1).min(len.saturating_sub(1)))),
|
||||||
|
key_pat!(Char('d')) => Cmd::Select(Select::Clip(0, s)),
|
||||||
|
key_pat!(Char(',')) => Cmd::Scene(Scene::Swap(s, s - 1)),
|
||||||
|
key_pat!(Char('.')) => Cmd::Scene(Scene::Swap(s, s + 1)),
|
||||||
|
key_pat!(Char('<')) => Cmd::Scene(Scene::Swap(s, s - 1)),
|
||||||
|
key_pat!(Char('>')) => Cmd::Scene(Scene::Swap(s, s + 1)),
|
||||||
|
key_pat!(Char('q')) => Cmd::Scene(Scene::Play(s)),
|
||||||
|
key_pat!(Char('c')) => Cmd::Scene(Scene::SetColor(s, ItemPalette::random())),
|
||||||
|
key_pat!(Delete) => Cmd::Scene(Scene::Delete(s)),
|
||||||
|
//key_pat!(Char('c')) => Cmd::Track(Scene::Color(s, ItemPalette::random())),
|
||||||
|
_ => return None
|
||||||
|
})
|
||||||
|
}
|
||||||
|
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 {
|
#[derive(Default, Debug, Clone)] pub struct ArrangerScene {
|
||||||
/// Name of scene
|
/// Name of scene
|
||||||
pub(crate) name: Arc<RwLock<String>>,
|
pub(crate) name: Arc<RwLock<String>>,
|
||||||
|
@ -62,37 +102,6 @@ impl ArrangerScene {
|
||||||
match self.clips().get(index) { Some(Some(clip)) => Some(clip), _ => None }
|
match self.clips().get(index) { Some(Some(clip)) => Some(clip), _ => None }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub enum ArrangerSceneCommand {
|
|
||||||
Add,
|
|
||||||
Delete(usize),
|
|
||||||
RandomColor,
|
|
||||||
Play(usize),
|
|
||||||
Swap(usize, usize),
|
|
||||||
SetSize(usize),
|
|
||||||
SetZoom(usize),
|
|
||||||
SetColor(usize, ItemPalette),
|
|
||||||
}
|
|
||||||
pub fn to_arranger_scene_command (input: &TuiInput, s: usize, len: usize) -> Option<ArrangerCommand> {
|
|
||||||
use KeyCode::{Char, Delete};
|
|
||||||
use ArrangerCommand as Cmd;
|
|
||||||
use ArrangerSelection as Select;
|
|
||||||
use ArrangerSceneCommand as Scene;
|
|
||||||
Some(match input.event() {
|
|
||||||
key_pat!(Char('w')) => Cmd::Select(if s > 0 { Select::Scene(s - 1) } else { Select::Mix }),
|
|
||||||
key_pat!(Char('s')) => Cmd::Select(Select::Scene((s + 1).min(len.saturating_sub(1)))),
|
|
||||||
key_pat!(Char('d')) => Cmd::Select(Select::Clip(0, s)),
|
|
||||||
key_pat!(Char(',')) => Cmd::Scene(Scene::Swap(s, s - 1)),
|
|
||||||
key_pat!(Char('.')) => Cmd::Scene(Scene::Swap(s, s + 1)),
|
|
||||||
key_pat!(Char('<')) => Cmd::Scene(Scene::Swap(s, s - 1)),
|
|
||||||
key_pat!(Char('>')) => Cmd::Scene(Scene::Swap(s, s + 1)),
|
|
||||||
key_pat!(Char('q')) => Cmd::Scene(Scene::Play(s)),
|
|
||||||
key_pat!(Char('c')) => Cmd::Scene(Scene::SetColor(s, ItemPalette::random())),
|
|
||||||
key_pat!(Delete) => Cmd::Scene(Scene::Delete(s)),
|
|
||||||
//key_pat!(Char('c')) => Cmd::Track(Scene::Color(s, ItemPalette::random())),
|
|
||||||
_ => return None
|
|
||||||
})
|
|
||||||
}
|
|
||||||
impl ArrangerTui {
|
impl ArrangerTui {
|
||||||
pub fn scenes (&self) -> &Vec<ArrangerScene> {
|
pub fn scenes (&self) -> &Vec<ArrangerScene> {
|
||||||
&self.scenes
|
&self.scenes
|
||||||
|
@ -123,65 +132,3 @@ impl ArrangerTui {
|
||||||
self.selected.scene().map(|s|self.scenes_mut().get_mut(s)).flatten()
|
self.selected.scene().map(|s|self.scenes_mut().get_mut(s)).flatten()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//impl Command<ArrangerModel> for ArrangerSceneCommand {
|
|
||||||
//}
|
|
||||||
//Edit(phrase) => { state.state.phrase = phrase.clone() },
|
|
||||||
//ToggleViewMode => { state.state.mode.to_next(); },
|
|
||||||
//Delete => { state.state.delete(); },
|
|
||||||
//Activate => { state.state.activate(); },
|
|
||||||
//ZoomIn => { state.state.zoom_in(); },
|
|
||||||
//ZoomOut => { state.state.zoom_out(); },
|
|
||||||
//MoveBack => { state.state.move_back(); },
|
|
||||||
//MoveForward => { state.state.move_forward(); },
|
|
||||||
//RandomColor => { state.state.randomize_color(); },
|
|
||||||
//Put => { state.state.phrase_put(); },
|
|
||||||
//Get => { state.state.phrase_get(); },
|
|
||||||
//AddScene => { state.state.scene_add(None, None)?; },
|
|
||||||
//AddTrack => { state.state.track_add(None, None)?; },
|
|
||||||
//ToggleLoop => { state.state.toggle_loop() },
|
|
||||||
//pub fn zoom_in (&mut self) {
|
|
||||||
//if let ArrangerEditorMode::V(factor) = self.mode {
|
|
||||||
//self.mode = ArrangerEditorMode::V(factor + 1)
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
//pub fn zoom_out (&mut self) {
|
|
||||||
//if let ArrangerEditorMode::V(factor) = self.mode {
|
|
||||||
//self.mode = ArrangerEditorMode::V(factor.saturating_sub(1))
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
//pub fn move_back (&mut self) {
|
|
||||||
//match self.selected {
|
|
||||||
//ArrangerEditorFocus::Scene(s) => {
|
|
||||||
//if s > 0 {
|
|
||||||
//self.scenes.swap(s, s - 1);
|
|
||||||
//self.selected = ArrangerEditorFocus::Scene(s - 1);
|
|
||||||
//}
|
|
||||||
//},
|
|
||||||
//ArrangerEditorFocus::Track(t) => {
|
|
||||||
//if t > 0 {
|
|
||||||
//self.tracks.swap(t, t - 1);
|
|
||||||
//self.selected = ArrangerEditorFocus::Track(t - 1);
|
|
||||||
//// FIXME: also swap clip order in scenes
|
|
||||||
//}
|
|
||||||
//},
|
|
||||||
//_ => todo!("arrangement: move forward")
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
//pub fn move_forward (&mut self) {
|
|
||||||
//match self.selected {
|
|
||||||
//ArrangerEditorFocus::Scene(s) => {
|
|
||||||
//if s < self.scenes.len().saturating_sub(1) {
|
|
||||||
//self.scenes.swap(s, s + 1);
|
|
||||||
//self.selected = ArrangerEditorFocus::Scene(s + 1);
|
|
||||||
//}
|
|
||||||
//},
|
|
||||||
//ArrangerEditorFocus::Track(t) => {
|
|
||||||
//if t < self.tracks.len().saturating_sub(1) {
|
|
||||||
//self.tracks.swap(t, t + 1);
|
|
||||||
//self.selected = ArrangerEditorFocus::Track(t + 1);
|
|
||||||
//// FIXME: also swap clip order in scenes
|
|
||||||
//}
|
|
||||||
//},
|
|
||||||
//_ => todo!("arrangement: move forward")
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
|
@ -1,38 +1,32 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use KeyCode::{Char, Delete};
|
use KeyCode::{Char, Delete};
|
||||||
|
|
||||||
impl ArrangerTui {
|
pub fn to_arranger_track_command (input: &TuiInput, t: usize, len: usize) -> Option<ArrangerCommand> {
|
||||||
pub fn tracks (&self) -> &Vec<ArrangerTrack> {
|
use ArrangerCommand::*;
|
||||||
&self.tracks
|
use ArrangerSelection as Selected;
|
||||||
}
|
use ArrangerTrackCommand as Tracks;
|
||||||
pub fn tracks_mut (&mut self) -> &mut Vec<ArrangerTrack> {
|
Some(match input.event() {
|
||||||
&mut self.tracks
|
key_pat!(Char('s')) => Select(Selected::Clip(t, 0)),
|
||||||
}
|
key_pat!(Char('a')) => Select(if t > 0 { Selected::Track(t - 1) } else { Selected::Mix }),
|
||||||
pub fn track_next_name (&self) -> String {
|
key_pat!(Char('d')) => Select(Selected::Track((t + 1).min(len.saturating_sub(1)))),
|
||||||
format!("T{}", self.tracks().len() + 1)
|
key_pat!(Char('c')) => Track(Tracks::SetColor(t, ItemPalette::random())),
|
||||||
}
|
key_pat!(Char(',')) => Track(Tracks::Swap(t, t - 1)),
|
||||||
pub fn track_add (&mut self, name: Option<&str>, color: Option<ItemPalette>)
|
key_pat!(Char('.')) => Track(Tracks::Swap(t, t + 1)),
|
||||||
-> Usually<&mut ArrangerTrack>
|
key_pat!(Char('<')) => Track(Tracks::Swap(t, t - 1)),
|
||||||
{
|
key_pat!(Char('>')) => Track(Tracks::Swap(t, t + 1)),
|
||||||
let name = name.map_or_else(||self.track_next_name(), |x|x.to_string());
|
key_pat!(Delete) => Track(Tracks::Delete(t)),
|
||||||
let track = ArrangerTrack {
|
//key_pat!(Char('c')) => Cmd::Track(Track::Color(t, ItemPalette::random())),
|
||||||
width: name.len() + 2,
|
_ => return None
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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 {
|
#[derive(Debug)] pub struct ArrangerTrack {
|
||||||
/// Name of track
|
/// Name of track
|
||||||
|
@ -132,21 +126,34 @@ impl<'a> Audio for TracksAudio<'a> {
|
||||||
Control::Continue
|
Control::Continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn to_arranger_track_command (input: &TuiInput, t: usize, len: usize) -> Option<ArrangerCommand> {
|
impl ArrangerTui {
|
||||||
use ArrangerCommand::*;
|
pub fn tracks (&self) -> &Vec<ArrangerTrack> {
|
||||||
use ArrangerSelection as Selected;
|
&self.tracks
|
||||||
use ArrangerTrackCommand as Tracks;
|
}
|
||||||
Some(match input.event() {
|
pub fn tracks_mut (&mut self) -> &mut Vec<ArrangerTrack> {
|
||||||
key_pat!(Char('s')) => Select(Selected::Clip(t, 0)),
|
&mut self.tracks
|
||||||
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)))),
|
pub fn track_next_name (&self) -> String {
|
||||||
key_pat!(Char('c')) => Track(Tracks::SetColor(t, ItemPalette::random())),
|
format!("T{}", self.tracks().len() + 1)
|
||||||
key_pat!(Char(',')) => Track(Tracks::Swap(t, t - 1)),
|
}
|
||||||
key_pat!(Char('.')) => Track(Tracks::Swap(t, t + 1)),
|
pub fn track_add (&mut self, name: Option<&str>, color: Option<ItemPalette>)
|
||||||
key_pat!(Char('<')) => Track(Tracks::Swap(t, t - 1)),
|
-> Usually<&mut ArrangerTrack>
|
||||||
key_pat!(Char('>')) => Track(Tracks::Swap(t, t + 1)),
|
{
|
||||||
key_pat!(Delete) => Track(Tracks::Delete(t)),
|
let name = name.map_or_else(||self.track_next_name(), |x|x.to_string());
|
||||||
//key_pat!(Char('c')) => Cmd::Track(Track::Color(t, ItemPalette::random())),
|
let track = ArrangerTrack {
|
||||||
_ => return None
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue