pub mod focus; pub mod mixer; pub mod plugin; pub mod sampler; pub use self::focus::*; use crate::{core::*, handle, App}; handle!(App |self, e| { if let Some(ref mut modal) = self.modal { if modal.handle(e)? { self.modal = None; return Ok(true) }; } handle_keymap(self, e, KEYMAP) }); const KEYMAP: &'static [KeyBinding] = keymap!(App { [Char(' '), NONE, "toggle_play", "play or pause", |app: &mut App| { app.toggle_play()?; Ok(true) }], [Char('a'), CONTROL, "add_scene", "add a new scene", |app: &mut App| { app.add_scene(None)?; Ok(true) }], [Char('t'), CONTROL, "add_track", "add a new track", |app: &mut App| { app.add_track(None)?; Ok(true) }], [Char('`'), NONE, "switch_mode", "switch the display mode", |app: &mut App| { match app.section { 0 => {app.grid_mode = !app.grid_mode; Ok(true)}, 1 => {app.chain_mode = !app.chain_mode; Ok(true)}, 2 => {app.seq_mode = !app.seq_mode; Ok(true)}, _ => Ok(false) } }], [F(1), NONE, "toggle_help", "toggle help", |_: &mut App| {Ok(true)}], [Char('r'), NONE, "toggle_record", "toggle recording", |_: &mut App| {Ok(true)}], [Char('d'), NONE, "toggle_overdub", "toggle overdub", |_: &mut App| {Ok(true)}], [Char('m'), NONE, "toggle_monitor", "toggle input monitoring", |_: &mut App| {Ok(true)}], [Up, NONE, "cursor_up", "move cursor up", |app: &mut App| { if app.entered { match app.section { 0 => match app.grid_mode { false => {app.scene_cursor = app.scene_cursor.saturating_sub(1); Ok(true)}, true => {app.track_cursor = app.track_cursor.saturating_sub(1); Ok(true)}, }, 2 => { app.note_cursor = app.note_cursor.saturating_sub(1); Ok(true) } _ => Ok(false) } } else { focus_next(app) } }], [Down, NONE, "cursor_down", "move cursor down", |app: &mut App| { if app.entered { match app.section { 0 => match app.grid_mode { false => {app.scene_cursor = app.scenes.len().min(app.scene_cursor + 1); Ok(true)}, true => {app.track_cursor = app.tracks.len().min(app.track_cursor + 1); Ok(true)}, }, 2 => { app.note_cursor = app.note_cursor + 1; Ok(true) } _ => Ok(false) } } else { focus_prev(app) } }], [Left, NONE, "cursor_left", "move cursor left", |app: &mut App| { match app.section { 0 => match app.grid_mode { false => {app.track_cursor = app.track_cursor.saturating_sub(1); Ok(true)}, true => {app.scene_cursor = app.scene_cursor.saturating_sub(1); Ok(true)}, }, 1 => { if let Some((_, track)) = app.track_mut() { track.device = track.device.saturating_sub(1); Ok(true) } else { Ok(false) } }, 2 => { app.time_cursor = app.time_cursor.saturating_sub(1); Ok(true) }, _ => Ok(false) } }], [Right, NONE, "cursor_right", "move cursor right", |app: &mut App| { match app.section { 0 => match app.grid_mode { false => {app.track_cursor = app.tracks.len().min(app.track_cursor + 1); Ok(true)}, true => {app.scene_cursor = app.scenes.len().min(app.scene_cursor + 1); Ok(true)}, }, 1 => { if let Some((_, track)) = app.track_mut() { track.device = (track.device + 1).min(track.devices.len().saturating_sub(1)); Ok(true) } else { Ok(false) } }, 2 => { app.time_cursor = app.time_cursor + 1; Ok(true) }, _ => Ok(false) } }], [Tab, NONE, "focus_next", "focus next area", focus_next], [Tab, SHIFT, "focus_prev", "focus previous area", focus_prev], [Char('.'), NONE, "increment", "increment value", increment], [Char(','), NONE, "decrement", "decrement value", decrement], [Delete, CONTROL, "delete", "delete track", delete], [Char('d'), CONTROL, "duplicate", "duplicate scene or track", duplicate], [Enter, NONE, "activate", "activate item at cursor", enter], [Esc, NONE, "escape", "unfocus", escape], [Char('r'), CONTROL, "rename", "rename current element", rename], // [Char('='), NONE, "zoom_in", "Zoom in", zoom_in], // [Char('-'), NONE, "zoom_out", "Zoom out", zoom_out], // [Char('a'), NONE, "note_add", "Add note", note_add], // [Char('z'), NONE, "note_del", "Delete note", note_del], // [CapsLock, NONE, "advance", "Toggle auto advance", nop], // [Char('w'), NONE, "rest", "Advance by note duration", nop], // [Char('s'), NONE, "stop_and_rewind", "Stop and rewind", stop_and_rewind], // [Char('q'), NONE, "quantize_next", "Next quantize value", quantize_next], // [Char('Q'), SHIFT, "quantize_prev", "Previous quantize value", quantize_prev], }); fn focus_next (app: &mut App) -> Usually { if app.section >= 2 { app.section = 0; } else { app.section = app.section + 1; } Ok(true) } fn focus_prev (app: &mut App) -> Usually { if app.section == 0 { app.section = 2; } else { app.section = app.section - 1; } Ok(true) } fn increment (app: &mut App) -> Usually { match app.section { 0 => clip_next(app), _ => Ok(false) } } fn clip_next (_: &mut App) -> Usually { Ok(true) } //fn clip_next (state: &mut Launcher) -> Usually { //if state.cursor.0 >= 1 && state.cursor.1 >= 1 { //let scene_id = state.cursor.1 - 1; //let clip_id = state.cursor.0 - 1; //let scene = &mut state.scenes[scene_id]; //scene.clips[clip_id] = match scene.clips[clip_id] { //None => Some(0), //Some(i) => if i >= state.tracks[clip_id].sequencer.phrases.len().saturating_sub(1) { //None //} else { //Some(i + 1) //} //}; //} //Ok(true) //} fn decrement (app: &mut App) -> Usually { match app.section { 0 => clip_prev(app), _ => Ok(false) } } fn clip_prev (_: &mut App) -> Usually { Ok(true) } //fn clip_prev (state: &mut Launcher) -> Usually { //if state.cursor.0 >= 1 && state.cursor.1 >= 1 { //let scene_id = state.cursor.1 - 1; //let clip_id = state.cursor.0 - 1; //let scene = &mut state.scenes[scene_id]; //scene.clips[clip_id] = match scene.clips[clip_id] { //None => Some(state.tracks[clip_id].sequencer.phrases.len().saturating_sub(1)), //Some(i) => if i == 0 { //None //} else { //Some(i - 1) //} //}; //} //Ok(true) //} fn activate (_: &mut App) -> Usually { Ok(true) } //fn activate (_: &mut Launcher) -> Usually { //unimplemented!(); ////if let ( ////Some((_scene_id, scene)), ////Some((track_id, track)), ////) = (state.scene_mut(), state.track_mut()) { ////// Launch clip ////if let Some(phrase_id) = scene.clips.get(track_id) { ////track.sequencer.sequence = *phrase_id; ////} ////if state.playing == TransportState::Stopped { ////state.transport.start()?; ////state.playing = TransportState::Starting; ////} ////} else if let Some((_scene_id, scene)) = state.scene() { ////// Launch scene ////for (track_id, track) in state.tracks.iter().enumerate() { ////if let Some(phrase_id) = scene.clips.get(track_id) { ////track.sequencer.sequence = *phrase_id; ////} ////} ////if state.playing == TransportState::Stopped { ////state.transport.start()?; ////state.playing = TransportState::Starting; ////} ////} else if let Some((_track_id, _track)) = state.track() { ////// Rename track? ////} ////let track = state.active_track().unwrap(); ////let scene = state.active_scene(); ////if state.cursor.1 >= 2 { ////if let Some(Some(index)) = scene.clips.get(state.cursor.1 - 2) { ////track.enqueue(index) ////} else { ////} ////} ////if state.cursor.0 >= 1 { ////let sequencer = state.tracks.get_mut(state.cursor.0 - 1); ////if state.cursor.1 >= 2 { ////let scene = state.scenes.get_mut(state.cursor.1 - 2); ////if let Some(index) = scene.get(state.cursor.0 - 1) { ////let phrase = sequencer.phrases.get(index); ////} else { ////let index = sequencer.phrases.len(); ////let phrase = Phrase::new(&format!("Phrase#{index}")); ////sequencer.phrases.push(phrase); ////scene[state.cursor.0 - 1] = Some(index); ////} ////} ////} //Ok(true) //} fn delete (app: &mut App) -> Usually { match app.section { 0 => delete_track(app), _ => Ok(false) } } fn enter (app: &mut App) -> Usually { if app.entered { activate(app) } else { app.entered = true; Ok(true) } } fn escape (app: &mut App) -> Usually { if app.entered { app.entered = false; Ok(true) } else { Ok(false) } } fn delete_track (app: &mut App) -> Usually { if app.tracks.len() > 0 { let track = app.tracks.remove(app.track_cursor); app.track_cursor = app.track_cursor.saturating_sub(1); app.jack.as_ref().unwrap().as_client().unregister_port(track.midi_out)?; return Ok(true) } Ok(false) } fn duplicate (_: &mut App) -> Usually { Ok(true) } fn rename (_: &mut App) -> Usually { Ok(true) } //fn toggle_record (s: &mut Launcher) -> Usually { //s.sequencer_mut().map(|s|s.recording = !s.recording); //Ok(true) //} //fn toggle_overdub (s: &mut Launcher) -> Usually { //s.sequencer_mut().map(|s|s.overdub = !s.overdub); //Ok(true) //} //fn toggle_monitor (s: &mut Launcher) -> Usually { //s.sequencer_mut().map(|s|s.monitoring = !s.monitoring); //Ok(true) //} //use crate::{core::*, model::*}; //use super::focus::*; //pub fn handle (state: &mut Chain, event: &AppEvent) -> Usually { //Ok(handle_focus(state, event, keymap!(Chain { //[Up, NONE, "focus_up", "focus row above", //|s: &mut Chain|s.handle_focus(&FocusEvent::Backward)], //[Down, NONE, "focus_down", "focus row below", //|s: &mut Chain|s.handle_focus(&FocusEvent::Forward)], //[Enter, NONE, "focus_down", "focus row below", //|s: &mut Chain|s.handle_focus(&FocusEvent::Inward)], //[Esc, NONE, "focus_down", "focus row below", //|s: &mut Chain|s.handle_focus(&FocusEvent::Outward)], //}))? || handle_keymap(state, event, keymap!(Chain { //[Char('a'), NONE, "add_device", "add a device", add_device] //}))?) //} //fn add_device (state: &mut Chain) -> Usually { //state.adding = true; //Ok(true) //} //impl Focus for Chain { //fn unfocus (&mut self) { //self.focused = false //} //fn focused (&self) -> Option<&Box> { //match self.focused { //true => self.items.get(self.focus), //false => None //} //} //fn focused_mut (&mut self) -> Option<&mut Box> { //match self.focused { //true => self.items.get_mut(self.focus), //false => None //} //} //fn handle_focus (&mut self, event: &FocusEvent) -> Usually { //Ok(match event { //FocusEvent::Backward => { //if self.focus == 0 { //self.focus = self.items.len(); //} //self.focus = self.focus - 1; //true //}, //FocusEvent::Forward => { //self.focus = self.focus + 1; //if self.focus >= self.items.len() { //self.focus = 0; //} //true //}, //FocusEvent::Inward => { //self.focused = true; //self.items[self.focus].handle(&AppEvent::Focus)?; //true //}, //FocusEvent::Outward => { //if self.focused { //self.focused = false; //self.items[self.focus].handle(&AppEvent::Blur)?; //true //} else { //false //} //}, //}) //} //}