mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
extract _cmd modules
This commit is contained in:
parent
e20f195c20
commit
60c129d868
7 changed files with 270 additions and 267 deletions
95
crates/tek_sequencer/src/arranger_cmd.rs
Normal file
95
crates/tek_sequencer/src/arranger_cmd.rs
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
use crate::*;
|
||||||
|
/// Handle top-level events in standalone arranger.
|
||||||
|
impl Handle<Tui> for Arranger<Tui> {
|
||||||
|
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
||||||
|
if !match self.focused() {
|
||||||
|
ArrangerFocus::Transport => self.transport.handle(from)?,
|
||||||
|
ArrangerFocus::PhrasePool => self.phrases.handle(from)?,
|
||||||
|
ArrangerFocus::PhraseEditor => self.editor.handle(from)?,
|
||||||
|
ArrangerFocus::Arrangement => {
|
||||||
|
let mut handle_phrase = ||{
|
||||||
|
let result = self.phrases.handle(from);
|
||||||
|
self.arrangement.phrase_put();
|
||||||
|
result
|
||||||
|
};
|
||||||
|
match from.event() {
|
||||||
|
key!(KeyCode::Char('a')) => handle_phrase()?,
|
||||||
|
key!(KeyCode::Char('c')) => handle_phrase()?,
|
||||||
|
key!(KeyCode::Char('i')) => handle_phrase()?,
|
||||||
|
key!(KeyCode::Char('d')) => handle_phrase()?,
|
||||||
|
_ => self.arrangement.handle(from)?
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}.unwrap_or(false) {
|
||||||
|
match from.event() {
|
||||||
|
// Tab navigation
|
||||||
|
key!(KeyCode::Tab) => { self.focus_next(); },
|
||||||
|
key!(Shift-KeyCode::Tab) => { self.focus_prev(); },
|
||||||
|
key!(KeyCode::BackTab) => { self.focus_prev(); },
|
||||||
|
key!(Shift-KeyCode::BackTab) => { self.focus_prev(); },
|
||||||
|
// Directional navigation
|
||||||
|
key!(KeyCode::Up) => { self.focus_up(); },
|
||||||
|
key!(KeyCode::Down) => { self.focus_down(); },
|
||||||
|
key!(KeyCode::Left) => { self.focus_left(); },
|
||||||
|
key!(KeyCode::Right) => { self.focus_right(); },
|
||||||
|
// Put selected phrase at position
|
||||||
|
key!(KeyCode::Char('s')) => { self.arrangement.phrase_put(); },
|
||||||
|
// Global play/pause binding
|
||||||
|
key!(KeyCode::Char(' ')) => match self.transport {
|
||||||
|
Some(ref mut transport) => { transport.write().unwrap().toggle_play()?; },
|
||||||
|
None => { return Ok(None) }
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(Some(true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Handle<Tui> for Arrangement<Tui> {
|
||||||
|
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
||||||
|
match from.event() {
|
||||||
|
key!(KeyCode::Char('`')) => { self.mode.to_next(); },
|
||||||
|
key!(KeyCode::Delete) => { self.delete(); },
|
||||||
|
key!(KeyCode::Char('.')) => { self.increment(); },
|
||||||
|
key!(KeyCode::Char(',')) => { self.decrement(); },
|
||||||
|
// TODO: next/prev scene
|
||||||
|
key!(KeyCode::Enter) => { self.activate(); },
|
||||||
|
key!(Ctrl-KeyCode::Char('a')) => { self.scene_add(None, None)?; },
|
||||||
|
key!(Ctrl-KeyCode::Char('t')) => { self.track_add(None, None)?; },
|
||||||
|
key!(KeyCode::Char('n')) => { todo!("rename selected"); },
|
||||||
|
key!(KeyCode::Char('l')) => if let Some(phrase) = self.phrase() {
|
||||||
|
phrase.write().unwrap().toggle_loop()
|
||||||
|
},
|
||||||
|
key!(KeyCode::Up) => {
|
||||||
|
match self.mode {
|
||||||
|
ArrangementViewMode::Horizontal => self.track_prev(),
|
||||||
|
_ => self.scene_prev(),
|
||||||
|
};
|
||||||
|
self.show_phrase();
|
||||||
|
},
|
||||||
|
key!(KeyCode::Down) => {
|
||||||
|
match self.mode {
|
||||||
|
ArrangementViewMode::Horizontal => self.track_next(),
|
||||||
|
_ => self.scene_next(),
|
||||||
|
};
|
||||||
|
self.show_phrase();
|
||||||
|
},
|
||||||
|
key!(KeyCode::Left) => {
|
||||||
|
match self.mode {
|
||||||
|
ArrangementViewMode::Horizontal => self.scene_prev(),
|
||||||
|
_ => self.track_prev(),
|
||||||
|
};
|
||||||
|
self.show_phrase();
|
||||||
|
},
|
||||||
|
key!(KeyCode::Right) => {
|
||||||
|
match self.mode {
|
||||||
|
ArrangementViewMode::Horizontal => self.scene_next(),
|
||||||
|
_ => self.track_next(),
|
||||||
|
};
|
||||||
|
self.show_phrase();
|
||||||
|
},
|
||||||
|
_ => return Ok(None)
|
||||||
|
}
|
||||||
|
Ok(Some(true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -25,52 +25,6 @@ impl Content for Arranger<Tui> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Handle top-level events in standalone arranger.
|
|
||||||
impl Handle<Tui> for Arranger<Tui> {
|
|
||||||
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
|
||||||
if !match self.focused() {
|
|
||||||
ArrangerFocus::Transport => self.transport.handle(from)?,
|
|
||||||
ArrangerFocus::PhrasePool => self.phrases.handle(from)?,
|
|
||||||
ArrangerFocus::PhraseEditor => self.editor.handle(from)?,
|
|
||||||
ArrangerFocus::Arrangement => {
|
|
||||||
let mut handle_phrase = ||{
|
|
||||||
let result = self.phrases.handle(from);
|
|
||||||
self.arrangement.phrase_put();
|
|
||||||
result
|
|
||||||
};
|
|
||||||
match from.event() {
|
|
||||||
key!(KeyCode::Char('a')) => handle_phrase()?,
|
|
||||||
key!(KeyCode::Char('c')) => handle_phrase()?,
|
|
||||||
key!(KeyCode::Char('i')) => handle_phrase()?,
|
|
||||||
key!(KeyCode::Char('d')) => handle_phrase()?,
|
|
||||||
_ => self.arrangement.handle(from)?
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}.unwrap_or(false) {
|
|
||||||
match from.event() {
|
|
||||||
// Tab navigation
|
|
||||||
key!(KeyCode::Tab) => { self.focus_next(); },
|
|
||||||
key!(Shift-KeyCode::Tab) => { self.focus_prev(); },
|
|
||||||
key!(KeyCode::BackTab) => { self.focus_prev(); },
|
|
||||||
key!(Shift-KeyCode::BackTab) => { self.focus_prev(); },
|
|
||||||
// Directional navigation
|
|
||||||
key!(KeyCode::Up) => { self.focus_up(); },
|
|
||||||
key!(KeyCode::Down) => { self.focus_down(); },
|
|
||||||
key!(KeyCode::Left) => { self.focus_left(); },
|
|
||||||
key!(KeyCode::Right) => { self.focus_right(); },
|
|
||||||
// Put selected phrase at position
|
|
||||||
key!(KeyCode::Char('s')) => { self.arrangement.phrase_put(); },
|
|
||||||
// Global play/pause binding
|
|
||||||
key!(KeyCode::Char(' ')) => match self.transport {
|
|
||||||
Some(ref mut transport) => { transport.write().unwrap().toggle_play()?; },
|
|
||||||
None => { return Ok(None) }
|
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Ok(Some(true))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Arranger<Tui> {
|
impl Arranger<Tui> {
|
||||||
pub fn rename_selected (&mut self) {
|
pub fn rename_selected (&mut self) {
|
||||||
let Arrangement { selected, ref name, ref tracks, ref scenes, .. } = self.arrangement;
|
let Arrangement { selected, ref name, ref tracks, ref scenes, .. } = self.arrangement;
|
||||||
|
|
@ -92,54 +46,6 @@ impl Arranger<Tui> {
|
||||||
//};
|
//};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Handle<Tui> for Arrangement<Tui> {
|
|
||||||
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
|
||||||
match from.event() {
|
|
||||||
key!(KeyCode::Char('`')) => { self.mode.to_next(); },
|
|
||||||
key!(KeyCode::Delete) => { self.delete(); },
|
|
||||||
key!(KeyCode::Char('.')) => { self.increment(); },
|
|
||||||
key!(KeyCode::Char(',')) => { self.decrement(); },
|
|
||||||
// TODO: next/prev scene
|
|
||||||
key!(KeyCode::Enter) => { self.activate(); },
|
|
||||||
key!(Ctrl-KeyCode::Char('a')) => { self.scene_add(None, None)?; },
|
|
||||||
key!(Ctrl-KeyCode::Char('t')) => { self.track_add(None, None)?; },
|
|
||||||
key!(KeyCode::Char('n')) => { todo!("rename selected"); },
|
|
||||||
key!(KeyCode::Char('l')) => if let Some(phrase) = self.phrase() {
|
|
||||||
phrase.write().unwrap().toggle_loop()
|
|
||||||
},
|
|
||||||
key!(KeyCode::Up) => {
|
|
||||||
match self.mode {
|
|
||||||
ArrangementViewMode::Horizontal => self.track_prev(),
|
|
||||||
_ => self.scene_prev(),
|
|
||||||
};
|
|
||||||
self.show_phrase();
|
|
||||||
},
|
|
||||||
key!(KeyCode::Down) => {
|
|
||||||
match self.mode {
|
|
||||||
ArrangementViewMode::Horizontal => self.track_next(),
|
|
||||||
_ => self.scene_next(),
|
|
||||||
};
|
|
||||||
self.show_phrase();
|
|
||||||
},
|
|
||||||
key!(KeyCode::Left) => {
|
|
||||||
match self.mode {
|
|
||||||
ArrangementViewMode::Horizontal => self.scene_prev(),
|
|
||||||
_ => self.track_prev(),
|
|
||||||
};
|
|
||||||
self.show_phrase();
|
|
||||||
},
|
|
||||||
key!(KeyCode::Right) => {
|
|
||||||
match self.mode {
|
|
||||||
ArrangementViewMode::Horizontal => self.scene_next(),
|
|
||||||
_ => self.track_next(),
|
|
||||||
};
|
|
||||||
self.show_phrase();
|
|
||||||
},
|
|
||||||
_ => return Ok(None)
|
|
||||||
}
|
|
||||||
Ok(Some(true))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Content for Arrangement<Tui> {
|
impl Content for Arrangement<Tui> {
|
||||||
type Engine = Tui;
|
type Engine = Tui;
|
||||||
fn content (&self) -> impl Widget<Engine = Tui> {
|
fn content (&self) -> impl Widget<Engine = Tui> {
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,9 @@ pub(crate) use palette::{*, convert::*, okhsl::*};
|
||||||
use rand::distributions::uniform::UniformSampler;
|
use rand::distributions::uniform::UniformSampler;
|
||||||
|
|
||||||
submod! {
|
submod! {
|
||||||
arranger arranger_tui
|
arranger arranger_cmd arranger_tui
|
||||||
sequencer sequencer_tui
|
sequencer sequencer_cmd sequencer_tui
|
||||||
transport transport_tui
|
transport transport_cmd transport_tui
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const PPQ: usize = 96;
|
pub const PPQ: usize = 96;
|
||||||
|
|
@ -39,8 +39,8 @@ tui_style!(STYLE_VALUE =
|
||||||
pub fn random_okhsl () -> Okhsl<f32> {
|
pub fn random_okhsl () -> Okhsl<f32> {
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
UniformOkhsl::new(
|
UniformOkhsl::new(
|
||||||
Okhsl::new(-180.0, 0.05, 0.1),
|
Okhsl::new(-180.0, 0.01, 0.05),
|
||||||
Okhsl::new( 180.0, 0.9, 0.5),
|
Okhsl::new( 180.0, 0.9, 0.5),
|
||||||
).sample(&mut rng)
|
).sample(&mut rng)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
118
crates/tek_sequencer/src/sequencer_cmd.rs
Normal file
118
crates/tek_sequencer/src/sequencer_cmd.rs
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
use crate::*;
|
||||||
|
/// Handle top-level events in standalone arranger.
|
||||||
|
impl Handle<Tui> for Sequencer<Tui> {
|
||||||
|
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
||||||
|
if !match self.focused() {
|
||||||
|
SequencerFocus::Transport => self.transport.handle(from)?,
|
||||||
|
SequencerFocus::PhrasePool => self.phrases.handle(from)?,
|
||||||
|
SequencerFocus::PhraseEditor => self.editor.handle(from)?
|
||||||
|
}.unwrap_or(false) {
|
||||||
|
match from.event() {
|
||||||
|
// Tab navigation
|
||||||
|
key!(KeyCode::Tab) => { self.focus_next(); },
|
||||||
|
key!(Shift-KeyCode::Tab) => { self.focus_prev(); },
|
||||||
|
key!(KeyCode::BackTab) => { self.focus_prev(); },
|
||||||
|
key!(Shift-KeyCode::BackTab) => { self.focus_prev(); },
|
||||||
|
// Directional navigation
|
||||||
|
key!(KeyCode::Up) => { self.focus_up(); },
|
||||||
|
key!(KeyCode::Down) => { self.focus_down(); },
|
||||||
|
key!(KeyCode::Left) => { self.focus_left(); },
|
||||||
|
key!(KeyCode::Right) => { self.focus_right(); },
|
||||||
|
// Global play/pause binding
|
||||||
|
key!(KeyCode::Char(' ')) => match self.transport {
|
||||||
|
Some(ref mut transport) => { transport.write().unwrap().toggle_play()?; },
|
||||||
|
None => { return Ok(None) }
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(Some(true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Handle<Tui> for PhrasePool<Tui> {
|
||||||
|
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
||||||
|
match self.mode {
|
||||||
|
Some(PhrasePoolMode::Rename(phrase, ref mut old_name)) => {
|
||||||
|
let mut phrase = self.phrases[phrase].write().unwrap();
|
||||||
|
match from.event() {
|
||||||
|
key!(KeyCode::Backspace) => { phrase.name.pop(); },
|
||||||
|
key!(KeyCode::Char(c)) => { phrase.name.push(*c); },
|
||||||
|
key!(Shift-KeyCode::Char(c)) => { phrase.name.push(*c); },
|
||||||
|
key!(KeyCode::Esc) => { phrase.name = old_name.clone(); self.mode = None; },
|
||||||
|
key!(KeyCode::Enter) => { self.mode = None; },
|
||||||
|
_ => return Ok(None)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => match from.event() {
|
||||||
|
key!(KeyCode::Up) => self.phrase = if self.phrase > 0 {
|
||||||
|
self.phrase - 1
|
||||||
|
} else {
|
||||||
|
self.phrases.len() - 1
|
||||||
|
},
|
||||||
|
key!(KeyCode::Down) => {
|
||||||
|
self.phrase = (self.phrase + 1) % self.phrases.len()
|
||||||
|
},
|
||||||
|
key!(KeyCode::Char('a')) => { // append new
|
||||||
|
let mut phrase = Phrase::default();
|
||||||
|
phrase.name = String::from("(no name)");
|
||||||
|
phrase.color = random_color();
|
||||||
|
self.phrases.push(Arc::new(RwLock::new(phrase)));
|
||||||
|
self.phrase = self.phrases.len() - 1;
|
||||||
|
},
|
||||||
|
key!(KeyCode::Char('i')) => { // insert new
|
||||||
|
let mut phrase = Phrase::default();
|
||||||
|
phrase.name = String::from("(no name)");
|
||||||
|
phrase.color = random_color();
|
||||||
|
self.phrases.insert(self.phrase + 1, Arc::new(RwLock::new(phrase)));
|
||||||
|
self.phrase += 1;
|
||||||
|
},
|
||||||
|
key!(KeyCode::Char('d')) => { // insert duplicate
|
||||||
|
let mut phrase = (*self.phrases[self.phrase].read().unwrap()).clone();
|
||||||
|
phrase.color = random_color_near(phrase.color, 0.2);
|
||||||
|
self.phrases.insert(self.phrase + 1, Arc::new(RwLock::new(phrase)));
|
||||||
|
self.phrase += 1;
|
||||||
|
},
|
||||||
|
key!(KeyCode::Char('c')) => { // change color
|
||||||
|
let mut phrase = self.phrases[self.phrase].write().unwrap();
|
||||||
|
phrase.color = random_color();
|
||||||
|
},
|
||||||
|
key!(KeyCode::Char('n')) => { // change name
|
||||||
|
let phrase = self.phrases[self.phrase].read().unwrap();
|
||||||
|
self.mode = Some(PhrasePoolMode::Rename(self.phrase, phrase.name.clone()));
|
||||||
|
},
|
||||||
|
_ => return Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(Some(true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Handle<Tui> for PhraseEditor<Tui> {
|
||||||
|
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
||||||
|
match from.event() {
|
||||||
|
key!(KeyCode::Char('`')) => {
|
||||||
|
self.mode = !self.mode;
|
||||||
|
},
|
||||||
|
key!(KeyCode::Up) => match self.entered {
|
||||||
|
true => { self.note_axis.point_dec(); },
|
||||||
|
false => { self.note_axis.start_dec(); },
|
||||||
|
},
|
||||||
|
key!(KeyCode::Down) => match self.entered {
|
||||||
|
true => { self.note_axis.point_inc(); },
|
||||||
|
false => { self.note_axis.start_inc(); },
|
||||||
|
},
|
||||||
|
key!(KeyCode::Left) => match self.entered {
|
||||||
|
true => { self.time_axis.point_dec(); },
|
||||||
|
false => { self.time_axis.start_dec(); },
|
||||||
|
},
|
||||||
|
key!(KeyCode::Right) => match self.entered {
|
||||||
|
true => { self.time_axis.point_inc(); },
|
||||||
|
false => { self.time_axis.start_inc(); },
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
return Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(Some(true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,36 +10,6 @@ impl Content for Sequencer<Tui> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Handle top-level events in standalone arranger.
|
|
||||||
impl Handle<Tui> for Sequencer<Tui> {
|
|
||||||
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
|
||||||
if !match self.focused() {
|
|
||||||
SequencerFocus::Transport => self.transport.handle(from)?,
|
|
||||||
SequencerFocus::PhrasePool => self.phrases.handle(from)?,
|
|
||||||
SequencerFocus::PhraseEditor => self.editor.handle(from)?
|
|
||||||
}.unwrap_or(false) {
|
|
||||||
match from.event() {
|
|
||||||
// Tab navigation
|
|
||||||
key!(KeyCode::Tab) => { self.focus_next(); },
|
|
||||||
key!(Shift-KeyCode::Tab) => { self.focus_prev(); },
|
|
||||||
key!(KeyCode::BackTab) => { self.focus_prev(); },
|
|
||||||
key!(Shift-KeyCode::BackTab) => { self.focus_prev(); },
|
|
||||||
// Directional navigation
|
|
||||||
key!(KeyCode::Up) => { self.focus_up(); },
|
|
||||||
key!(KeyCode::Down) => { self.focus_down(); },
|
|
||||||
key!(KeyCode::Left) => { self.focus_left(); },
|
|
||||||
key!(KeyCode::Right) => { self.focus_right(); },
|
|
||||||
// Global play/pause binding
|
|
||||||
key!(KeyCode::Char(' ')) => match self.transport {
|
|
||||||
Some(ref mut transport) => { transport.write().unwrap().toggle_play()?; },
|
|
||||||
None => { return Ok(None) }
|
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Ok(Some(true))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO: Display phrases always in order of appearance
|
// TODO: Display phrases always in order of appearance
|
||||||
impl Content for PhrasePool<Tui> {
|
impl Content for PhrasePool<Tui> {
|
||||||
type Engine = Tui;
|
type Engine = Tui;
|
||||||
|
|
@ -82,64 +52,6 @@ impl Content for PhrasePool<Tui> {
|
||||||
}).push_x(1))
|
}).push_x(1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Handle<Tui> for PhrasePool<Tui> {
|
|
||||||
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
|
||||||
match self.mode {
|
|
||||||
Some(PhrasePoolMode::Rename(phrase, ref mut old_name)) => {
|
|
||||||
let mut phrase = self.phrases[phrase].write().unwrap();
|
|
||||||
match from.event() {
|
|
||||||
key!(KeyCode::Backspace) => { phrase.name.pop(); },
|
|
||||||
key!(KeyCode::Char(c)) => { phrase.name.push(*c); },
|
|
||||||
key!(Shift-KeyCode::Char(c)) => { phrase.name.push(*c); },
|
|
||||||
key!(KeyCode::Esc) => { phrase.name = old_name.clone(); self.mode = None; },
|
|
||||||
key!(KeyCode::Enter) => { self.mode = None; },
|
|
||||||
_ => return Ok(None)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => match from.event() {
|
|
||||||
key!(KeyCode::Up) => self.phrase = if self.phrase > 0 {
|
|
||||||
self.phrase - 1
|
|
||||||
} else {
|
|
||||||
self.phrases.len() - 1
|
|
||||||
},
|
|
||||||
key!(KeyCode::Down) => {
|
|
||||||
self.phrase = (self.phrase + 1) % self.phrases.len()
|
|
||||||
},
|
|
||||||
key!(KeyCode::Char('a')) => { // append new
|
|
||||||
let mut phrase = Phrase::default();
|
|
||||||
phrase.name = String::from("(no name)");
|
|
||||||
phrase.color = random_color();
|
|
||||||
self.phrases.push(Arc::new(RwLock::new(phrase)));
|
|
||||||
self.phrase = self.phrases.len() - 1;
|
|
||||||
},
|
|
||||||
key!(KeyCode::Char('i')) => { // insert new
|
|
||||||
let mut phrase = Phrase::default();
|
|
||||||
phrase.name = String::from("(no name)");
|
|
||||||
phrase.color = random_color();
|
|
||||||
self.phrases.insert(self.phrase + 1, Arc::new(RwLock::new(phrase)));
|
|
||||||
self.phrase += 1;
|
|
||||||
},
|
|
||||||
key!(KeyCode::Char('d')) => { // insert duplicate
|
|
||||||
let mut phrase = (*self.phrases[self.phrase].read().unwrap()).clone();
|
|
||||||
phrase.color = random_color_near(phrase.color, 0.2);
|
|
||||||
self.phrases.insert(self.phrase + 1, Arc::new(RwLock::new(phrase)));
|
|
||||||
self.phrase += 1;
|
|
||||||
},
|
|
||||||
key!(KeyCode::Char('c')) => { // change color
|
|
||||||
let mut phrase = self.phrases[self.phrase].write().unwrap();
|
|
||||||
phrase.color = random_color();
|
|
||||||
},
|
|
||||||
key!(KeyCode::Char('n')) => { // change name
|
|
||||||
let phrase = self.phrases[self.phrase].read().unwrap();
|
|
||||||
self.mode = Some(PhrasePoolMode::Rename(self.phrase, phrase.name.clone()));
|
|
||||||
},
|
|
||||||
_ => return Ok(None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(Some(true))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Content for PhraseEditor<Tui> {
|
impl Content for PhraseEditor<Tui> {
|
||||||
type Engine = Tui;
|
type Engine = Tui;
|
||||||
fn content (&self) -> impl Widget<Engine = Tui> {
|
fn content (&self) -> impl Widget<Engine = Tui> {
|
||||||
|
|
@ -247,35 +159,6 @@ impl Content for PhraseEditor<Tui> {
|
||||||
}).push_x(1))
|
}).push_x(1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Handle<Tui> for PhraseEditor<Tui> {
|
|
||||||
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
|
||||||
match from.event() {
|
|
||||||
key!(KeyCode::Char('`')) => {
|
|
||||||
self.mode = !self.mode;
|
|
||||||
},
|
|
||||||
key!(KeyCode::Up) => match self.entered {
|
|
||||||
true => { self.note_axis.point_dec(); },
|
|
||||||
false => { self.note_axis.start_dec(); },
|
|
||||||
},
|
|
||||||
key!(KeyCode::Down) => match self.entered {
|
|
||||||
true => { self.note_axis.point_inc(); },
|
|
||||||
false => { self.note_axis.start_inc(); },
|
|
||||||
},
|
|
||||||
key!(KeyCode::Left) => match self.entered {
|
|
||||||
true => { self.time_axis.point_dec(); },
|
|
||||||
false => { self.time_axis.start_dec(); },
|
|
||||||
},
|
|
||||||
key!(KeyCode::Right) => match self.entered {
|
|
||||||
true => { self.time_axis.point_inc(); },
|
|
||||||
false => { self.time_axis.start_inc(); },
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
return Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Ok(Some(true))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl PhraseEditor<Tui> {
|
impl PhraseEditor<Tui> {
|
||||||
const H_KEYS_OFFSET: usize = 5;
|
const H_KEYS_OFFSET: usize = 5;
|
||||||
/// Select which pattern to display. This pre-renders it to the buffer at full resolution.
|
/// Select which pattern to display. This pre-renders it to the buffer at full resolution.
|
||||||
|
|
|
||||||
52
crates/tek_sequencer/src/transport_cmd.rs
Normal file
52
crates/tek_sequencer/src/transport_cmd.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
use crate::*;
|
||||||
|
impl Handle<Tui> for TransportToolbar<Tui> {
|
||||||
|
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
||||||
|
match from.event() {
|
||||||
|
key!(KeyCode::Left) => { self.focus.prev(); },
|
||||||
|
key!(KeyCode::Right) => { self.focus.next(); },
|
||||||
|
_ => match self.focus {
|
||||||
|
TransportToolbarFocus::PlayPause => return self.handle_play_pause(from),
|
||||||
|
TransportToolbarFocus::Bpm => return self.handle_bpm(from),
|
||||||
|
TransportToolbarFocus::Quant => return self.handle_quant(from),
|
||||||
|
TransportToolbarFocus::Sync => return self.handle_sync(from),
|
||||||
|
TransportToolbarFocus::Clock => {/*todo*/},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Some(true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl TransportToolbar<Tui> {
|
||||||
|
fn handle_play_pause (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
||||||
|
match from.event() {
|
||||||
|
key!(KeyCode::Enter) => self.toggle_play().map(|_|())?,
|
||||||
|
_ => return Ok(None)
|
||||||
|
}
|
||||||
|
Ok(Some(true))
|
||||||
|
}
|
||||||
|
fn handle_bpm (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
||||||
|
match from.event() {
|
||||||
|
key!(KeyCode::Char(',')) => { self.bpm -= 1.0; },
|
||||||
|
key!(KeyCode::Char('.')) => { self.bpm += 1.0; },
|
||||||
|
key!(KeyCode::Char('<')) => { self.bpm -= 0.001; },
|
||||||
|
key!(KeyCode::Char('>')) => { self.bpm += 0.001; },
|
||||||
|
_ => return Ok(None)
|
||||||
|
}
|
||||||
|
Ok(Some(true))
|
||||||
|
}
|
||||||
|
fn handle_quant (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
||||||
|
match from.event() {
|
||||||
|
key!(KeyCode::Char(',')) => { self.quant = prev_note_length(self.quant); },
|
||||||
|
key!(KeyCode::Char('.')) => { self.quant = next_note_length(self.quant); },
|
||||||
|
_ => return Ok(None)
|
||||||
|
}
|
||||||
|
return Ok(Some(true))
|
||||||
|
}
|
||||||
|
fn handle_sync (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
||||||
|
match from.event() {
|
||||||
|
key!(KeyCode::Char(',')) => { self.sync = prev_note_length(self.sync); },
|
||||||
|
key!(KeyCode::Char('.')) => { self.sync = next_note_length(self.sync); },
|
||||||
|
_ => return Ok(None)
|
||||||
|
}
|
||||||
|
return Ok(Some(true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,55 +1,4 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
impl TransportToolbar<Tui> {
|
|
||||||
fn handle_play_pause (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
|
||||||
match from.event() {
|
|
||||||
key!(KeyCode::Enter) => self.toggle_play().map(|_|())?,
|
|
||||||
_ => return Ok(None)
|
|
||||||
}
|
|
||||||
Ok(Some(true))
|
|
||||||
}
|
|
||||||
fn handle_bpm (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
|
||||||
match from.event() {
|
|
||||||
key!(KeyCode::Char(',')) => { self.bpm -= 1.0; },
|
|
||||||
key!(KeyCode::Char('.')) => { self.bpm += 1.0; },
|
|
||||||
key!(KeyCode::Char('<')) => { self.bpm -= 0.001; },
|
|
||||||
key!(KeyCode::Char('>')) => { self.bpm += 0.001; },
|
|
||||||
_ => return Ok(None)
|
|
||||||
}
|
|
||||||
Ok(Some(true))
|
|
||||||
}
|
|
||||||
fn handle_quant (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
|
||||||
match from.event() {
|
|
||||||
key!(KeyCode::Char(',')) => { self.quant = prev_note_length(self.quant); },
|
|
||||||
key!(KeyCode::Char('.')) => { self.quant = next_note_length(self.quant); },
|
|
||||||
_ => return Ok(None)
|
|
||||||
}
|
|
||||||
return Ok(Some(true))
|
|
||||||
}
|
|
||||||
fn handle_sync (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
|
||||||
match from.event() {
|
|
||||||
key!(KeyCode::Char(',')) => { self.sync = prev_note_length(self.sync); },
|
|
||||||
key!(KeyCode::Char('.')) => { self.sync = next_note_length(self.sync); },
|
|
||||||
_ => return Ok(None)
|
|
||||||
}
|
|
||||||
return Ok(Some(true))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Handle<Tui> for TransportToolbar<Tui> {
|
|
||||||
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
|
||||||
match from.event() {
|
|
||||||
key!(KeyCode::Left) => { self.focus.prev(); },
|
|
||||||
key!(KeyCode::Right) => { self.focus.next(); },
|
|
||||||
_ => match self.focus {
|
|
||||||
TransportToolbarFocus::PlayPause => return self.handle_play_pause(from),
|
|
||||||
TransportToolbarFocus::Bpm => return self.handle_bpm(from),
|
|
||||||
TransportToolbarFocus::Quant => return self.handle_quant(from),
|
|
||||||
TransportToolbarFocus::Sync => return self.handle_sync(from),
|
|
||||||
TransportToolbarFocus::Clock => {/*todo*/},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(Some(true))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Content for TransportToolbar<Tui> {
|
impl Content for TransportToolbar<Tui> {
|
||||||
type Engine = Tui;
|
type Engine = Tui;
|
||||||
fn content (&self) -> impl Widget<Engine = Tui> {
|
fn content (&self) -> impl Widget<Engine = Tui> {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue