From 50b7d8a23d99ec9a07b4ddf6f9ff8411a72e9fe4 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Tue, 14 Jan 2025 17:34:10 +0100 Subject: [PATCH] use edn_command on all midi pool commands --- edn/src/edn_provide.rs | 4 +- midi/src/lib.rs | 7 +- midi/src/midi_edit.rs | 143 +++++++++++++++++++++++++++++++++++- midi/src/midi_edit_cmd.rs | 106 -------------------------- midi/src/midi_edit_tui.rs | 37 ---------- midi/src/midi_edit_view.edn | 0 midi/src/midi_player.rs | 22 +----- midi/src/midi_pool_cmd.rs | 63 +++++++++++----- 8 files changed, 194 insertions(+), 188 deletions(-) delete mode 100644 midi/src/midi_edit_cmd.rs delete mode 100644 midi/src/midi_edit_tui.rs delete mode 100644 midi/src/midi_edit_view.edn diff --git a/edn/src/edn_provide.rs b/edn/src/edn_provide.rs index e80ad0b3..ee52b042 100644 --- a/edn/src/edn_provide.rs +++ b/edn/src/edn_provide.rs @@ -4,14 +4,14 @@ use crate::*; ($lt:lifetime: $type:ty:|$self:ident:$State:ty|{ $($pat:pat => $expr:expr),* $(,)? }) => { impl<$lt> EdnProvide<$lt, $type> for $State { fn get > (&$lt $self, edn: &$lt EdnItem) -> Option<$type> { - Some(match edn.to_ref() { $(EdnItem::Sym($pat) => $expr),*, _ => return None }) + Some(match edn.to_ref() { $(EdnItem::Sym($pat) => $expr,)* _ => return None }) } } }; ($type:ty:|$self:ident:$State:ty|{ $($pat:pat => $expr:expr),* $(,)? }) => { impl<'a> EdnProvide<'a, $type> for $State { fn get > (&'a $self, edn: &'a EdnItem) -> Option<$type> { - Some(match edn.to_ref() { $(EdnItem::Sym($pat) => $expr),*, _ => return None }) + Some(match edn.to_ref() { $(EdnItem::Sym($pat) => $expr,)* _ => return None }) } } }; diff --git a/midi/src/lib.rs b/midi/src/lib.rs index 569aee85..7293dea4 100644 --- a/midi/src/lib.rs +++ b/midi/src/lib.rs @@ -13,11 +13,8 @@ mod midi_pool; pub use midi_pool::*; mod midi_pool_tui; pub use midi_pool_tui::*; mod midi_pool_cmd; pub use midi_pool_cmd::*; -mod midi_edit; pub use midi_edit::*; -mod midi_edit_cmd; pub use midi_edit_cmd::*; -mod midi_edit_tui; pub use midi_edit_tui::*; - -mod piano_h; pub use self::piano_h::*; +mod midi_edit; pub use midi_edit::*; +mod piano_h; pub use self::piano_h::*; pub(crate) use ::tek_time::*; pub(crate) use ::tek_jack::{*, jack::*}; diff --git a/midi/src/midi_edit.rs b/midi/src/midi_edit.rs index 3ea0f8a4..b0e972ed 100644 --- a/midi/src/midi_edit.rs +++ b/midi/src/midi_edit.rs @@ -1,4 +1,6 @@ use crate::*; +use self::MidiEditCommand::*; +use KeyCode::*; pub trait HasEditor { fn editor (&self) -> &Option; fn editor_mut (&mut self) -> &Option; @@ -46,7 +48,7 @@ impl Default for MidiEditor { mode: PianoHorizontal::new(None), size: Measure::new(), keymap: EdnKeymap( - EdnItem::::read_all(include_str!("midi_editor_keys.edn")) + EdnItem::::read_all(include_str!("midi_edit_keys.edn")) .expect("failed to load keymap for MidiEditor") ) } @@ -126,3 +128,142 @@ impl MidiViewer for MidiEditor { fn clip_mut (&mut self) -> &mut Option>> { self.mode.clip_mut() } fn set_clip (&mut self, p: Option<&Arc>>) { self.mode.set_clip(p) } } +has_size!(|self: MidiEditor|&self.size); +content!(TuiOut: |self: MidiEditor| { + self.autoscroll(); + //self.autozoom(); + self.size.of(&self.mode) +}); +impl MidiEditor { + pub fn clip_status (&self) -> impl Content + '_ { + let (color, name, length, looped) = if let Some(clip) = self.clip().as_ref().map(|p|p.read().unwrap()) { + (clip.color, clip.name.clone(), clip.length, clip.looped) + } else { + (ItemPalette::from(TuiTheme::g(64)), String::new().into(), 0, false) + }; + row!( + FieldV(color, "Edit", format!("{name} ({length})")), + FieldV(color, "Loop", looped.to_string()) + ) + } + pub fn edit_status (&self) -> impl Content + '_ { + let (color, length) = if let Some(clip) = self.clip().as_ref().map(|p|p.read().unwrap()) { + (clip.color, clip.length) + } else { + (ItemPalette::from(TuiTheme::g(64)), 0) + }; + let time_point = self.time_point(); + let time_zoom = self.time_zoom().get(); + let time_lock = if self.time_lock().get() { "[lock]" } else { " " }; + let note_point = format!("{:>3}", self.note_point()); + let note_name = format!("{:4}", Note::pitch_to_name(self.note_point())); + let note_len = format!("{:>4}", self.note_len()); + Bsp::e( + FieldV(color, "Time", format!("{length}/{time_zoom}+{time_point} {time_lock}")), + FieldV(color, "Note", format!("{note_name} {note_point} {note_len}")), + ) + } +} +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 for MidiEditCommand { + //fn from_edn <'a> (state: &MidiEditor, head: &EdnItem<&str>, tail: &'a [EdnItem]) -> 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>>), +} +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 for MidiEditCommand { + fn execute (self, state: &mut MidiEditor) -> Perhaps { + 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) + } +} diff --git a/midi/src/midi_edit_cmd.rs b/midi/src/midi_edit_cmd.rs deleted file mode 100644 index 9d023ee2..00000000 --- a/midi/src/midi_edit_cmd.rs +++ /dev/null @@ -1,106 +0,0 @@ -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 for MidiEditCommand { - //fn from_edn <'a> (state: &MidiEditor, head: &EdnItem<&str>, tail: &'a [EdnItem]) -> 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>>), -} -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 for MidiEditCommand { - fn execute (self, state: &mut MidiEditor) -> Perhaps { - 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) - } -} diff --git a/midi/src/midi_edit_tui.rs b/midi/src/midi_edit_tui.rs deleted file mode 100644 index fdeaed9f..00000000 --- a/midi/src/midi_edit_tui.rs +++ /dev/null @@ -1,37 +0,0 @@ -use crate::*; -has_size!(|self: MidiEditor|&self.size); -content!(TuiOut: |self: MidiEditor| { - self.autoscroll(); - //self.autozoom(); - self.size.of(&self.mode) -}); -impl MidiEditor { - pub fn clip_status (&self) -> impl Content + '_ { - let (color, name, length, looped) = if let Some(clip) = self.clip().as_ref().map(|p|p.read().unwrap()) { - (clip.color, clip.name.clone(), clip.length, clip.looped) - } else { - (ItemPalette::from(TuiTheme::g(64)), String::new().into(), 0, false) - }; - row!( - FieldV(color, "Edit", format!("{name} ({length})")), - FieldV(color, "Loop", looped.to_string()) - ) - } - pub fn edit_status (&self) -> impl Content + '_ { - let (color, length) = if let Some(clip) = self.clip().as_ref().map(|p|p.read().unwrap()) { - (clip.color, clip.length) - } else { - (ItemPalette::from(TuiTheme::g(64)), 0) - }; - let time_point = self.time_point(); - let time_zoom = self.time_zoom().get(); - let time_lock = if self.time_lock().get() { "[lock]" } else { " " }; - let note_point = format!("{:>3}", self.note_point()); - let note_name = format!("{:4}", Note::pitch_to_name(self.note_point())); - let note_len = format!("{:>4}", self.note_len()); - Bsp::e( - FieldV(color, "Time", format!("{length}/{time_zoom}+{time_point} {time_lock}")), - FieldV(color, "Note", format!("{note_name} {note_point} {note_len}")), - ) - } -} diff --git a/midi/src/midi_edit_view.edn b/midi/src/midi_edit_view.edn deleted file mode 100644 index e69de29b..00000000 diff --git a/midi/src/midi_player.rs b/midi/src/midi_player.rs index 8d49f05b..4723f7c8 100644 --- a/midi/src/midi_player.rs +++ b/midi/src/midi_player.rs @@ -1,14 +1,8 @@ use crate::*; - -pub trait MidiPlayerApi: MidiRecordApi + MidiPlaybackApi + Send + Sync {} - -impl MidiPlayerApi for MidiPlayer {} - pub trait HasPlayer { fn player (&self) -> &impl MidiPlayerApi; fn player_mut (&mut self) -> &mut impl MidiPlayerApi; } - #[macro_export] macro_rules! has_player { (|$self:ident:$Struct:ident$(<$($L:lifetime),*$($T:ident$(:$U:path)?),*>)?|$cb:expr) => { impl $(<$($L),*$($T $(: $U)?),*>)? HasPlayer for $Struct $(<$($L),*$($T),*>)? { @@ -17,7 +11,8 @@ pub trait HasPlayer { } } } - +pub trait MidiPlayerApi: MidiRecordApi + MidiPlaybackApi + Send + Sync {} +impl MidiPlayerApi for MidiPlayer {} /// Contains state for playing a clip pub struct MidiPlayer { /// State of clock and playhead @@ -83,17 +78,11 @@ impl MidiPlayer { ..Default::default() }) } - pub fn play_status (&self) -> impl Content { - ClipSelected::play_clip(self) - } - pub fn next_status (&self) -> impl Content { - ClipSelected::next_clip(self) - } } impl std::fmt::Debug for MidiPlayer { fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { f.debug_struct("MidiPlayer") - .field("clock", &self.clock) + .field("clock", &self.clock) .field("play_clip", &self.play_clip) .field("next_clip", &self.next_clip) .finish() @@ -129,7 +118,6 @@ impl HasMidiOuts for MidiPlayer { fn midi_outs_mut (&mut self) -> &mut Vec> { &mut self.midi_outs } fn midi_note (&mut self) -> &mut Vec { &mut self.note_buf } } - /// Hosts the JACK callback for a single MIDI player pub struct PlayerAudio<'a, T: MidiPlayerApi>( /// Player @@ -139,7 +127,6 @@ pub struct PlayerAudio<'a, T: MidiPlayerApi>( /// Note chunk buffer pub &'a mut Vec>>, ); - /// JACK process callback for a sequencer's clip player/recorder. impl Audio for PlayerAudio<'_, T> { fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control { @@ -166,7 +153,6 @@ impl Audio for PlayerAudio<'_, T> { Control::Continue } } - impl MidiRecordApi for MidiPlayer { fn recording (&self) -> bool { self.recording @@ -190,13 +176,11 @@ impl MidiRecordApi for MidiPlayer { &self.notes_in } } - impl MidiPlaybackApi for MidiPlayer { fn notes_out (&self) -> &Arc> { &self.notes_out } } - impl HasPlayClip for MidiPlayer { fn reset (&self) -> bool { self.reset diff --git a/midi/src/midi_pool_cmd.rs b/midi/src/midi_pool_cmd.rs index 5f4bc048..70919214 100644 --- a/midi/src/midi_pool_cmd.rs +++ b/midi/src/midi_pool_cmd.rs @@ -1,5 +1,11 @@ use crate::*; use KeyCode::*; +edn_provide!(bool: |self: MidiPool| {}); +edn_provide!(usize: |self: MidiPool| {}); +edn_provide!(MidiClip: |self: MidiPool| {}); +edn_provide!(PathBuf: |self: MidiPool| {}); +edn_provide!(Arc: |self: MidiPool| {}); +edn_provide!(ItemColor: |self: MidiPool| {}); #[derive(Clone, PartialEq, Debug)] pub enum PoolCommand { Show(bool), /// Update the contents of the clip pool @@ -20,7 +26,7 @@ edn_command!(PoolCommand: |state: MidiPool| { ("select" [i: usize] Self::Select(i.expect("no index"))) ("clip" [a, ..b] Self::Clip(PoolClipCommand::from_edn(state, &a.to_ref(), b))) ("rename" [a, ..b] Self::Rename(ClipRenameCommand::from_edn(state, &a.to_ref(), b))) - ("length" [a, ..b] Self::Length(ClipRenameCommand::from_edn(state, &a.to_ref(), b))) + ("length" [a, ..b] Self::Length(ClipLengthCommand::from_edn(state, &a.to_ref(), b))) ("import" [a, ..b] Self::Import(FileBrowserCommand::from_edn(state, &a.to_ref(), b))) ("export" [a, ..b] Self::Export(FileBrowserCommand::from_edn(state, &a.to_ref(), b))) }); @@ -44,6 +50,44 @@ edn_command!(PoolClipCommand: |state: MidiPool| { ("set-length" [i: usize, l: usize] Self::SetLength(i.expect("no index"), l.expect("no length"))) ("set-color" [i: usize, c: ItemColor] Self::SetColor(i.expect("no index"), c.expect("no color"))) }); +#[derive(Clone, Debug, PartialEq)] pub enum ClipRenameCommand { + Begin, + Cancel, + Confirm, + Set(Arc), +} +edn_command!(ClipRenameCommand: |state: MidiPool| { + ("begin" [] Self::Begin) + ("cancel" [] Self::Cancel) + ("confirm" [] Self::Confirm) + ("set" [n: Arc] Self::Set(n.expect("no name"))) +}); +#[derive(Copy, Clone, Debug, PartialEq)] pub enum ClipLengthCommand { + Begin, + Cancel, + Set(usize), + Next, + Prev, + Inc, + Dec, +} +edn_command!(ClipLengthCommand: |state: MidiPool| { + ("begin" [] Self::Begin) + ("cancel" [] Self::Cancel) + ("next" [] Self::Next) + ("prev" [] Self::Prev) + ("inc" [] Self::Inc) + ("dec" [] Self::Dec) + ("set" [l: usize] Self::Set(l.expect("no length"))) +}); +edn_command!(FileBrowserCommand: |state: MidiPool| { + ("begin" [] Self::Begin) + ("cancel" [] Self::Cancel) + ("confirm" [] Self::Confirm) + ("select" [i: usize] Self::Select(i.expect("no index"))) + ("chdir" [p: PathBuf] Self::Chdir(p.expect("no path"))) + ("filter" [f: Arc] Self::Filter(f.expect("no filter"))) +}); impl Command for PoolClipCommand { fn execute (self, model: &mut T) -> Perhaps { use PoolClipCommand::*; @@ -281,16 +325,6 @@ input_to_command!(FileBrowserCommand: |state: MidiPool, input: Event|{ unreachable!() } }); -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum ClipLengthCommand { - Begin, - Cancel, - Set(usize), - Next, - Prev, - Inc, - Dec, -} command!(|self: ClipLengthCommand,state:MidiPool|{ use ClipLengthCommand::*; use ClipLengthFocus::*; @@ -364,13 +398,6 @@ impl InputToCommand for ClipRenameCommand { } } } -#[derive(Clone, Debug, PartialEq)] -pub enum ClipRenameCommand { - Begin, - Cancel, - Confirm, - Set(Arc), -} impl Command for ClipRenameCommand { fn execute (self, state: &mut MidiPool) -> Perhaps { use ClipRenameCommand::*;