//! Handling of input events. use crate::*; handle!{ App |self, e| { if handle_modal(e)? { return Ok(true) } Ok(if self.entered { handle_focused(self, e)? || handle_keymap(self, e, KEYMAP_GLOBAL)? || handle_keymap(self, e, crate::control::KEYMAP_FOCUS)? } else { handle_keymap(self, e, KEYMAP_GLOBAL)? || handle_keymap(self, e, crate::control::KEYMAP_FOCUS)? || handle_focused(self, e)? }) } } fn handle_modal (e: &AppEvent) -> Usually { let mut handled = false; let mut close = false; if let Some(ref mut modal) = *MODAL.lock().unwrap() { if modal.handle(e)? { handled = true; if modal.exited() { close = true; } }; } if close { *MODAL.lock().unwrap() = None; } Ok(handled) } fn handle_focused (state: &mut App, e: &AppEvent) -> Usually { unimplemented!() //match state.section { //AppFocus::Transport => state.transport.handle(e), //AppFocus::Arranger => state.arranger.sequencer_mut().map(|s|s.handle(e)), //AppFocus::Sequencer => state.arranger.sequencer_mut().map(|s|s.handle(e)), //AppFocus::Chain => Ok(false)[>if state.entered { //handle_device(state, e)? || //handle_keymap(state, e, crate::control::KEYMAP_CHAIN)? //} else { //handle_keymap(state, e, crate::control::KEYMAP_CHAIN)? || handle_device(state, e)? //})*/ //} } fn handle_device (state: &mut App, e: &AppEvent) -> Usually { state.mixer.track() .and_then(|track|track.device_mut()) .map(|mut device|device.handle(e)) .transpose() .map(|x|x.unwrap_or(false)) } /// Global key bindings. pub const KEYMAP_GLOBAL: &'static [KeyBinding] = keymap!(App { [Char(' '), NONE, "play_toggle", "play or pause", |app: &mut App| { app.transport.toggle_play()?; Ok(true) }], [Char('r'), NONE, "record_toggle", "toggle recording", |app: &mut App| { app.arranger.track_mut().map(|t|t.toggle_record()); Ok(true) }], [Char('o'), NONE, "overdub_toggle", "toggle overdub", |app: &mut App| { app.arranger.track_mut().map(|t|t.toggle_overdub()); Ok(true) }], [Char('m'), NONE, "monitor_toggle", "toggle monitor", |app: &mut App| { app.arranger.track_mut().map(|t|t.toggle_monitor()); Ok(true) }], [Char('+'), NONE, "quant_inc", "quantize coarser", |app: &mut App| { app.transport.quant = Note::next(app.transport.quant); Ok(true) }], [Char('_'), NONE, "quant_dec", "quantize finer", |app: &mut App| { app.transport.quant = Note::prev(app.transport.quant); Ok(true) }], [Char('='), NONE, "zoom_in", "show fewer ticks per block", |app: &mut App| { app.arranger.sequencer_mut().map(|s|s.time_axis.scale_mut(&Note::prev)); Ok(true) }], [Char('-'), NONE, "zoom_out", "show more ticks per block", |app: &mut App| { app.arranger.sequencer_mut().map(|s|s.time_axis.scale_mut(&Note::next)); Ok(true) }], [Char('x'), NONE, "extend", "double the current clip", |app: &mut App| { app.arranger.phrase().map(|x|x.write().unwrap()).map(|mut phrase|{ let mut notes = phrase.notes.clone(); notes.extend_from_slice(&mut phrase.notes); phrase.notes = notes; phrase.length = phrase.length * 2; }); //app.arranger.show_phrase()?; Ok(true) }], [Char('l'), NONE, "loop_toggle", "toggle looping", |_app: &mut App| { // TODO: This toggles the loop flag for the clip under the cursor. Ok(true) }], [Char('['), NONE, "loop_start_dec", "move loop start back", |_app: &mut App| { // TODO: This moves the loop start to the previous quant. Ok(true) }], [Char(']'), NONE, "loop_start_inc", "move loop start forward", |_app: &mut App| { // TODO: This moves the loop start to the next quant. Ok(true) }], [Char('{'), NONE, "loop_end_dec", "move loop end back", |_app: &mut App| { // TODO: This moves the loop end to the previous quant. Ok(true) }], [Char('}'), NONE, "loop_end_inc", "move loop end forward", |_app: &mut App| { // TODO: This moves the loop end to the next quant. Ok(true) }], [Char('a'), CONTROL, "scene_add", "add a new scene", |app: &mut App| { app.arranger.scene_add(None)?; Ok(true) }], [Char('t'), CONTROL, "track_add", "add a new track", |app: &mut App| { app.arranger.track_add(None)?; Ok(true) }], }); /// Generic key bindings for views that support focus. pub const KEYMAP_FOCUS: &'static [KeyBinding] = keymap!(App { [Char(';'), NONE, "command", "open command palette", |_: &mut App| { *MODAL.lock().unwrap() = Some(Box::new(HelpModal::new())); Ok(true) }], [Tab, NONE, "focus_next", "focus next area", focus_next], [Tab, SHIFT, "focus_prev", "focus previous area", focus_prev], [Esc, NONE, "focus_exit", "unfocus", |app: &mut App|{ app.entered = false; app.transport.entered = app.entered; //app.arranger.entered = app.entered; app.arranger.sequencer_mut().map(|s|s.entered = app.entered); Ok(true) }], [Enter, NONE, "focus_enter", "activate item at cursor", |app: &mut App|{ app.entered = true; app.transport.entered = app.entered; //app.arranger.entered = app.entered; app.arranger.sequencer_mut().map(|s|s.entered = app.entered); Ok(true) }], }); pub fn focus_next (app: &mut App) -> Usually { app.section.next(); app.transport.focused = app.section == AppFocus::Transport; app.transport.entered = app.entered; //app.arranger.focused = app.section == AppFocus::Arranger; //app.arranger.entered = app.entered; app.arranger.sequencer_mut().map(|s|{ s.focused = app.section == AppFocus::Sequencer; s.entered = app.entered; }); Ok(true) } pub fn focus_prev (app: &mut App) -> Usually { app.section.prev(); app.transport.focused = app.section == AppFocus::Transport; app.transport.entered = app.entered; //app.arranger.focused = app.section == AppFocus::Arranger; //app.arranger.entered = app.entered; app.arranger.sequencer_mut().map(|s|{ s.focused = app.section == AppFocus::Sequencer; s.entered = app.entered; }); Ok(true) }