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"
#vst3 = "0.1.0"
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();
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 + 0, y + 2, &format!("├--------------------------------------"), style.dim());
buf.set_string(x + 0, y + 2, &format!("├------------------------------------------------"), style.dim());
match &state.plugin {
Some(PluginKind::LV2(ports, instance)) => {
let mut height = 3;
for (i, port) in ports.iter().skip(state.parameter_offset).enumerate() {
if i >= 10 {
if i >= 20 {
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.default_value
), Style::default());
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);

View file

@ -88,17 +88,18 @@ impl Sequencer {
}
fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control {
process_out(self, scope);
process_in(self, scope);
let transport = self.transport.query().unwrap();
process_out(self, scope, &transport);
process_in(self, scope, &transport);
Control::Continue
}
}
fn process_in (s: &mut Sequencer, scope: &ProcessScope) {
fn process_in (s: &mut Sequencer, scope: &ProcessScope, transport: &::jack::TransportStatePosition) {
if !s.recording {
return
}
let pos = s.transport.query().unwrap().pos;
let pos = &transport.pos;
let usecs = s.timebase.frame_to_usec(pos.frame() as usize);
let steps = usecs / s.timebase.usec_per_step(s.resolution as usize);
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 {
return
}
let transport = s.transport.query().unwrap();
if transport.state != ::jack::TransportState::Rolling {
return
}
@ -196,7 +196,7 @@ fn render (s: &Sequencer, buf: &mut Buffer, mut area: Rect) -> Usually<Rect> {
SequencerView::Horizontal => draw_horizontal(s, buf, Rect {
x,
y: y + header.height,
width: 3 + time1 - time0,
width: area.width.max(3 + time1 - time0),
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 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 + 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,
//&format!("▶ PLAY"), if s.playing {
//Style::default().green()
@ -225,14 +230,20 @@ fn draw_header (s: &Sequencer, buf: &mut Buffer, area: Rect, beat: usize) -> Usu
//Style::default().dim()
//});
buf.set_string(x + 10, y + 1,
&format!("REC"), if s.recording {
Style::default().red()
&format!("MON"), if s.monitoring {
Style::default().bold().green()
} else {
Style::default().bold().dim()
});
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 {
Style::default().yellow()
Style::default().bold().yellow()
} else {
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> {
let Rect { x, y, .. } = area;
let style = Style::default().gray();
buf.set_string(x + 2, y + 3, &format!("{}", &s.name), style.not_dim().bold());
buf.set_string(x + 2, y + 5, &format!("{}", &s.name), style.dim());
buf.set_string(x + 2, y + 7, &format!("{}", &s.name), style.dim());
buf.set_string(x + 2, y + 9, &format!("{}", &s.name), style.dim());
buf.set_string(x + 2, y + 11, &format!("{}", &s.name), style.dim());
buf.set_string(x + 2, y + 13, &format!("{}", &s.name), style.dim());
buf.set_string(x + 2, y + 15, &format!("{}", &s.name), style.dim());
buf.set_string(x + 2, y + 17, &format!("{}", &s.name), style.dim());
for i in 0..8 {
buf.set_string(x + 2, y + 3 + i*2, &format!("{}", &s.name), if i as usize == s.sequence {
if s.playing {
style.white().bold()
} else {
style.not_dim().bold()
}
} else {
style.dim()
});
}
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 { "" },
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 {
@ -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> {
area.x = area.x + 13;
let Rect { x, y, .. } = area;
let Rect { x, y, width, .. } = area;
let (time0, time1) = s.time_axis;
let (note0, note1) = s.note_axis;
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;
buf.set_string(x + 2, y + height, format!(
" Q 1/{} | N {} ({}-{}) | T {} ({}-{})",
buf.set_string(x - 13, y + height, format!("{}", "-".repeat((width - 2).into())),
Style::default().dim());
buf.set_string(x - 11, y + height + 1, format!(
"Sync 4/4 Quantize 1/{} Notes {} ({}-{}) Time {} ({}-{})",
4 * s.resolution,
s.note_axis.0 + s.note_cursor,
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 + 1,
s.time_axis.1,
), Style::default().dim());
), Style::default().not_dim());
buf.set_string(
x + 6 + s.time_cursor,
y + s.note_cursor / 2,
@ -448,7 +464,7 @@ fn draw_horizontal (s: &Sequencer, buf: &mut Buffer, mut area: Rect) -> Usually<
x: x - 13,
y,
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 {
[Up, NONE, "cursor_up", "move cursor up", cursor_up],
[Down, NONE, "cursor_down", "move cursor down", cursor_down],
[Left, NONE, "cursor_left", "move cursor left", cursor_left],
[Right, NONE, "cursor_right", "move cursor right", cursor_right],
[Char(']'), NONE, "cursor_inc", "increase note duration", cursor_duration_inc],
[Char('['), NONE, "cursor_dec", "decrease note duration", cursor_duration_dec],
[Char('`'), NONE, "mode_next", "Next view mode", mode_next],
[Char('+'), NONE, "zoom_in", "Zoom in", nop],
[Char('-'), NONE, "zoom_out", "Zoom out", nop],
[Char('a'), NONE, "note_add", "Add note", note_add],
[Char('d'), NONE, "note_del", "Delete note", note_del],
[CapsLock, NONE, "advance", "Toggle auto advance", nop],
[Char('w'), NONE, "rest", "Advance by note duration", nop],
[Char('r'), NONE, "record", "Toggle recodring", toggle_record],
[Char('o'), NONE, "overdub", "Toggle overdub", toggle_overdub],
[Char('p'), NONE, "play", "Toggle play/pause", toggle_play],
[Char('s'), NONE, "stop", "Stop and rewind", stop_and_rewind],
[Char('q'), NONE, "quantize_next", "Next quantize value", quantize_next],
[Char('Q'), SHIFT, "quantize_prev", "Previous quantize value", quantize_prev],
[Char('n'), NONE, "note_axis", "Focus note axis", nop],
[Char('t'), NONE, "time_axis", "Focus time axis", nop],
[Char('v'), NONE, "variations", "Focus variation selector", nop],
[Char('s'), SHIFT, "sync", "Focus sync selector", nop],
[Char('1'), NONE, "focus_1", "Sequence 1", focus_seq(0)],
[Char('2'), NONE, "focus_1", "Sequence 1", focus_seq(1)],
[Char('3'), NONE, "focus_1", "Sequence 1", focus_seq(2)],
[Char('4'), NONE, "focus_1", "Sequence 1", focus_seq(3)],
[Char('5'), NONE, "focus_1", "Sequence 1", focus_seq(4)],
[Char('6'), NONE, "focus_1", "Sequence 1", focus_seq(5)],
[Char('7'), NONE, "focus_1", "Sequence 1", focus_seq(6)],
[Char('8'), NONE, "focus_1", "Sequence 1", focus_seq(7)],
[Up, NONE, "cursor_up", "move cursor up", cursor_up],
[Down, NONE, "cursor_down", "move cursor down", cursor_down],
[Left, NONE, "cursor_left", "move cursor left", cursor_left],
[Right, NONE, "cursor_right", "move cursor right", cursor_right],
[Char(']'), NONE, "cursor_inc", "increase note duration", cursor_duration_inc],
[Char('['), NONE, "cursor_dec", "decrease note duration", cursor_duration_dec],
[Char('`'), NONE, "mode_next", "Next view mode", mode_next],
[Char('+'), NONE, "zoom_in", "Zoom in", nop],
[Char('-'), NONE, "zoom_out", "Zoom out", nop],
[Char('a'), NONE, "note_add", "Add note", note_add],
[Char('z'), NONE, "note_del", "Delete note", note_del],
[CapsLock, NONE, "advance", "Toggle auto advance", nop],
[Char('w'), NONE, "rest", "Advance by note duration", nop],
[Char('r'), NONE, "toggle_record", "Toggle recording", toggle_record],
[Char('d'), NONE, "toggle_overdub", "Toggle overdub", toggle_overdub],
[Char(' '), NONE, "toggle_play", "Toggle play/pause", toggle_play],
[Char('s'), NONE, "stop_and_rewind", "Stop and rewind", stop_and_rewind],
[Char('q'), NONE, "quantize_next", "Next quantize value", quantize_next],
[Char('Q'), SHIFT, "quantize_prev", "Previous quantize value", quantize_prev],
[Char('n'), NONE, "note_axis", "Focus note axis", nop],
[Char('t'), NONE, "time_axis", "Focus time axis", nop],
[Char('v'), NONE, "variations", "Focus variation selector", nop],
[Char('s'), SHIFT, "sync", "Focus sync selector", nop],
[Char('1'), NONE, "seq_1", "Sequence 1", focus_seq(0)],
[Char('2'), NONE, "seq_2", "Sequence 2", focus_seq(1)],
[Char('3'), NONE, "seq_3", "Sequence 3", focus_seq(2)],
[Char('4'), NONE, "seq_4", "Sequence 4", focus_seq(3)],
[Char('5'), NONE, "seq_5", "Sequence 5", focus_seq(4)],
[Char('6'), NONE, "seq_6", "Sequence 6", focus_seq(5)],
[Char('7'), NONE, "seq_7", "Sequence 7", focus_seq(6)],
[Char('8'), NONE, "seq_8", "Sequence 8", focus_seq(7)],
});
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> {
s.playing = !s.playing;
if s.playing {
s.transport.start()?;
} else {
s.transport.stop()?;
s.transport.locate(0)?;
}
Ok(true)
}
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()));
buffer.set_string(area.x, area.y, top, style);
for y in (area.y + 1)..(area.y + area.height - 1) {
buffer.set_string(area.x, y, format!(""), style);
buffer.set_string(area.x + area.width - 1, 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.y + area.height - 1, bottom, style);
area