use crate::prelude::*; use super::*; pub fn handle (state: &mut Launcher, event: &AppEvent) -> Usually { Ok(handle_keymap(state, event, KEYMAP)? || match state.view { LauncherView::Modal(ref mut device) => { device.handle(event)? }, LauncherView::Tracks => { handle_keymap(state, event, KEYMAP_TRACKS)? }, LauncherView::Sequencer => { let i = state.col().saturating_sub(1); if let Some(track) = state.tracks.get_mut(i) { crate::device::sequencer::handle(&mut *track.sequencer.state(), event)? } else { true } }, LauncherView::Chains => { let i = state.col().saturating_sub(1); if let Some(track) = state.tracks.get_mut(i) { crate::device::chain::handle(&mut *track.chain.state(), event)? } else { true } } }) } pub const KEYMAP: &'static [KeyBinding] = keymap!(Launcher { [F(1), NONE, "toggle_help", "toggle help", toggle_help], [Tab, SHIFT, "focus_prev", "focus previous area", focus_prev], [Tab, NONE, "focus_next", "focus next area", focus_next], [Char(' '), NONE, "play_toggle", "play or pause", play_toggle], [Char('r'), NONE, "record_toggle", "toggle recording", record_toggle], [Char('d'), NONE, "overdub_toggle", "toggle overdub", overdub_toggle], [Char('m'), NONE, "monitor_toggle", "toggle input monitoring", monitor_toggle], [Char('r'), CONTROL, "rename", "rename current element", rename], [Char('t'), CONTROL, "add_track", "add a new track", add_track], //[Char(' '), SHIFT, "play_start", "play from start", play_start], }); pub const KEYMAP_TRACKS: &'static [KeyBinding] = keymap!(Launcher { [Up, NONE, "cursor_up", "move cursor up", cursor_up], [Down, NONE, "cursor_down", "move cursor down", cursor_down], [Left, NONE, "cursor_left", "move cursor left", cursor_left], [Right, NONE, "cursor_right", "move cursor right", cursor_right], [Char('.'), NONE, "clip_next", "set clip to next phrase", clip_next], [Char(','), NONE, "clip_prev", "set clip to last phrase", clip_prev], [Delete, CONTROL, "delete_track", "delete track", delete_track], [Char('d'), CONTROL, "duplicate", "duplicate scene or track", duplicate], [Enter, NONE, "clip_enter", "play or record clip or stop and advance", clip_enter], }); fn duplicate (_: &mut Launcher) -> Usually { Ok(true) } fn clip_enter (_: &mut Launcher) -> Usually { //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 rename (_: &mut Launcher) -> Usually { Ok(true) } fn add_track (state: &mut Launcher) -> Usually { let name = format!("Track {}", state.tracks.len() + 1); state.tracks.push(Track::new(&name, &state.timebase, None, None)?); state.cursor.0 = state.tracks.len(); Ok(true) } fn delete_track (state: &mut Launcher) -> Usually { if state.tracks.len() > 0 && state.cursor.0 >= 1 { state.tracks.remove(state.cursor.0 - 1); state.cursor.0 = state.cursor.0.min(state.tracks.len()); } Ok(true) } fn cursor_up (state: &mut Launcher) -> Usually { state.dec_row(); Ok(true) } fn cursor_down (state: &mut Launcher) -> Usually { state.inc_row(); Ok(true) } fn cursor_left (state: &mut Launcher) -> Usually { state.dec_col(); Ok(true) } fn cursor_right (state: &mut Launcher) -> Usually { state.inc_col(); Ok(true) } fn toggle_help (state: &mut Launcher) -> Usually { state.show_help = !state.show_help; Ok(true) } fn focus_next (state: &mut Launcher) -> Usually { match state.view { LauncherView::Tracks => { state.view = LauncherView::Sequencer; }, LauncherView::Sequencer => { state.view = LauncherView::Chains; }, LauncherView::Chains => { state.view = LauncherView::Tracks; }, _ => {}, }; Ok(true) } fn focus_prev (state: &mut Launcher) -> Usually { match state.view { LauncherView::Tracks => { state.view = LauncherView::Chains; }, LauncherView::Chains => { state.view = LauncherView::Sequencer; }, LauncherView::Sequencer => { state.view = LauncherView::Tracks; }, _ => {}, }; 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.state().sequences.len().saturating_sub(1) { None } else { Some(i + 1) } }; } 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.state().sequences.len().saturating_sub(1)), Some(i) => if i == 0 { None } else { Some(i - 1) } }; } Ok(true) } fn play_toggle (s: &mut Launcher) -> Usually { s.playing = match s.playing { TransportState::Stopped => { s.transport.start()?; TransportState::Starting }, _ => { s.transport.stop()?; s.transport.locate(0)?; TransportState::Stopped }, }; Ok(true) } //fn play_start (_: &mut Launcher) -> Usually { //unimplemented!() //} fn record_toggle (s: &mut Launcher) -> Usually { s.recording = !s.recording; for track in s.tracks.iter() { track.sequencer.state().recording = s.recording; } Ok(true) } fn overdub_toggle (s: &mut Launcher) -> Usually { s.overdub = !s.overdub; for track in s.tracks.iter() { track.sequencer.state().overdub = s.overdub; } Ok(true) } fn monitor_toggle (s: &mut Launcher) -> Usually { s.monitoring = !s.monitoring; for track in s.tracks.iter() { track.sequencer.state().monitoring = s.monitoring; } Ok(true) }