transport master

This commit is contained in:
🪞👃🪞 2024-06-21 13:32:20 +03:00
parent 185c6b5b34
commit be2c2df92b
4 changed files with 85 additions and 62 deletions

View file

@ -16,3 +16,4 @@ midly = "0.5"
vst = "0.4.0" vst = "0.4.0"
#vst3 = "0.1.0" #vst3 = "0.1.0"
livi = "0.7.4" livi = "0.7.4"
#atomic_enum = "0.3.0"

View file

@ -44,21 +44,21 @@ pub fn render (state: &Plugin, buf: &mut Buffer, Rect { x, y, .. }: Rect)
let style = Style::default().gray(); let style = Style::default().gray();
buf.set_string(x + 1, y + 1, &format!(" {}", state.name), style.white().bold()); buf.set_string(x + 1, y + 1, &format!(" {}", state.name), style.white().bold());
buf.set_string(x + 13, y + 1, &format!("│ ...{}...", &HELM[13..30]), style.not_dim()); buf.set_string(x + 13, y + 1, &format!("│ ...{}...", &HELM[13..30]), style.not_dim());
buf.set_string(x + 0, y + 2, &format!("├--------------------------------------"), style.dim()); buf.set_string(x + 0, y + 2, &format!("├------------------------------------------------"), style.dim());
match &state.plugin { match &state.plugin {
Some(PluginKind::LV2(ports, instance)) => { Some(PluginKind::LV2(ports, instance)) => {
let mut height = 3; let mut height = 3;
for (i, port) in ports.iter().skip(state.parameter_offset).enumerate() { for (i, port) in ports.iter().skip(state.parameter_offset).enumerate() {
if i >= 10 { if i >= 20 {
break break
} }
buf.set_string(x + 2, y + 3 + i as u16, &format!("{:20} = {:03}", buf.set_string(x + 2, y + 3 + i as u16, &format!("{:30} = {:03}",
port.name, port.name,
port.default_value port.default_value
), Style::default()); ), Style::default());
height = height + 1; height = height + 1;
} }
Ok(draw_box(buf, Rect { x, y, width: 40, height: height.max(10) })) Ok(draw_box(buf, Rect { x, y, width: 50, height: height.max(20) }))
}, },
_ => { _ => {
buf.set_string(x + 1, y + 3, &format!(" Parameter 1 0.0"), style); buf.set_string(x + 1, y + 3, &format!(" Parameter 1 0.0"), style);

View file

@ -88,17 +88,18 @@ impl Sequencer {
} }
fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control { fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control {
process_out(self, scope); let transport = self.transport.query().unwrap();
process_in(self, scope); process_out(self, scope, &transport);
process_in(self, scope, &transport);
Control::Continue Control::Continue
} }
} }
fn process_in (s: &mut Sequencer, scope: &ProcessScope) { fn process_in (s: &mut Sequencer, scope: &ProcessScope, transport: &::jack::TransportStatePosition) {
if !s.recording { if !s.recording {
return return
} }
let pos = s.transport.query().unwrap().pos; let pos = &transport.pos;
let usecs = s.timebase.frame_to_usec(pos.frame() as usize); let usecs = s.timebase.frame_to_usec(pos.frame() as usize);
let steps = usecs / s.timebase.usec_per_step(s.resolution as usize); let steps = usecs / s.timebase.usec_per_step(s.resolution as usize);
let step = steps % s.steps; let step = steps % s.steps;
@ -139,11 +140,10 @@ fn process_in (s: &mut Sequencer, scope: &ProcessScope) {
} }
} }
fn process_out (s: &mut Sequencer, scope: &ProcessScope) { fn process_out (s: &mut Sequencer, scope: &ProcessScope, transport: &::jack::TransportStatePosition) {
if !s.playing { if !s.playing {
return return
} }
let transport = s.transport.query().unwrap();
if transport.state != ::jack::TransportState::Rolling { if transport.state != ::jack::TransportState::Rolling {
return return
} }
@ -196,7 +196,7 @@ fn render (s: &Sequencer, buf: &mut Buffer, mut area: Rect) -> Usually<Rect> {
SequencerView::Horizontal => draw_horizontal(s, buf, Rect { SequencerView::Horizontal => draw_horizontal(s, buf, Rect {
x, x,
y: y + header.height, y: y + header.height,
width: 3 + time1 - time0, width: area.width.max(3 + time1 - time0),
height: 3 + note1 - note0, height: 3 + note1 - note0,
})?, })?,
}; };
@ -217,7 +217,12 @@ fn draw_header (s: &Sequencer, buf: &mut Buffer, area: Rect, beat: usize) -> Usu
let style = Style::default().gray(); let style = Style::default().gray();
let timer = format!("{rep}.{step:02} / {reps}.{steps}"); let timer = format!("{rep}.{step:02} / {reps}.{steps}");
buf.set_string(x + width - 2 - timer.len() as u16, y + 1, &timer, style.bold().not_dim()); buf.set_string(x + width - 2 - timer.len() as u16, y + 1, &timer, style.bold().not_dim());
buf.set_string(x + 2, y + 1, &format!("⏹ STOP"), style.not_dim().white().bold()); buf.set_string(x + 2, y + 1, &format!("⏹ STOP"), if s.playing {
style.dim().bold()
} else {
style.not_dim().white().bold()
});
buf.set_string(x, y + 2, format!("{}", "-".repeat((area.width - 2).into())), style.dim());
//buf.set_string(x + 2, y + 2, //buf.set_string(x + 2, y + 2,
//&format!("▶ PLAY"), if s.playing { //&format!("▶ PLAY"), if s.playing {
//Style::default().green() //Style::default().green()
@ -225,14 +230,20 @@ fn draw_header (s: &Sequencer, buf: &mut Buffer, area: Rect, beat: usize) -> Usu
//Style::default().dim() //Style::default().dim()
//}); //});
buf.set_string(x + 10, y + 1, buf.set_string(x + 10, y + 1,
&format!("REC"), if s.recording { &format!("MON"), if s.monitoring {
Style::default().red() Style::default().bold().green()
} else { } else {
Style::default().bold().dim() Style::default().bold().dim()
}); });
buf.set_string(x + 17, y + 1, buf.set_string(x + 17, y + 1,
&format!("⏺ REC"), if s.recording {
Style::default().bold().red()
} else {
Style::default().bold().dim()
});
buf.set_string(x + 24, y + 1,
&format!("⏺ DUB"), if s.overdub { &format!("⏺ DUB"), if s.overdub {
Style::default().yellow() Style::default().bold().yellow()
} else { } else {
Style::default().bold().dim() Style::default().bold().dim()
}); });
@ -243,14 +254,17 @@ fn draw_header (s: &Sequencer, buf: &mut Buffer, area: Rect, beat: usize) -> Usu
fn draw_clips (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually<Rect> { fn draw_clips (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
let Rect { x, y, .. } = area; let Rect { x, y, .. } = area;
let style = Style::default().gray(); let style = Style::default().gray();
buf.set_string(x + 2, y + 3, &format!("{}", &s.name), style.not_dim().bold()); for i in 0..8 {
buf.set_string(x + 2, y + 5, &format!("{}", &s.name), style.dim()); buf.set_string(x + 2, y + 3 + i*2, &format!("{}", &s.name), if i as usize == s.sequence {
buf.set_string(x + 2, y + 7, &format!("{}", &s.name), style.dim()); if s.playing {
buf.set_string(x + 2, y + 9, &format!("{}", &s.name), style.dim()); style.white().bold()
buf.set_string(x + 2, y + 11, &format!("{}", &s.name), style.dim()); } else {
buf.set_string(x + 2, y + 13, &format!("{}", &s.name), style.dim()); style.not_dim().bold()
buf.set_string(x + 2, y + 15, &format!("{}", &s.name), style.dim()); }
buf.set_string(x + 2, y + 17, &format!("{}", &s.name), style.dim()); } else {
style.dim()
});
}
Ok(Rect { x, y, width: 14, height: 14 }) Ok(Rect { x, y, width: 14, height: 14 })
} }
@ -350,7 +364,7 @@ fn draw_vertical (s: &Sequencer, buf: &mut Buffer, mut area: Rect, beat: usize)
if s.time_cursor % 2 == 0 { "" } else { "" }, if s.time_cursor % 2 == 0 { "" } else { "" },
Style::default() Style::default()
); );
Ok(Rect { x, y, width: area.width, height: height + 3 }) Ok(Rect { x, y, width: area.width, height: height + 1 })
} }
fn contains_note_on (sequence: &Sequence, k: ::midly::num::u7, start: u32, end: u32) -> bool { fn contains_note_on (sequence: &Sequence, k: ::midly::num::u7, start: u32, end: u32) -> bool {
@ -412,7 +426,7 @@ fn draw_keys_horizontal (s: &Sequencer, buf: &mut Buffer, mut area: Rect) -> Usu
fn draw_horizontal (s: &Sequencer, buf: &mut Buffer, mut area: Rect) -> Usually<Rect> { fn draw_horizontal (s: &Sequencer, buf: &mut Buffer, mut area: Rect) -> Usually<Rect> {
area.x = area.x + 13; area.x = area.x + 13;
let Rect { x, y, .. } = area; let Rect { x, y, width, .. } = area;
let (time0, time1) = s.time_axis; let (time0, time1) = s.time_axis;
let (note0, note1) = s.note_axis; let (note0, note1) = s.note_axis;
let bw = Style::default().dim(); let bw = Style::default().dim();
@ -428,8 +442,10 @@ fn draw_horizontal (s: &Sequencer, buf: &mut Buffer, mut area: Rect) -> Usually<
} }
} }
let height = 32.max(note1 - note0) / 2; let height = 32.max(note1 - note0) / 2;
buf.set_string(x + 2, y + height, format!( buf.set_string(x - 13, y + height, format!("{}", "-".repeat((width - 2).into())),
" Q 1/{} | N {} ({}-{}) | T {} ({}-{})", Style::default().dim());
buf.set_string(x - 11, y + height + 1, format!(
"Sync 4/4 Quantize 1/{} Notes {} ({}-{}) Time {} ({}-{})",
4 * s.resolution, 4 * s.resolution,
s.note_axis.0 + s.note_cursor, s.note_axis.0 + s.note_cursor,
s.note_axis.0, s.note_axis.0,
@ -437,7 +453,7 @@ fn draw_horizontal (s: &Sequencer, buf: &mut Buffer, mut area: Rect) -> Usually<
s.time_axis.0 + s.time_cursor + 1, s.time_axis.0 + s.time_cursor + 1,
s.time_axis.0 + 1, s.time_axis.0 + 1,
s.time_axis.1, s.time_axis.1,
), Style::default().dim()); ), Style::default().not_dim());
buf.set_string( buf.set_string(
x + 6 + s.time_cursor, x + 6 + s.time_cursor,
y + s.note_cursor / 2, y + s.note_cursor / 2,
@ -448,7 +464,7 @@ fn draw_horizontal (s: &Sequencer, buf: &mut Buffer, mut area: Rect) -> Usually<
x: x - 13, x: x - 13,
y, y,
width: time1 - time0 + 19, width: time1 - time0 + 19,
height: height + 2 height: height + 3
}) })
} }
@ -457,37 +473,37 @@ pub fn handle (s: &mut Sequencer, event: &AppEvent) -> Usually<bool> {
} }
pub const KEYMAP: &'static [KeyBinding<Sequencer>] = keymap!(Sequencer { pub const KEYMAP: &'static [KeyBinding<Sequencer>] = keymap!(Sequencer {
[Up, NONE, "cursor_up", "move cursor up", cursor_up], [Up, NONE, "cursor_up", "move cursor up", cursor_up],
[Down, NONE, "cursor_down", "move cursor down", cursor_down], [Down, NONE, "cursor_down", "move cursor down", cursor_down],
[Left, NONE, "cursor_left", "move cursor left", cursor_left], [Left, NONE, "cursor_left", "move cursor left", cursor_left],
[Right, NONE, "cursor_right", "move cursor right", cursor_right], [Right, NONE, "cursor_right", "move cursor right", cursor_right],
[Char(']'), NONE, "cursor_inc", "increase note duration", cursor_duration_inc], [Char(']'), NONE, "cursor_inc", "increase note duration", cursor_duration_inc],
[Char('['), NONE, "cursor_dec", "decrease note duration", cursor_duration_dec], [Char('['), NONE, "cursor_dec", "decrease note duration", cursor_duration_dec],
[Char('`'), NONE, "mode_next", "Next view mode", mode_next], [Char('`'), NONE, "mode_next", "Next view mode", mode_next],
[Char('+'), NONE, "zoom_in", "Zoom in", nop], [Char('+'), NONE, "zoom_in", "Zoom in", nop],
[Char('-'), NONE, "zoom_out", "Zoom out", nop], [Char('-'), NONE, "zoom_out", "Zoom out", nop],
[Char('a'), NONE, "note_add", "Add note", note_add], [Char('a'), NONE, "note_add", "Add note", note_add],
[Char('d'), NONE, "note_del", "Delete note", note_del], [Char('z'), NONE, "note_del", "Delete note", note_del],
[CapsLock, NONE, "advance", "Toggle auto advance", nop], [CapsLock, NONE, "advance", "Toggle auto advance", nop],
[Char('w'), NONE, "rest", "Advance by note duration", nop], [Char('w'), NONE, "rest", "Advance by note duration", nop],
[Char('r'), NONE, "record", "Toggle recodring", toggle_record], [Char('r'), NONE, "toggle_record", "Toggle recording", toggle_record],
[Char('o'), NONE, "overdub", "Toggle overdub", toggle_overdub], [Char('d'), NONE, "toggle_overdub", "Toggle overdub", toggle_overdub],
[Char('p'), NONE, "play", "Toggle play/pause", toggle_play], [Char(' '), NONE, "toggle_play", "Toggle play/pause", toggle_play],
[Char('s'), NONE, "stop", "Stop and rewind", stop_and_rewind], [Char('s'), NONE, "stop_and_rewind", "Stop and rewind", stop_and_rewind],
[Char('q'), NONE, "quantize_next", "Next quantize value", quantize_next], [Char('q'), NONE, "quantize_next", "Next quantize value", quantize_next],
[Char('Q'), SHIFT, "quantize_prev", "Previous quantize value", quantize_prev], [Char('Q'), SHIFT, "quantize_prev", "Previous quantize value", quantize_prev],
[Char('n'), NONE, "note_axis", "Focus note axis", nop], [Char('n'), NONE, "note_axis", "Focus note axis", nop],
[Char('t'), NONE, "time_axis", "Focus time axis", nop], [Char('t'), NONE, "time_axis", "Focus time axis", nop],
[Char('v'), NONE, "variations", "Focus variation selector", nop], [Char('v'), NONE, "variations", "Focus variation selector", nop],
[Char('s'), SHIFT, "sync", "Focus sync selector", nop], [Char('s'), SHIFT, "sync", "Focus sync selector", nop],
[Char('1'), NONE, "focus_1", "Sequence 1", focus_seq(0)], [Char('1'), NONE, "seq_1", "Sequence 1", focus_seq(0)],
[Char('2'), NONE, "focus_1", "Sequence 1", focus_seq(1)], [Char('2'), NONE, "seq_2", "Sequence 2", focus_seq(1)],
[Char('3'), NONE, "focus_1", "Sequence 1", focus_seq(2)], [Char('3'), NONE, "seq_3", "Sequence 3", focus_seq(2)],
[Char('4'), NONE, "focus_1", "Sequence 1", focus_seq(3)], [Char('4'), NONE, "seq_4", "Sequence 4", focus_seq(3)],
[Char('5'), NONE, "focus_1", "Sequence 1", focus_seq(4)], [Char('5'), NONE, "seq_5", "Sequence 5", focus_seq(4)],
[Char('6'), NONE, "focus_1", "Sequence 1", focus_seq(5)], [Char('6'), NONE, "seq_6", "Sequence 6", focus_seq(5)],
[Char('7'), NONE, "focus_1", "Sequence 1", focus_seq(6)], [Char('7'), NONE, "seq_7", "Sequence 7", focus_seq(6)],
[Char('8'), NONE, "focus_1", "Sequence 1", focus_seq(7)], [Char('8'), NONE, "seq_8", "Sequence 8", focus_seq(7)],
}); });
const fn focus_seq (i: usize) -> impl Fn(&mut Sequencer)->Usually<bool> { const fn focus_seq (i: usize) -> impl Fn(&mut Sequencer)->Usually<bool> {
@ -605,6 +621,12 @@ fn stop_and_rewind (s: &mut Sequencer) -> Usually<bool> {
} }
fn toggle_play (s: &mut Sequencer) -> Usually<bool> { fn toggle_play (s: &mut Sequencer) -> Usually<bool> {
s.playing = !s.playing; s.playing = !s.playing;
if s.playing {
s.transport.start()?;
} else {
s.transport.stop()?;
s.transport.locate(0)?;
}
Ok(true) Ok(true)
} }
fn toggle_record (s: &mut Sequencer) -> Usually<bool> { fn toggle_record (s: &mut Sequencer) -> Usually<bool> {

View file

@ -25,8 +25,8 @@ pub fn draw_box_styled (buffer: &mut Buffer, area: Rect, style: Option<Style>) -
let bottom = format!("{}", "".repeat((area.width - 2).into())); let bottom = format!("{}", "".repeat((area.width - 2).into()));
buffer.set_string(area.x, area.y, top, style); buffer.set_string(area.x, area.y, top, style);
for y in (area.y + 1)..(area.y + area.height - 1) { for y in (area.y + 1)..(area.y + area.height - 1) {
buffer.set_string(area.x, y, format!(""), style); buffer.set_string(area.x, y, format!(""), style);
buffer.set_string(area.x + area.width - 1, y, format!(""), style); buffer.set_string(area.x + area.width - 1, y, format!(""), style);
} }
buffer.set_string(area.x, area.y + area.height - 1, bottom, style); buffer.set_string(area.x, area.y + area.height - 1, bottom, style);
area area