mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
advance play cursor in sequencer
This commit is contained in:
parent
4fd208d53f
commit
7c1dc9ce9b
9 changed files with 53 additions and 37 deletions
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ fn run_one (command: &cli::Command) -> Result<(), Box<dyn Error>> {
|
|||
),
|
||||
|
||||
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<dyn Error>> {
|
|||
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)| {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ pub fn render (
|
|||
) -> Result<(), Box<dyn Error>> {
|
||||
render_table(state, stdout, offset)?;
|
||||
render_meters(state, stdout, offset)?;
|
||||
stdout.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ pub fn render (
|
|||
) -> Result<(), Box<dyn Error>> {
|
||||
render_table(state, stdout, offset)?;
|
||||
render_meters(state, stdout, offset)?;
|
||||
stdout.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,10 +14,12 @@ pub const ACTIONS: [(&'static str, &'static str);4] = [
|
|||
];
|
||||
|
||||
pub struct Sequencer {
|
||||
exited: bool,
|
||||
jack: Jack<Notifications>,
|
||||
cursor: (u16, u16, u16),
|
||||
sequence: Vec<Vec<Option<Event>>>,
|
||||
exited: bool,
|
||||
cursor: (u16, u16, u16),
|
||||
sequence: Vec<Vec<Option<Event>>>,
|
||||
transport: ::jack::Transport,
|
||||
bpm: f64,
|
||||
timesig: (f32, f32),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
@ -27,24 +29,15 @@ pub enum Event {
|
|||
}
|
||||
|
||||
impl Sequencer {
|
||||
pub fn new () -> Result<Self, Box<dyn Error>> {
|
||||
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 Box<dyn FnMut(&Client, &ProcessScope)->Control + Send>
|
||||
)
|
||||
)?;
|
||||
pub fn new (client: &Client) -> Result<Self, Box<dyn Error>> {
|
||||
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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ fn render_grid (
|
|||
offset: (u16, u16)
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
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))
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Self, Box<dyn Error>> {
|
||||
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,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue