mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +01:00
wip: add note with (Shift-)Enter
This commit is contained in:
parent
d07ed00034
commit
6be71a4413
6 changed files with 65 additions and 44 deletions
|
|
@ -1,22 +1,23 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use ClockCommand::{Play, Pause};
|
use ClockCommand::{Play, Pause};
|
||||||
use KeyCode::{Char, Delete};
|
use KeyCode::{Char, Delete, Tab};
|
||||||
/// Root view for standalone `tek_arranger`
|
/// Root view for standalone `tek_arranger`
|
||||||
pub struct ArrangerTui {
|
pub struct ArrangerTui {
|
||||||
jack: Arc<RwLock<JackClient>>,
|
jack: Arc<RwLock<JackClient>>,
|
||||||
pub clock: ClockModel,
|
pub clock: ClockModel,
|
||||||
pub phrases: PhraseListModel,
|
pub phrases: PhraseListModel,
|
||||||
pub tracks: Vec<ArrangerTrack>,
|
pub tracks: Vec<ArrangerTrack>,
|
||||||
pub scenes: Vec<ArrangerScene>,
|
pub scenes: Vec<ArrangerScene>,
|
||||||
pub splits: [u16;2],
|
pub splits: [u16;2],
|
||||||
pub selected: ArrangerSelection,
|
pub selected: ArrangerSelection,
|
||||||
pub mode: ArrangerMode,
|
pub mode: ArrangerMode,
|
||||||
pub color: ItemPalette,
|
pub color: ItemPalette,
|
||||||
pub size: Measure<Tui>,
|
pub size: Measure<Tui>,
|
||||||
pub note_buf: Vec<u8>,
|
pub note_buf: Vec<u8>,
|
||||||
pub midi_buf: Vec<Vec<Vec<u8>>>,
|
pub midi_buf: Vec<Vec<Vec<u8>>>,
|
||||||
pub editor: PhraseEditorModel,
|
pub editor: PhraseEditorModel,
|
||||||
pub perf: PerfModel,
|
pub perf: PerfModel,
|
||||||
|
pub show_pool: bool,
|
||||||
}
|
}
|
||||||
from_jack!(|jack| ArrangerTui {
|
from_jack!(|jack| ArrangerTui {
|
||||||
let clock = ClockModel::from(jack);
|
let clock = ClockModel::from(jack);
|
||||||
|
|
@ -26,19 +27,20 @@ from_jack!(|jack| ArrangerTui {
|
||||||
)));
|
)));
|
||||||
Self {
|
Self {
|
||||||
clock,
|
clock,
|
||||||
phrases: PhraseListModel::from(&phrase),
|
phrases: PhraseListModel::from(&phrase),
|
||||||
editor: PhraseEditorModel::from(&phrase),
|
editor: PhraseEditorModel::from(&phrase),
|
||||||
selected: ArrangerSelection::Clip(0, 0),
|
selected: ArrangerSelection::Clip(0, 0),
|
||||||
scenes: vec![],
|
scenes: vec![],
|
||||||
tracks: vec![],
|
tracks: vec![],
|
||||||
color: TuiTheme::bg().into(),
|
color: TuiTheme::bg().into(),
|
||||||
mode: ArrangerMode::V(1),
|
mode: ArrangerMode::V(1),
|
||||||
size: Measure::new(),
|
size: Measure::new(),
|
||||||
splits: [12, 20],
|
splits: [12, 20],
|
||||||
midi_buf: vec![vec![];65536],
|
midi_buf: vec![vec![];65536],
|
||||||
note_buf: vec![],
|
note_buf: vec![],
|
||||||
perf: PerfModel::default(),
|
perf: PerfModel::default(),
|
||||||
jack: jack.clone(),
|
show_pool: false,
|
||||||
|
jack: jack.clone(),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
render!(<Tui>|self: ArrangerTui|{
|
render!(<Tui>|self: ArrangerTui|{
|
||||||
|
|
@ -62,7 +64,11 @@ render!(<Tui>|self: ArrangerTui|{
|
||||||
let play = Fixed::wh(5, 2, PlayPause(self.clock.is_rolling()));
|
let play = Fixed::wh(5, 2, PlayPause(self.clock.is_rolling()));
|
||||||
let transport = TransportView::from((self, None, true));
|
let transport = TransportView::from((self, None, true));
|
||||||
let with_transport = |x|col!([row!(![&play, &transport]), &x]);
|
let with_transport = |x|col!([row!(![&play, &transport]), &x]);
|
||||||
let with_pool = |x|Split::left(false, self.splits[1], PhraseListView(&self.phrases), x);
|
let with_pool = |x|Split::left(false, if self.show_pool {
|
||||||
|
self.splits[1]
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}, PhraseListView(&self.phrases), x);
|
||||||
with_transport(with_pool(col!([
|
with_transport(with_pool(col!([
|
||||||
&self.size,
|
&self.size,
|
||||||
Fill::w(Fixed::h(20, arranger())),
|
Fill::w(Fixed::h(20, arranger())),
|
||||||
|
|
@ -124,6 +130,7 @@ handle!(<Tui>|self: ArrangerTui, input|ArrangerCommand::execute_with_state(self,
|
||||||
Zoom(usize),
|
Zoom(usize),
|
||||||
Phrases(PhrasesCommand),
|
Phrases(PhrasesCommand),
|
||||||
Editor(PhraseCommand),
|
Editor(PhraseCommand),
|
||||||
|
ShowPool(bool)
|
||||||
}
|
}
|
||||||
input_to_command!(ArrangerCommand: <Tui>|state:ArrangerTui,input|{
|
input_to_command!(ArrangerCommand: <Tui>|state:ArrangerTui,input|{
|
||||||
use ArrangerSelection as Selected;
|
use ArrangerSelection as Selected;
|
||||||
|
|
@ -163,11 +170,18 @@ input_to_command!(ArrangerCommand: <Tui>|state:ArrangerTui,input|{
|
||||||
Selected::Scene(s) => return None,
|
Selected::Scene(s) => return None,
|
||||||
Selected::Clip(t, s) => return None,
|
Selected::Clip(t, s) => return None,
|
||||||
},
|
},
|
||||||
|
// Tab: Toggle visibility of phrase pool column
|
||||||
|
key_pat!(Tab) =>
|
||||||
|
ShowPool(!state.show_pool),
|
||||||
_ => match state.selected() {
|
_ => match state.selected() {
|
||||||
Selected::Mix => to_arranger_mix_command(input),
|
Selected::Mix => to_arranger_mix_command(input),
|
||||||
Selected::Track(t) => to_arranger_track_command(input, t),
|
Selected::Track(t) => to_arranger_track_command(input,
|
||||||
Selected::Scene(s) => to_arranger_scene_command(input, s),
|
t, state.tracks.len()),
|
||||||
Selected::Clip(t, s) => to_arranger_clip_command(input, t, s),
|
Selected::Scene(s) => to_arranger_scene_command(input,
|
||||||
|
s, state.scenes.len()),
|
||||||
|
Selected::Clip(t, s) => to_arranger_clip_command(input,
|
||||||
|
t, state.tracks.len(),
|
||||||
|
s, state.scenes.len()),
|
||||||
}.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(Editor(command))
|
Some(Editor(command))
|
||||||
} else if let Some(command) = PhrasesCommand::input_to_command(&state.phrases, input) {
|
} else if let Some(command) = PhrasesCommand::input_to_command(&state.phrases, input) {
|
||||||
|
|
@ -213,6 +227,10 @@ command!(|self:ArrangerCommand,state:ArrangerTui|{
|
||||||
state.color = palette;
|
state.color = palette;
|
||||||
Some(Color(old))
|
Some(Color(old))
|
||||||
},
|
},
|
||||||
|
ShowPool(show) => {
|
||||||
|
state.show_pool = show;
|
||||||
|
None
|
||||||
|
},
|
||||||
_ => { todo!() }
|
_ => { todo!() }
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
pub fn to_arranger_clip_command (input: &TuiInput, t: usize, s: usize) -> Option<ArrangerCommand> {
|
pub fn to_arranger_clip_command (input: &TuiInput, t: usize, len_t: usize, s: usize, len_s: usize) -> Option<ArrangerCommand> {
|
||||||
use KeyCode::{Char, Up, Down, Left, Right, Delete};
|
use KeyCode::{Char, Up, Down, Left, Right, Delete};
|
||||||
use ArrangerCommand as Cmd;
|
use ArrangerCommand as Cmd;
|
||||||
use ArrangerSelection as Select;
|
use ArrangerSelection as Select;
|
||||||
|
|
|
||||||
|
|
@ -81,12 +81,16 @@ render!(<Tui>|self: ArrangerVCursor|render(move|to: &mut TuiOutput|{
|
||||||
let focused = self.focused;
|
let focused = self.focused;
|
||||||
let selected = self.selected;
|
let selected = self.selected;
|
||||||
let get_track_area = |t: usize| [
|
let get_track_area = |t: usize| [
|
||||||
self.scenes_w + area.x() + self.cols[t].1 as u16, area.y(),
|
self.scenes_w + area.x() + self.cols[t].1 as u16,
|
||||||
self.cols[t].0 as u16, area.h(),
|
area.y(),
|
||||||
|
self.cols[t].0 as u16,
|
||||||
|
area.h(),
|
||||||
];
|
];
|
||||||
let get_scene_area = |s: usize| [
|
let get_scene_area = |s: usize| [
|
||||||
area.x(), self.header_h + area.y() + (self.rows[s].1 / PPQ) as u16,
|
area.x(),
|
||||||
area.w(), (self.rows[s].0 / PPQ) as u16
|
self.header_h + area.y() + (self.rows[s].1 / PPQ) as u16,
|
||||||
|
area.w(),
|
||||||
|
(self.rows[s].0 / PPQ) as u16
|
||||||
];
|
];
|
||||||
let get_clip_area = |t: usize, s: usize| [
|
let get_clip_area = |t: usize, s: usize| [
|
||||||
self.scenes_w + area.x() + self.cols[t].1 as u16,
|
self.scenes_w + area.x() + self.cols[t].1 as u16,
|
||||||
|
|
|
||||||
|
|
@ -73,14 +73,14 @@ pub enum ArrangerSceneCommand {
|
||||||
SetZoom(usize),
|
SetZoom(usize),
|
||||||
SetColor(usize, ItemPalette),
|
SetColor(usize, ItemPalette),
|
||||||
}
|
}
|
||||||
pub fn to_arranger_scene_command (input: &TuiInput, s: usize) -> Option<ArrangerCommand> {
|
pub fn to_arranger_scene_command (input: &TuiInput, s: usize, len: usize) -> Option<ArrangerCommand> {
|
||||||
use KeyCode::{Char, Up, Down, Right, Enter, Delete};
|
use KeyCode::{Char, Up, Down, Right, Enter, Delete};
|
||||||
use ArrangerCommand as Cmd;
|
use ArrangerCommand as Cmd;
|
||||||
use ArrangerSelection as Select;
|
use ArrangerSelection as Select;
|
||||||
use ArrangerSceneCommand as Scene;
|
use ArrangerSceneCommand as Scene;
|
||||||
Some(match input.event() {
|
Some(match input.event() {
|
||||||
key_pat!(Char('w')) => Cmd::Select(if s > 0 { Select::Scene(s - 1) } else { Select::Mix }),
|
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)),
|
key_pat!(Char('s')) => Cmd::Select(Select::Scene((s + 1) % len)),
|
||||||
key_pat!(Char('d')) => Cmd::Select(Select::Clip(0, s)),
|
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)),
|
||||||
|
|
|
||||||
|
|
@ -86,14 +86,14 @@ impl<'a, T: ArrangerTrackApi, H: HasTracks<T>> Audio for TracksAudio<'a, T, H> {
|
||||||
Control::Continue
|
Control::Continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn to_arranger_track_command (input: &TuiInput, t: usize) -> Option<ArrangerCommand> {
|
pub fn to_arranger_track_command (input: &TuiInput, t: usize, len: usize) -> Option<ArrangerCommand> {
|
||||||
use ArrangerCommand::*;
|
use ArrangerCommand::*;
|
||||||
use ArrangerSelection as Selected;
|
use ArrangerSelection as Selected;
|
||||||
use ArrangerTrackCommand as Tracks;
|
use ArrangerTrackCommand as Tracks;
|
||||||
Some(match input.event() {
|
Some(match input.event() {
|
||||||
key_pat!(Char('s')) => Select(Selected::Clip(t, 0)),
|
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('a')) => Select(if t > 0 { Selected::Track(t - 1) } else { Selected::Mix }),
|
||||||
key_pat!(Char('d')) => Select(Selected::Track(t + 1)),
|
key_pat!(Char('d')) => Select(Selected::Track((t + 1) % len)),
|
||||||
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!(Char('<')) => Track(Tracks::Swap(t, t - 1)),
|
key_pat!(Char('<')) => Track(Tracks::Swap(t, t - 1)),
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use Ordering::Relaxed;
|
|
||||||
use KeyCode::{Char, Up, Down, Left, Right};
|
use KeyCode::{Char, Up, Down, Left, Right};
|
||||||
use PhraseCommand::*;
|
use PhraseCommand::*;
|
||||||
|
|
||||||
|
|
@ -64,8 +63,8 @@ impl InputToCommand<Tui, PhraseEditorModel> for PhraseCommand {
|
||||||
key_pat!(Char('_')) => SetTimeZoom(next_note_length(time_zoom())),
|
key_pat!(Char('_')) => SetTimeZoom(next_note_length(time_zoom())),
|
||||||
key_pat!(Char('=')) => SetTimeZoom(prev_note_length(time_zoom())),
|
key_pat!(Char('=')) => SetTimeZoom(prev_note_length(time_zoom())),
|
||||||
key_pat!(Char('+')) => SetTimeZoom(prev_note_length(time_zoom())),
|
key_pat!(Char('+')) => SetTimeZoom(prev_note_length(time_zoom())),
|
||||||
key_pat!(Char('a')) => AppendNote,
|
key_pat!(Enter) => PutNote,
|
||||||
key_pat!(Char('s')) => PutNote,
|
key_pat!(Ctrl-Enter) => AppendNote,
|
||||||
key_pat!(Char(',')) => SetNoteLength(prev_note_length(note_len())), // TODO: no 3plet
|
key_pat!(Char(',')) => SetNoteLength(prev_note_length(note_len())), // TODO: no 3plet
|
||||||
key_pat!(Char('.')) => SetNoteLength(next_note_length(note_len())),
|
key_pat!(Char('.')) => SetNoteLength(next_note_length(note_len())),
|
||||||
key_pat!(Char('<')) => SetNoteLength(prev_note_length(note_len())), // TODO: 3plet
|
key_pat!(Char('<')) => SetNoteLength(prev_note_length(note_len())), // TODO: 3plet
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue