From 7c1dc9ce9b2ead7c8ffca4f37ed14ba29bef662c Mon Sep 17 00:00:00 2001 From: unspeaker Date: Mon, 3 Jun 2024 06:51:53 +0300 Subject: [PATCH] advance play cursor in sequencer --- src/engine.rs | 4 ++-- src/looper/render.rs | 3 +-- src/main.rs | 4 ++-- src/mixer/render.rs | 1 - src/sampler/render.rs | 1 - src/sequencer/mod.rs | 29 +++++++++++------------------ src/sequencer/render.rs | 37 ++++++++++++++++++++++++++++--------- src/transport/mod.rs | 7 ++++++- src/transport/render.rs | 4 +++- 9 files changed, 53 insertions(+), 37 deletions(-) diff --git a/src/engine.rs b/src/engine.rs index b75991e5..0a58ba5f 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -101,7 +101,7 @@ impl Engine { stdout .queue(crossterm::terminal::EnterAlternateScreen)? .flush()?; - let sleep = std::time::Duration::from_millis(16); + let sleep = std::time::Duration::from_millis(20); loop { stdout .queue(crossterm::terminal::BeginSynchronizedUpdate)? @@ -122,7 +122,7 @@ impl Engine { crossterm::terminal::disable_raw_mode()?; break } - std::thread::sleep(sleep); + //std::thread::sleep(sleep); } Ok(()) } diff --git a/src/looper/render.rs b/src/looper/render.rs index 4be2892d..9f21c29a 100644 --- a/src/looper/render.rs +++ b/src/looper/render.rs @@ -12,7 +12,6 @@ pub fn render ( .queue(move_to(0, 1))?.queue(PrintStyledContent(" Metronome [ ] ████ Track 1".bold()))? .queue(move_to(0, 2))?.queue(PrintStyledContent(" Loop 1 [ ] ████ Track 1".bold()))? .queue(move_to(0, 3))?.queue(PrintStyledContent(" Loop 2 [ ] ████████ Track 2".bold()))? - .queue(move_to(0, 4))?.queue(PrintStyledContent(" Loop 3 [ ] ████████ Track 3".bold()))? - .flush()?; + .queue(move_to(0, 4))?.queue(PrintStyledContent(" Loop 3 [ ] ████████ Track 3".bold()))?; Ok(()) } diff --git a/src/main.rs b/src/main.rs index bf96a173..247fa252 100644 --- a/src/main.rs +++ b/src/main.rs @@ -72,7 +72,7 @@ fn run_one (command: &cli::Command) -> Result<(), Box> { ), cli::Command::Sequencer => engine.run( - &mut sequencer::Sequencer::new()?, + &mut sequencer::Sequencer::new(engine.jack_client.as_client())?, |state, stdout, mut offset| { let (w, h) = render::render_toolbar_vertical(stdout, offset, &sequencer::ACTIONS)?; offset.0 = offset.0 + w + 2; @@ -122,10 +122,10 @@ fn run_all () -> Result<(), Box> { exited: false, mode: Mode::Sequencer, transport: transport::Transport::new(engine.jack_client.as_client())?, + sequencer: sequencer::Sequencer::new(engine.jack_client.as_client())?, mixer: mixer::Mixer::new()?, looper: looper::Looper::new()?, sampler: sampler::Sampler::new()?, - sequencer: sequencer::Sequencer::new()?, }; let render = |state: &mut App, stdout: &mut Stdout, mut offset: (u16, u16)| { diff --git a/src/mixer/render.rs b/src/mixer/render.rs index f674e2bd..946e1b83 100644 --- a/src/mixer/render.rs +++ b/src/mixer/render.rs @@ -8,7 +8,6 @@ pub fn render ( ) -> Result<(), Box> { render_table(state, stdout, offset)?; render_meters(state, stdout, offset)?; - stdout.flush()?; Ok(()) } diff --git a/src/sampler/render.rs b/src/sampler/render.rs index 8832990d..dbec8338 100644 --- a/src/sampler/render.rs +++ b/src/sampler/render.rs @@ -8,7 +8,6 @@ pub fn render ( ) -> Result<(), Box> { render_table(state, stdout, offset)?; render_meters(state, stdout, offset)?; - stdout.flush()?; Ok(()) } diff --git a/src/sequencer/mod.rs b/src/sequencer/mod.rs index d4ba4a41..f70a750e 100644 --- a/src/sequencer/mod.rs +++ b/src/sequencer/mod.rs @@ -14,10 +14,12 @@ pub const ACTIONS: [(&'static str, &'static str);4] = [ ]; pub struct Sequencer { - exited: bool, - jack: Jack, - cursor: (u16, u16, u16), - sequence: Vec>>, + exited: bool, + cursor: (u16, u16, u16), + sequence: Vec>>, + transport: ::jack::Transport, + bpm: f64, + timesig: (f32, f32), } #[derive(Clone)] @@ -27,24 +29,15 @@ pub enum Event { } impl Sequencer { - pub fn new () -> Result> { - let (client, status) = Client::new( - "bloop-sequencer", - ClientOptions::NO_START_SERVER - )?; - let jack = client.activate_async( - Notifications, - ClosureProcessHandler::new(Box::new( - move |_: &Client, _: &ProcessScope| -> Control { - Control::Continue - }) as BoxControl + Send> - ) - )?; + pub fn new (client: &Client) -> Result> { + let transport = client.transport(); Ok(Self { exited: false, cursor: (0, 0, 0), - jack, + transport, sequence: vec![vec![None;64];4], + bpm: 120.0, + timesig: (4.0, 4.0) }) } } diff --git a/src/sequencer/render.rs b/src/sequencer/render.rs index b5253462..05675f5f 100644 --- a/src/sequencer/render.rs +++ b/src/sequencer/render.rs @@ -18,7 +18,6 @@ fn render_grid ( offset: (u16, u16) ) -> Result<(), Box> { let move_to = |col, row| crossterm::cursor::MoveTo(offset.0 + col, offset.1 + row); - let bg = "┊···············┊···············┊···············┊···············"; let cursor: String = if state.cursor.2 == 0 { "❱".into() } else { @@ -26,6 +25,17 @@ fn render_grid ( .take(state.cursor.2 as usize) .collect() }; + let transport = state.transport.query()?; + let frame = transport.pos.frame(); + let rate = transport.pos.frame_rate().unwrap(); + let second = (frame as f64) / (rate as f64); + let minute = second / 60f64; + let bpm = 120f64; + let div = 4; + let beats = minute * bpm; + let bars = beats as u32 / div as u32; + let beat = beats as u32 % div as u32 + 1; + let beat_sub = beats % 1.0; stdout .queue(move_to(1, 3))?.queue(Print("1.1"))? .queue(move_to(17, 3))?.queue(Print("1.2"))? @@ -33,14 +43,23 @@ fn render_grid ( .queue(move_to(49, 3))?.queue(Print("1.4"))?; for (index, row) in state.sequence.iter().enumerate() { let y = index as u16 + 4; - stdout.queue(move_to(1, y))?.queue( - PrintStyledContent(bg.grey()) - )?; - for (index, step) in row.iter().enumerate() { - if step.is_some() { - let x = index as u16 + 1; - stdout.queue(move_to(x, y))?.queue( - PrintStyledContent("X".white().bold()) + for x in 0u16..64 { + let bg = if x as u32 == (beat - 1) * 16 + (beat_sub * 16.0) as u32 { + crossterm::style::Color::Black + } else { + crossterm::style::Color::Reset + }; + if let Some(step) = &row[x as usize] { + stdout.queue(move_to(1 + x, y))?.queue( + PrintStyledContent("X".white().bold().on(bg)) + )?; + } else if x % 16 == 0 { + stdout.queue(move_to(1 + x, y))?.queue( + PrintStyledContent("┊".grey().on(bg)) + )?; + } else { + stdout.queue(move_to(1 + x, y))?.queue( + PrintStyledContent("·".grey().on(bg)) )?; } } diff --git a/src/transport/mod.rs b/src/transport/mod.rs index fb91d2e0..ab2b863d 100644 --- a/src/transport/mod.rs +++ b/src/transport/mod.rs @@ -16,14 +16,19 @@ pub struct Transport { exited: bool, title: String, transport: ::jack::Transport, + bpm: f64, + timesig: (f32, f32), } impl Transport { pub fn new (client: &Client) -> Result> { + let transport = client.transport(); Ok(Self { exited: false, title: String::from("Untitled project"), - transport: client.transport(), + bpm: 93.0, + timesig: (4.0, 4.0), + transport, }) } diff --git a/src/transport/render.rs b/src/transport/render.rs index 16c6da08..052fd2bd 100644 --- a/src/transport/render.rs +++ b/src/transport/render.rs @@ -16,7 +16,9 @@ pub fn render ( if let Ok(position) = state.transport.query() { let frame = position.pos.frame(); let rate = position.pos.frame_rate(); - let bbt = position.pos.bbt(); + let bbt = position.pos.bbt().map(|mut bbt|*bbt + .with_bpm(state.bpm) + .with_timesig(state.timesig.0, state.timesig.1)); stdout .queue(move_to( 1, 1))?.queue(Print("Frame: "))? .queue(move_to( 1, 2))?.queue(