diff --git a/src/control.rs b/src/control.rs index dea34734..0379120f 100644 --- a/src/control.rs +++ b/src/control.rs @@ -15,8 +15,8 @@ handle!(App |self, e| { }; } let handle_focused = |state: &mut Self|match state.section { - AppSection::Grid => - handle_keymap(state, e, KEYMAP_GRID), + AppSection::Arranger => + handle_keymap(state, e, KEYMAP_ARRANGER), AppSection::Sequencer => handle_keymap(state, e, KEYMAP_SEQUENCER), AppSection::Chain => @@ -47,7 +47,6 @@ const KEYMAP_FOCUS: &'static [KeyBinding] = keymap!(App { }); const KEYMAP: &'static [KeyBinding] = keymap!(App { - [F(1), NONE, "help_toggle", "toggle help", |_: &mut App| {Ok(true)}], [Up, NONE, "focus_prev", "focus previous area", focus_prev], @@ -140,24 +139,32 @@ const KEYMAP: &'static [KeyBinding] = keymap!(App { // [Char('s'), NONE, "stop_and_rewind", "Stop and rewind", stop_and_rewind], }); -const KEYMAP_GRID: &'static [KeyBinding] = keymap!(App { - [Up, NONE, "grid_cursor_up", "move cursor up", |app: &mut App| Ok(match app.grid_mode { - false => {app.scene_cursor = app.scene_cursor.saturating_sub(1); true}, - true => {app.track_cursor = app.track_cursor.saturating_sub(1); true}, - })], - [Down, NONE, "grid_cursor_down", "move cursor down", |app: &mut App| Ok(match app.grid_mode { - false => {app.scene_cursor = app.scenes.len().min(app.scene_cursor + 1); true}, - true => {app.track_cursor = app.tracks.len().min(app.track_cursor + 1); true}, - })], - [Left, NONE, "grid_cursor_left", "move cursor left", |app: &mut App| Ok(match app.grid_mode { - false => {app.track_cursor = app.track_cursor.saturating_sub(1); true}, - true => {app.scene_cursor = app.scene_cursor.saturating_sub(1); true}, - })], - [Right, NONE, "grid_cursor_right", "move cursor right", |app: &mut App| Ok(match app.grid_mode { - false => {app.track_cursor = app.tracks.len().min(app.track_cursor + 1); true}, - true => {app.scene_cursor = app.scenes.len().min(app.scene_cursor + 1); true}, - })], - [Enter, NONE, "grid_activate", "activate item at cursor", |app: &mut App| Ok( +const KEYMAP_ARRANGER: &'static [KeyBinding] = keymap!(App { + [Up, NONE, "arranger_cursor_up", "move cursor up", |app: &mut App| Ok( + match app.arranger_mode { + false => {app.scene_cursor = app.scene_cursor.saturating_sub(1); true}, + true => {app.track_cursor = app.track_cursor.saturating_sub(1); true}, + } + )], + [Down, NONE, "arranger_cursor_down", "move cursor down", |app: &mut App| Ok( + match app.arranger_mode { + false => {app.scene_cursor = app.scenes.len().min(app.scene_cursor + 1); true}, + true => {app.track_cursor = app.tracks.len().min(app.track_cursor + 1); true}, + } + )], + [Left, NONE, "arranger_cursor_left", "move cursor left", |app: &mut App| Ok( + match app.arranger_mode { + false => {app.track_cursor = app.track_cursor.saturating_sub(1); true}, + true => {app.scene_cursor = app.scene_cursor.saturating_sub(1); true}, + } + )], + [Right, NONE, "arranger_cursor_right", "move cursor right", |app: &mut App| Ok( + match app.arranger_mode { + false => {app.track_cursor = app.tracks.len().min(app.track_cursor + 1); true}, + true => {app.scene_cursor = app.scenes.len().min(app.scene_cursor + 1); true}, + } + )], + [Enter, NONE, "arranger_activate", "activate item at cursor", |app: &mut App| Ok( if app.scene_cursor == 0 { false } else { @@ -175,52 +182,43 @@ const KEYMAP_GRID: &'static [KeyBinding] = keymap!(App { true } )], - [Char('.'), NONE, "grid_increment", "set next clip at cursor", |app: &mut App| { + [Char('.'), NONE, "arranger_increment", "set next clip at cursor", |app: &mut App| { + //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) }], - [Char(','), NONE, "grid_decrement", "set previous clip at cursor", |app: &mut App| { + [Char(','), NONE, "arranger_decrement", "set previous clip at cursor", |app: &mut App| { + //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) }], - [Char('`'), NONE, "grid_mode_switch", "switch the display mode", |app: &mut App| { - app.grid_mode = !app.seq_mode; + [Char('`'), NONE, "arranger_mode_switch", "switch the display mode", |app: &mut App| { + app.arranger_mode = !app.seq_mode; Ok(true) }], }); -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 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) -//} const KEYMAP_SEQUENCER: &'static [KeyBinding] = keymap!(App { [Up, NONE, "seq_cursor_up", "move cursor up", |app: &mut App| { @@ -258,8 +256,12 @@ const KEYMAP_SEQUENCER: &'static [KeyBinding] = keymap!(App { }); const KEYMAP_CHAIN: &'static [KeyBinding] = keymap!(App { - [Up, NONE, "chain_cursor_up", "move cursor up", |_: &mut App| Ok(true)], - [Down, NONE, "chain_cursor_down", "move cursor down", |_: &mut App| Ok(true)], + [Up, NONE, "chain_cursor_up", "move cursor up", |_: &mut App| { + Ok(true) + }], + [Down, NONE, "chain_cursor_down", "move cursor down", |_: &mut App| { + Ok(true) + }], [Left, NONE, "chain_cursor_left", "move cursor left", |app: &mut App| { if let Some((_, track)) = app.track_mut() { track.device = track.device.saturating_sub(1); @@ -303,7 +305,7 @@ fn decrement (app: &mut App) -> Usually { fn delete (app: &mut App) -> Usually { match app.section { - AppSection::Grid => delete_track(app), + AppSection::Arranger => delete_track(app), _ => Ok(false) } } diff --git a/src/model.rs b/src/model.rs index 2bb393c9..71145c91 100644 --- a/src/model.rs +++ b/src/model.rs @@ -18,59 +18,59 @@ use crate::core::*; #[derive(Default)] pub struct App { /// Paths to user directories - pub xdg: Option>, + pub xdg: Option>, /// Main JACK client. - pub jack: Option, + pub jack: Option, /// Main MIDI controller. - pub midi_in: Option>, + pub midi_in: Option>, /// Main audio outputs. - pub audio_outs: Vec>>, + pub audio_outs: Vec>>, /// JACK transport handle. - pub transport: Option, + pub transport: Option, /// Current transport state - pub playing: Option, + pub playing: Option, /// Current position according to transport - pub playhead: usize, + pub playhead: usize, /// Position of T0 for this playback within global timeline - pub play_started: Option<(usize, usize)>, + pub play_started: Option<(usize, usize)>, /// Current sample rate and tempo. - pub timebase: Arc, - /// Display mode of grid section - pub grid_mode: bool, + pub timebase: Arc, + /// Display mode of arranger section + pub arranger_mode: bool, /// Display mode of chain section - pub chain_mode: bool, + pub chain_mode: bool, /// Display mode of sequencer seciton - pub seq_mode: bool, + pub seq_mode: bool, /// Optional modal dialog - pub modal: Option>, + pub modal: Option>, /// Currently focused section - pub section: AppSection, + pub section: AppSection, /// Whether the section is focused - pub entered: bool, + pub entered: bool, /// Current frame - pub metronome: bool, + pub metronome: bool, /// Display position of cursor within note range - pub note_cursor: usize, + pub note_cursor: usize, /// Range of notes to display - pub note_start: usize, + pub note_start: usize, /// Display position of cursor within time range - pub time_cursor: usize, + pub time_cursor: usize, /// PPQ per display unit - pub time_zoom: usize, + pub time_zoom: usize, /// Range of time steps to display - pub time_start: usize, + pub time_start: usize, /// Focused scene+1, 0 is track list - pub scene_cursor: usize, + pub scene_cursor: usize, /// Collection of scenes - pub scenes: Vec, + pub scenes: Vec, /// Focused track+1, 0 is scene list - pub track_cursor: usize, + pub track_cursor: usize, /// Collection of tracks - pub tracks: Vec, - - pub chunk_size: usize, - - pub quant: usize, + pub tracks: Vec, + /// Number of frames requested by process callback + pub chunk_size: usize, + /// Quantization factor + pub quant: usize, } process!(App |self, _client, scope| { let ( @@ -299,28 +299,28 @@ struct SelectionMut<'a> { #[derive(PartialEq, Clone, Copy)] pub enum AppSection { - Grid, + Arranger, Sequencer, Chain, } impl Default for AppSection { fn default () -> Self { - Self::Grid + Self::Arranger } } impl AppSection { pub fn prev (&mut self) { *self = match self { - Self::Grid => Self::Chain, - Self::Sequencer => Self::Grid, + Self::Arranger => Self::Chain, + Self::Sequencer => Self::Arranger, Self::Chain => Self::Sequencer, } } pub fn next (&mut self) { *self = match self { - Self::Grid => Self::Sequencer, + Self::Arranger => Self::Sequencer, Self::Sequencer => Self::Chain, - Self::Chain => Self::Grid, + Self::Chain => Self::Arranger, } } } diff --git a/src/view.rs b/src/view.rs index 5ce14ce5..2ed63f7e 100644 --- a/src/view.rs +++ b/src/view.rs @@ -1,18 +1,16 @@ pub mod chain; -pub mod grid; +pub mod arranger; pub mod layout; pub mod sampler; pub mod sequencer; pub mod transport; pub mod plugin; -pub mod focus; pub mod border; pub use self::border::*; pub use self::layout::*; pub use self::transport::TransportView; -pub use self::grid::*; -pub use self::focus::*; +pub use self::arranger::*; pub use self::chain::ChainView; pub use self::sequencer::SequencerView; @@ -22,23 +20,23 @@ render!(App |self, buf, area| { let Rect { x, y, width, height } = area; let transport = self.draw_transport(buf, area)?; let y = y + transport.height; - let grid = if self.grid_mode { - self.draw_grid_horizontal(buf, Rect { + let arranger = if self.arranger_mode { + self.draw_arranger_horizontal(buf, Rect { x, y, width, height: height / 3 })? } else { - self.draw_grid_vertical(buf, Rect { + self.draw_arranger_vertical(buf, Rect { x, y, width, height: height / 3 })? }; - if self.section == AppSection::Grid { + if self.section == AppSection::Arranger { QuarterV(if self.entered { Style::default().green() } else { Style::default().green().dim() - }).draw(buf, grid) + }).draw(buf, arranger) } - let y = y + grid.height; + let y = y + arranger.height; if self.track_cursor > 0 { let chain = self.draw_chain(buf, Rect { x, y: y + height - height / 3 - 1, width, height: height / 3 @@ -48,7 +46,7 @@ render!(App |self, buf, area| { Style::default().green() } else { Style::default().green().dim() - }).draw(buf, chain) + }).draw(buf, Rect { width, ..chain }) } let phrase = self.draw_phrase(buf, Rect { x, y, width, height: height - height / 3 @@ -101,22 +99,22 @@ impl App { quant: self.quant, }.render(buf, area) } - fn draw_grid_horizontal (&self, buf: &mut Buffer, area: Rect) -> Usually { - SceneGridViewHorizontal { + fn draw_arranger_horizontal (&self, buf: &mut Buffer, area: Rect) -> Usually { + ArrangerViewHorizontal { buf, area, - focused: self.section == AppSection::Grid, + focused: self.section == AppSection::Arranger, entered: self.entered, scenes: &self.scenes, tracks: &self.tracks, cursor: &(self.track_cursor, self.scene_cursor), }.draw() } - fn draw_grid_vertical (&self, buf: &mut Buffer, area: Rect) -> Usually { - SceneGridViewVertical { + fn draw_arranger_vertical (&self, buf: &mut Buffer, area: Rect) -> Usually { + ArrangerViewVertical { buf, area, - focused: self.section == AppSection::Grid, + focused: self.section == AppSection::Arranger, entered: self.entered, scenes: &self.scenes, tracks: &self.tracks, diff --git a/src/view/grid.rs b/src/view/arranger.rs similarity index 95% rename from src/view/grid.rs rename to src/view/arranger.rs index 6fe2e653..f899037c 100644 --- a/src/view/grid.rs +++ b/src/view/arranger.rs @@ -1,7 +1,7 @@ use crate::core::*; use crate::model::*; use crate::view::*; -pub struct SceneGridViewVertical<'a> { +pub struct ArrangerViewVertical<'a> { pub buf: &'a mut Buffer, pub area: Rect, pub scenes: &'a[Scene], @@ -10,7 +10,7 @@ pub struct SceneGridViewVertical<'a> { pub focused: bool, pub entered: bool, } -impl<'a> SceneGridViewVertical<'a> { +impl<'a> ArrangerViewVertical<'a> { pub fn size (&self) -> (u16, u16) { unimplemented!(); } @@ -37,14 +37,12 @@ impl<'a> SceneGridViewVertical<'a> { } else { Color::Rgb(20, 45, 5) }; - let columns = self.track_names(); let mut x2 = x; for (i, w) in self.track_widths().iter().enumerate() { let focus_column = i == self.cursor.0; if x2 >= x + width { break } - //self.separator_v(x2, focus_column); if focus_column { fill_bg( &mut self.buf, @@ -53,9 +51,9 @@ impl<'a> SceneGridViewVertical<'a> { ); } x2 = x2 + w; - //self.separator_v(x2, focus_column); } let (mut x2, y2) = (x, y); + let columns = self.track_names(); for (i, title) in columns.iter().enumerate() { let focus_column = i == self.cursor.0; if x2 >= x + width { @@ -77,7 +75,16 @@ impl<'a> SceneGridViewVertical<'a> { self.clips(x2+1, y2+2, i - 1); }; let style = Some(highlight(self.focused, focus_column).bold()); - title.blit(self.buf, x2+1, y2, style); + if i > 0 { + "⏺".blit(self.buf, x2, y2, Some(if self.tracks[i-1].recording { + Style::default().red() + } else if self.tracks[i-1].monitoring { + Style::default().green() + } else { + Style::default().black() + })); + } + title.blit(self.buf, x2+2, y2, style); x2 = x2 + w + 3; } fill_bg( @@ -187,7 +194,7 @@ impl<'a> SceneGridViewVertical<'a> { } -pub struct SceneGridViewHorizontal<'a> { +pub struct ArrangerViewHorizontal<'a> { pub buf: &'a mut Buffer, pub area: Rect, pub scenes: &'a[Scene], @@ -196,7 +203,7 @@ pub struct SceneGridViewHorizontal<'a> { pub focused: bool, pub entered: bool, } -impl<'a> SceneGridViewHorizontal<'a> { +impl<'a> ArrangerViewHorizontal<'a> { pub fn size (&self) -> (u16, u16) { let w = (4 + longest_track_name(&self.tracks) + self.scenes.len() as u16 * 10) as u16; let h = (2 + self.tracks.len()) as u16; diff --git a/src/view/focus.rs b/src/view/focus.rs deleted file mode 100644 index f62d792b..00000000 --- a/src/view/focus.rs +++ /dev/null @@ -1,67 +0,0 @@ -use crate::*; - -//trait Focus { - //fn focused (&self) -> &T; - //fn focused_mut (&mut self) -> &mut T; - //fn focus (&mut self, value: T) -> &mut T; - //fn focus_next (&mut self) -> &mut T; - //fn focus_prev (&mut self) -> &mut T; - //fn focus_enter (&mut self) -> &mut T; - //fn focus_exit (&mut self) -> &mut T; -//} - -//enum AppSection { - //Grid, - //Sequence, - //Chain, -//} - -//impl Focus for (AppSection, bool) { - //fn focused (&self) -> &Self { - //self - //} - //fn focused_mut (&mut self) -> &mut Self { - //self - //} - //fn focus (&mut self, value: Self) -> &mut Self { - //*self = value; - //self - //} - //fn focus_prev (&mut self) -> &mut Self { - //self.focus((match self.0 { - //AppSection::Grid => AppSection::Chain, - //AppSection::Sequence => AppSection::Grid, - //AppSection::Chain => AppSection::Sequence, - //}, self.1)) - //} - //fn focus_next (&mut self) -> &mut Self { - //self.focus((match self.0 { - //AppSection::Grid => AppSection::Sequence, - //AppSection::Sequence => AppSection::Chain, - //AppSection::Chain => AppSection::Grid, - //}, self.1)) - //} -//} - -/* - -App( - Column( - Transport( - Row(PLAY, REC, DUB, MON, BPM, SYNC, QUANT, _, TIME, BBT), - RowOrColumn( - Grid, - - ) - - - - - -App - \ (Transport) - \ Grid - \ Chains - \ Sequencer + Chain - -*/