mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 20:56:43 +01:00
106 lines
5.8 KiB
Rust
106 lines
5.8 KiB
Rust
use crate::*;
|
|
use self::MidiEditCommand::*;
|
|
use KeyCode::*;
|
|
edn_provide!(bool: |self: MidiEditor|{
|
|
":true" => true,
|
|
":false" => false
|
|
});
|
|
edn_provide!(usize: |self: MidiEditor|{
|
|
":note-length" => self.note_len(),
|
|
":note-point" => self.note_point(),
|
|
":time-point" => self.time_point(),
|
|
":time-zoom" => self.time_zoom().get(),
|
|
});
|
|
edn_command!(MidiEditCommand: |state: MidiEditor| {
|
|
("note/put" [a: bool] Self::PutNote)
|
|
("note/del" [a: bool] Self::PutNote)
|
|
("note/pos" [a: usize] Self::SetNoteCursor(a.expect("no note cursor")))
|
|
("note/len" [a: usize] Self::SetNoteLength(a.expect("no note length")))
|
|
("time/pos" [a: usize] Self::SetTimeCursor(a.expect("no time cursor")))
|
|
("time/zoom" [a: usize] Self::SetTimeZoom(a.expect("no time zoom")))
|
|
("time/lock" [a: bool] Self::SetTimeLock(a.expect("no time lock")))
|
|
});
|
|
//impl EdnCommand<MidiEditor> for MidiEditCommand {
|
|
//fn from_edn <'a> (state: &MidiEditor, head: &EdnItem<&str>, tail: &'a [EdnItem<String>]) -> Self {
|
|
//use EdnItem::*;
|
|
//match (head, tail) {
|
|
//(Key("note/put"), [a]) => Self::PutNote,
|
|
//(Key("note/del"), [a]) => Self::AppendNote,
|
|
//(Key("note/dur"), [a]) => Self::AppendNote,
|
|
//(Key("note/range"), [a]) => Self::AppendNote,
|
|
//(Key("note/pos"), [a]) => Self::AppendNote,
|
|
//(Key("time/pos"), [a]) => Self::AppendNote,
|
|
//(Key("time/zoom"), [a]) => Self::AppendNote,
|
|
//(Key("time/lock"), [a]) => Self::AppendNote,
|
|
//_ => todo!()
|
|
//}
|
|
//}
|
|
//}
|
|
#[derive(Clone, Debug)] pub enum MidiEditCommand {
|
|
// TODO: 1-9 seek markers that by default start every 8th of the clip
|
|
AppendNote,
|
|
PutNote,
|
|
SetNoteCursor(usize),
|
|
SetNoteLength(usize),
|
|
SetNoteScroll(usize),
|
|
SetTimeCursor(usize),
|
|
SetTimeScroll(usize),
|
|
SetTimeZoom(usize),
|
|
SetTimeLock(bool),
|
|
Show(Option<Arc<RwLock<MidiClip>>>),
|
|
}
|
|
handle!(TuiIn: |self: MidiEditor, input|MidiEditCommand::execute_with_state(self, input.event()));
|
|
keymap!(KEYS_MIDI_EDITOR = |s: MidiEditor, _input: Event| MidiEditCommand {
|
|
key(Up) => SetNoteCursor(s.note_point() + 1),
|
|
key(Char('w')) => SetNoteCursor(s.note_point() + 1),
|
|
key(Down) => SetNoteCursor(s.note_point().saturating_sub(1)),
|
|
key(Char('s')) => SetNoteCursor(s.note_point().saturating_sub(1)),
|
|
key(Left) => SetTimeCursor(s.time_point().saturating_sub(s.note_len())),
|
|
key(Char('a')) => SetTimeCursor(s.time_point().saturating_sub(s.note_len())),
|
|
key(Right) => SetTimeCursor((s.time_point() + s.note_len()) % s.clip_length()),
|
|
ctrl(alt(key(Up))) => SetNoteScroll(s.note_point() + 3),
|
|
ctrl(alt(key(Down))) => SetNoteScroll(s.note_point().saturating_sub(3)),
|
|
ctrl(alt(key(Left))) => SetTimeScroll(s.time_point().saturating_sub(s.time_zoom().get())),
|
|
ctrl(alt(key(Right))) => SetTimeScroll((s.time_point() + s.time_zoom().get()) % s.clip_length()),
|
|
ctrl(key(Up)) => SetNoteScroll(s.note_lo().get() + 1),
|
|
ctrl(key(Down)) => SetNoteScroll(s.note_lo().get().saturating_sub(1)),
|
|
ctrl(key(Left)) => SetTimeScroll(s.time_start().get().saturating_sub(s.note_len())),
|
|
ctrl(key(Right)) => SetTimeScroll(s.time_start().get() + s.note_len()),
|
|
alt(key(Up)) => SetNoteCursor(s.note_point() + 3),
|
|
alt(key(Down)) => SetNoteCursor(s.note_point().saturating_sub(3)),
|
|
alt(key(Left)) => SetTimeCursor(s.time_point().saturating_sub(s.time_zoom().get())),
|
|
alt(key(Right)) => SetTimeCursor((s.time_point() + s.time_zoom().get()) % s.clip_length()),
|
|
key(Char('d')) => SetTimeCursor((s.time_point() + s.note_len()) % s.clip_length()),
|
|
key(Char('z')) => SetTimeLock(!s.time_lock().get()),
|
|
key(Char('-')) => SetTimeZoom(if s.time_lock().get() { s.time_zoom().get() } else { NoteDuration::next(s.time_zoom().get()) }),
|
|
key(Char('_')) => SetTimeZoom(if s.time_lock().get() { s.time_zoom().get() } else { NoteDuration::next(s.time_zoom().get()) }),
|
|
key(Char('=')) => SetTimeZoom(if s.time_lock().get() { s.time_zoom().get() } else { NoteDuration::prev(s.time_zoom().get()) }),
|
|
key(Char('+')) => SetTimeZoom(if s.time_lock().get() { s.time_zoom().get() } else { NoteDuration::prev(s.time_zoom().get()) }),
|
|
key(Enter) => PutNote,
|
|
ctrl(key(Enter)) => AppendNote,
|
|
key(Char(',')) => SetNoteLength(NoteDuration::prev(s.note_len())),
|
|
key(Char('.')) => SetNoteLength(NoteDuration::next(s.note_len())),
|
|
key(Char('<')) => SetNoteLength(NoteDuration::prev(s.note_len())),
|
|
key(Char('>')) => SetNoteLength(NoteDuration::next(s.note_len())),
|
|
//// TODO: kpat!(Char('/')) => // toggle 3plet
|
|
//// TODO: kpat!(Char('?')) => // toggle dotted
|
|
});
|
|
impl Command<MidiEditor> for MidiEditCommand {
|
|
fn execute (self, state: &mut MidiEditor) -> Perhaps<Self> {
|
|
use MidiEditCommand::*;
|
|
match self {
|
|
Show(clip) => { state.set_clip(clip.as_ref()); },
|
|
PutNote => { state.put_note(false); },
|
|
AppendNote => { state.put_note(true); },
|
|
SetTimeZoom(x) => { state.time_zoom().set(x); state.redraw(); },
|
|
SetTimeLock(x) => { state.time_lock().set(x); },
|
|
SetTimeScroll(x) => { state.time_start().set(x); },
|
|
SetNoteScroll(x) => { state.note_lo().set(x.min(127)); },
|
|
SetNoteLength(x) => { state.set_note_len(x); },
|
|
SetTimeCursor(x) => { state.set_time_point(x); },
|
|
SetNoteCursor(note) => { state.set_note_point(note.min(127)); },
|
|
_ => todo!("{:?}", self)
|
|
}
|
|
Ok(None)
|
|
}
|
|
}
|