light up keys

This commit is contained in:
🪞👃🪞 2024-06-16 19:25:31 +03:00
parent e4f3942757
commit 2e7252f8b9
3 changed files with 86 additions and 53 deletions

View file

@ -20,6 +20,7 @@ pub struct Sequencer {
playing: bool,
recording: bool,
overdub: bool,
notes_on: Vec<bool>,
}
enum SequencerView {
@ -32,31 +33,27 @@ enum SequencerView {
impl Sequencer {
pub fn new (name: &str) -> Usually<DynamicDevice<Self>> {
let (client, _status) = Client::new(name, ClientOptions::NO_START_SERVER)?;
DynamicDevice::new(
render,
handle,
process,
Self {
name: name.into(),
mode: SequencerView::Horizontal,
note_axis: (36, 60),
note_cursor: 0,
time_axis: (0, 64),
time_cursor: 0,
rate: Hz(client.sample_rate() as u32),
tempo: Tempo(120000),
transport: client.transport(),
input_port: client.register_port("in", MidiIn::default())?,
input_connect: vec!["nanoKEY Studio * (capture): *".into()],
output_port: client.register_port("out", MidiOut::default())?,
output_connect: vec![],
ppq: 96,
sequence: std::collections::BTreeMap::new(),
playing: true,
recording: true,
overdub: true,
}
).activate(client)
DynamicDevice::new(render, handle, process, Self {
name: name.into(),
mode: SequencerView::Vertical,
note_axis: (36, 60),
note_cursor: 0,
time_axis: (0, 64),
time_cursor: 0,
rate: Hz(client.sample_rate() as u32),
tempo: Tempo(120000),
transport: client.transport(),
input_port: client.register_port("in", MidiIn::default())?,
input_connect: vec!["nanoKEY Studio * (capture): *".into()],
output_port: client.register_port("out", MidiOut::default())?,
output_connect: vec![],
ppq: 96,
sequence: std::collections::BTreeMap::new(),
playing: true,
recording: true,
overdub: true,
notes_on: vec![false;128],
}).activate(client)
}
}
@ -66,15 +63,15 @@ pub fn process (state: &mut Sequencer, client: &Client, scope: &ProcessScope) ->
Control::Continue
}
fn process_in (state: &Sequencer, scope: &ProcessScope) {
fn process_in (state: &mut Sequencer, scope: &ProcessScope) {
for event in state.input_port.iter(scope) {
match midly::live::LiveEvent::parse(event.bytes).unwrap() {
midly::live::LiveEvent::Midi { channel, message } => match message {
midly::MidiMessage::NoteOn { key, vel } => {
panic!("on")
state.notes_on[key.as_int() as usize] = true
},
midly::MidiMessage::NoteOff { key, vel } => {
panic!("off")
state.notes_on[key.as_int() as usize] = false
},
_ => {}
},
@ -313,21 +310,57 @@ fn draw_sequencer_vertical (sequencer: &Sequencer, buf: &mut Buffer, area: Rect)
let Rect { x, y, .. } = area;
let (time0, time1) = sequencer.time_axis;
let (note0, note1) = sequencer.note_axis;
let bw = Style::default().dim();
let bg = Style::default().on_black();
for step in 0..(time1-time0)/2 {
let y = y + step - time0;
buf.set_string(x + 5, y, &" ".repeat(32.max(note1-note0)as usize), bg);
if step % 2 == 0 {
buf.set_string(x + 2, y, &format!("{:2} ", step / 2 + 1), Style::default());
}
}
for key in note0..note1.max(note0+32) {
let x = x + 5 + key - note0;
let color = KEY_HORIZONTAL_STYLE[key as usize % 12];
let color = if sequencer.notes_on[key as usize] {
Style::default().red()
} else {
KEY_HORIZONTAL_STYLE[key as usize % 12]
};
buf.set_string(x, y - 1, &format!(""), color);
if key % 12 == 0 {
let octave = format!("C{}", (key / 12) as i8 - 4);
buf.set_string(x, y + 1, &octave, Style::default());
buf.set_string(x, y, &octave, Style::default());
}
}
for step in time0..time1 {
let y = y - time0 + step / 2;
buf.set_string(x + 5, y, &" ".repeat(32.max(note1-note0)as usize), bg);
if step % 8 == 0 {
buf.set_string(x + 2, y, &format!("{:2} ", step + 1), Style::default());
}
if step % 2 == 0 {
let mut has_1 = false;
let (start, end) = (
(step + 0) as u32 * sequencer.ppq,
(step + 1) as u32 * sequencer.ppq);
for (i, (t, events)) in sequencer.sequence.range(start..end).enumerate() {
if events.len() > 0 {
has_1 = true;
break
}
}
let mut has_2 = false;
let (start, end) = (
(step + 1) as u32 * sequencer.ppq,
(step + 2) as u32 * sequencer.ppq
);
for (i, (t, events)) in sequencer.sequence.range(start..end).enumerate() {
if events.len() > 0 {
has_2 = true;
break
}
}
if has_1 || has_2 {
buf.set_string(x + 4, y, &match (has_1, has_2) {
(true, true) => "",
(true, false) => "",
(false, true) => "",
_ => " ",
}, Style::default());
}
}
}
buf.set_string(