grid -> arranger

This commit is contained in:
🪞👃🪞 2024-07-08 19:50:18 +03:00
parent d99a08bcf7
commit f1f812d0fb
5 changed files with 131 additions and 191 deletions

View file

@ -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<App>] = keymap!(App {
});
const KEYMAP: &'static [KeyBinding<App>] = 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<App>] = keymap!(App {
// [Char('s'), NONE, "stop_and_rewind", "Stop and rewind", stop_and_rewind],
});
const KEYMAP_GRID: &'static [KeyBinding<App>] = 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<App>] = 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<App>] = 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<bool> { Ok(true) }
//fn clip_next (state: &mut Launcher) -> Usually<bool> {
//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<bool> { Ok(true) }
//fn clip_prev (state: &mut Launcher) -> Usually<bool> {
//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<App>] = keymap!(App {
[Up, NONE, "seq_cursor_up", "move cursor up", |app: &mut App| {
@ -258,8 +256,12 @@ const KEYMAP_SEQUENCER: &'static [KeyBinding<App>] = keymap!(App {
});
const KEYMAP_CHAIN: &'static [KeyBinding<App>] = 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<bool> {
fn delete (app: &mut App) -> Usually<bool> {
match app.section {
AppSection::Grid => delete_track(app),
AppSection::Arranger => delete_track(app),
_ => Ok(false)
}
}

View file

@ -18,59 +18,59 @@ use crate::core::*;
#[derive(Default)]
pub struct App {
/// Paths to user directories
pub xdg: Option<Arc<XdgApp>>,
pub xdg: Option<Arc<XdgApp>>,
/// Main JACK client.
pub jack: Option<DynamicAsyncClient>,
pub jack: Option<DynamicAsyncClient>,
/// Main MIDI controller.
pub midi_in: Option<Port<MidiIn>>,
pub midi_in: Option<Port<MidiIn>>,
/// Main audio outputs.
pub audio_outs: Vec<Arc<Port<Unowned>>>,
pub audio_outs: Vec<Arc<Port<Unowned>>>,
/// JACK transport handle.
pub transport: Option<Transport>,
pub transport: Option<Transport>,
/// Current transport state
pub playing: Option<TransportState>,
pub playing: Option<TransportState>,
/// 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<Timebase>,
/// Display mode of grid section
pub grid_mode: bool,
pub timebase: Arc<Timebase>,
/// 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<Box<dyn Component>>,
pub modal: Option<Box<dyn Component>>,
/// 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<Scene>,
pub scenes: Vec<Scene>,
/// Focused track+1, 0 is scene list
pub track_cursor: usize,
pub track_cursor: usize,
/// Collection of tracks
pub tracks: Vec<Track>,
pub chunk_size: usize,
pub quant: usize,
pub tracks: Vec<Track>,
/// 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,
}
}
}

View file

@ -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<Rect> {
SceneGridViewHorizontal {
fn draw_arranger_horizontal (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
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<Rect> {
SceneGridViewVertical {
fn draw_arranger_vertical (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
ArrangerViewVertical {
buf,
area,
focused: self.section == AppSection::Grid,
focused: self.section == AppSection::Arranger,
entered: self.entered,
scenes: &self.scenes,
tracks: &self.tracks,

View file

@ -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;

View file

@ -1,67 +0,0 @@
use crate::*;
//trait Focus<T> {
//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<Self> 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>
App
\ (Transport)
\ Grid
\ Chains
\ Sequencer + Chain
*/