wip: add note with (Shift-)Enter

This commit is contained in:
🪞👃🪞 2024-12-19 14:46:45 +01:00
parent d07ed00034
commit 6be71a4413
6 changed files with 65 additions and 44 deletions

View file

@ -1,22 +1,23 @@
use crate::*;
use ClockCommand::{Play, Pause};
use KeyCode::{Char, Delete};
use KeyCode::{Char, Delete, Tab};
/// Root view for standalone `tek_arranger`
pub struct ArrangerTui {
jack: Arc<RwLock<JackClient>>,
pub clock: ClockModel,
pub phrases: PhraseListModel,
pub tracks: Vec<ArrangerTrack>,
pub scenes: Vec<ArrangerScene>,
pub splits: [u16;2],
pub selected: ArrangerSelection,
pub mode: ArrangerMode,
pub color: ItemPalette,
pub size: Measure<Tui>,
pub note_buf: Vec<u8>,
pub midi_buf: Vec<Vec<Vec<u8>>>,
pub editor: PhraseEditorModel,
pub perf: PerfModel,
jack: Arc<RwLock<JackClient>>,
pub clock: ClockModel,
pub phrases: PhraseListModel,
pub tracks: Vec<ArrangerTrack>,
pub scenes: Vec<ArrangerScene>,
pub splits: [u16;2],
pub selected: ArrangerSelection,
pub mode: ArrangerMode,
pub color: ItemPalette,
pub size: Measure<Tui>,
pub note_buf: Vec<u8>,
pub midi_buf: Vec<Vec<Vec<u8>>>,
pub editor: PhraseEditorModel,
pub perf: PerfModel,
pub show_pool: bool,
}
from_jack!(|jack| ArrangerTui {
let clock = ClockModel::from(jack);
@ -26,19 +27,20 @@ from_jack!(|jack| ArrangerTui {
)));
Self {
clock,
phrases: PhraseListModel::from(&phrase),
editor: PhraseEditorModel::from(&phrase),
selected: ArrangerSelection::Clip(0, 0),
scenes: vec![],
tracks: vec![],
color: TuiTheme::bg().into(),
mode: ArrangerMode::V(1),
size: Measure::new(),
splits: [12, 20],
midi_buf: vec![vec![];65536],
note_buf: vec![],
perf: PerfModel::default(),
jack: jack.clone(),
phrases: PhraseListModel::from(&phrase),
editor: PhraseEditorModel::from(&phrase),
selected: ArrangerSelection::Clip(0, 0),
scenes: vec![],
tracks: vec![],
color: TuiTheme::bg().into(),
mode: ArrangerMode::V(1),
size: Measure::new(),
splits: [12, 20],
midi_buf: vec![vec![];65536],
note_buf: vec![],
perf: PerfModel::default(),
show_pool: false,
jack: jack.clone(),
}
});
render!(<Tui>|self: ArrangerTui|{
@ -62,7 +64,11 @@ render!(<Tui>|self: ArrangerTui|{
let play = Fixed::wh(5, 2, PlayPause(self.clock.is_rolling()));
let transport = TransportView::from((self, None, true));
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!([
&self.size,
Fill::w(Fixed::h(20, arranger())),
@ -124,6 +130,7 @@ handle!(<Tui>|self: ArrangerTui, input|ArrangerCommand::execute_with_state(self,
Zoom(usize),
Phrases(PhrasesCommand),
Editor(PhraseCommand),
ShowPool(bool)
}
input_to_command!(ArrangerCommand: <Tui>|state:ArrangerTui,input|{
use ArrangerSelection as Selected;
@ -163,11 +170,18 @@ input_to_command!(ArrangerCommand: <Tui>|state:ArrangerTui,input|{
Selected::Scene(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() {
Selected::Mix => to_arranger_mix_command(input),
Selected::Track(t) => to_arranger_track_command(input, t),
Selected::Scene(s) => to_arranger_scene_command(input, s),
Selected::Clip(t, s) => to_arranger_clip_command(input, t, s),
Selected::Track(t) => to_arranger_track_command(input,
t, state.tracks.len()),
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) {
Some(Editor(command))
} else if let Some(command) = PhrasesCommand::input_to_command(&state.phrases, input) {
@ -213,6 +227,10 @@ command!(|self:ArrangerCommand,state:ArrangerTui|{
state.color = palette;
Some(Color(old))
},
ShowPool(show) => {
state.show_pool = show;
None
},
_ => { todo!() }
}
});

View file

@ -1,6 +1,6 @@
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 ArrangerCommand as Cmd;
use ArrangerSelection as Select;

View file

@ -81,12 +81,16 @@ render!(<Tui>|self: ArrangerVCursor|render(move|to: &mut TuiOutput|{
let focused = self.focused;
let selected = self.selected;
let get_track_area = |t: usize| [
self.scenes_w + area.x() + self.cols[t].1 as u16, area.y(),
self.cols[t].0 as u16, area.h(),
self.scenes_w + area.x() + self.cols[t].1 as u16,
area.y(),
self.cols[t].0 as u16,
area.h(),
];
let get_scene_area = |s: usize| [
area.x(), self.header_h + area.y() + (self.rows[s].1 / PPQ) as u16,
area.w(), (self.rows[s].0 / PPQ) as u16
area.x(),
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| [
self.scenes_w + area.x() + self.cols[t].1 as u16,

View file

@ -73,14 +73,14 @@ pub enum ArrangerSceneCommand {
SetZoom(usize),
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 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)),
key_pat!(Char('s')) => Cmd::Select(Select::Scene((s + 1) % len)),
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)),

View file

@ -86,14 +86,14 @@ impl<'a, T: ArrangerTrackApi, H: HasTracks<T>> Audio for TracksAudio<'a, T, H> {
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 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)),
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)),

View file

@ -1,5 +1,4 @@
use crate::*;
use Ordering::Relaxed;
use KeyCode::{Char, Up, Down, Left, Right};
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(prev_note_length(time_zoom())),
key_pat!(Char('+')) => SetTimeZoom(prev_note_length(time_zoom())),
key_pat!(Char('a')) => AppendNote,
key_pat!(Char('s')) => PutNote,
key_pat!(Enter) => PutNote,
key_pat!(Ctrl-Enter) => AppendNote,
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(prev_note_length(note_len())), // TODO: 3plet