mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +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 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!() }
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue