mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
wip: highlight keys
This commit is contained in:
parent
dff42ca5a7
commit
1e3d96e64e
5 changed files with 124 additions and 35 deletions
|
|
@ -54,7 +54,7 @@ impl Phrase {
|
|||
pub fn process_out (
|
||||
&self,
|
||||
output: &mut MIDIChunk,
|
||||
notes_on: &mut Vec<bool>,
|
||||
notes_on: &mut [bool;128],
|
||||
timebase: &Arc<Timebase>,
|
||||
(frame0, frames, _): (usize, usize, f64),
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -16,15 +16,17 @@ pub struct Track {
|
|||
/// Output from current sequence.
|
||||
pub midi_out: Port<MidiOut>,
|
||||
midi_out_buf: Vec<Vec<Vec<u8>>>,
|
||||
/// Red keys on piano roll.
|
||||
pub notes_on: Vec<bool>,
|
||||
/// Device chain
|
||||
pub devices: Vec<JackDevice>,
|
||||
/// Device selector
|
||||
pub device: usize,
|
||||
/// Send all notes off
|
||||
/// FIXME: Some(nframes)?
|
||||
pub reset: bool
|
||||
pub reset: bool,
|
||||
/// Highlight keys on piano roll.
|
||||
pub notes_in: [bool;128],
|
||||
/// Highlight keys on piano roll.
|
||||
pub notes_out: [bool;128],
|
||||
}
|
||||
ports!(Track {
|
||||
audio: {
|
||||
|
|
@ -46,7 +48,8 @@ impl Track {
|
|||
name: name.to_string(),
|
||||
midi_out: jack.register_port(name, MidiOut)?,
|
||||
midi_out_buf: vec![vec![];16384],
|
||||
notes_on: vec![false;128],
|
||||
notes_in: [false;128],
|
||||
notes_out: [false;128],
|
||||
monitoring: false,
|
||||
recording: false,
|
||||
overdub: true,
|
||||
|
|
@ -147,14 +150,13 @@ impl Track {
|
|||
) {
|
||||
phrase.process_out(
|
||||
&mut self.midi_out_buf,
|
||||
&mut self.notes_on,
|
||||
&mut self.notes_out,
|
||||
timebase,
|
||||
(frame0.saturating_sub(start_frame), frames, period)
|
||||
);
|
||||
// Monitor and record input
|
||||
if self.recording || self.monitoring {
|
||||
// For highlighting keys and note repeat
|
||||
let notes_on = &mut self.notes_on;
|
||||
for (frame, event, bytes) in parse_midi_input(input) {
|
||||
match event {
|
||||
LiveEvent::Midi { message, .. } => {
|
||||
|
|
@ -175,10 +177,10 @@ impl Track {
|
|||
}
|
||||
match message {
|
||||
MidiMessage::NoteOn { key, .. } => {
|
||||
notes_on[key.as_int() as usize] = true;
|
||||
self.notes_in[key.as_int() as usize] = true;
|
||||
}
|
||||
MidiMessage::NoteOff { key, .. } => {
|
||||
notes_on[key.as_int() as usize] = false;
|
||||
self.notes_in[key.as_int() as usize] = false;
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
|
@ -218,10 +220,10 @@ impl Track {
|
|||
fn process_monitor_message (&mut self, message: &MidiMessage) {
|
||||
match message {
|
||||
MidiMessage::NoteOn { key, .. } => {
|
||||
self.notes_on[key.as_int() as usize] = true;
|
||||
self.notes_in[key.as_int() as usize] = true;
|
||||
}
|
||||
MidiMessage::NoteOff { key, .. } => {
|
||||
self.notes_on[key.as_int() as usize] = false;
|
||||
self.notes_in[key.as_int() as usize] = false;
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ impl App {
|
|||
}.render(buf, area)
|
||||
}
|
||||
fn draw_phrase (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
|
||||
let track = self.tracks.get(self.track_cursor - 1);
|
||||
let phrase = self.phrase();
|
||||
let seq_area = SequencerView {
|
||||
phrase,
|
||||
|
|
@ -140,8 +141,10 @@ impl App {
|
|||
time_zoom: self.time_zoom,
|
||||
note_cursor: self.note_cursor,
|
||||
note_start: self.note_start,
|
||||
notes_in: if let Some(track) = track { &track.notes_in } else { &[false;128] },
|
||||
notes_out: if let Some(track) = track { &track.notes_out } else { &[false;128] },
|
||||
}.render(buf, area)?;
|
||||
if let Some(track) = self.tracks.get(self.track_cursor - 1) {
|
||||
if let Some(track) = track {
|
||||
if phrase.is_none() && self.section == AppSection::Sequencer {
|
||||
let label = format!("[ENTER] Create new clip: {}", track.name);
|
||||
let x = area.x + seq_area.width / 2 - (label.len() / 2) as u16;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,12 @@ pub struct SequencerView<'a> {
|
|||
/// Position of cursor within time range
|
||||
pub time_cursor: usize,
|
||||
/// Current time
|
||||
pub now: usize
|
||||
pub now: usize,
|
||||
|
||||
/// Highlight input keys
|
||||
pub notes_in: &'a [bool; 128],
|
||||
/// Highlight output keys
|
||||
pub notes_out: &'a [bool; 128],
|
||||
}
|
||||
|
||||
impl<'a> Render for SequencerView<'a> {
|
||||
|
|
@ -39,8 +44,7 @@ impl<'a> SequencerView<'a> {
|
|||
} else {
|
||||
Style::default().green().dim()
|
||||
});
|
||||
let notes = &[];
|
||||
self::horizontal::keys(buf, area, self.note_start, notes)?;
|
||||
self::horizontal::keys(buf, area, self.note_start, self.notes_in, self.notes_out)?;
|
||||
let quant = ppq_to_name(self.time_zoom);
|
||||
quant.blit(
|
||||
buf,
|
||||
|
|
@ -76,10 +80,17 @@ mod horizontal {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn keys (buf: &mut Buffer, area: Rect, note0: usize, _notes: &[bool])
|
||||
-> Usually<Rect>
|
||||
{
|
||||
let dim = Style::default().dim();
|
||||
pub fn keys (
|
||||
buf: &mut Buffer,
|
||||
area: Rect,
|
||||
note0: usize,
|
||||
notes_in: &[bool;128],
|
||||
notes_out: &[bool;128],
|
||||
) -> Usually<Rect> {
|
||||
let dim = Style::default().not_dim();
|
||||
let red = Style::default().red();
|
||||
let yellow = Style::default().yellow();
|
||||
let green = Style::default().green();
|
||||
|
||||
let mut cell_bg = Cell::default();
|
||||
cell_bg.set_char('░');
|
||||
|
|
@ -102,12 +113,82 @@ mod horizontal {
|
|||
let Rect { x, y, width, height } = area;
|
||||
let height = height.min(128);
|
||||
let h = height.saturating_sub(2);
|
||||
let index_to_color = |index: usize, default: Color|
|
||||
if notes_in[index] && notes_out[index] {
|
||||
Color::Yellow
|
||||
} else if notes_in[index] {
|
||||
Color::Red
|
||||
} else if notes_out[index] {
|
||||
Color::Green
|
||||
} else {
|
||||
default
|
||||
};
|
||||
|
||||
for index in 0..h {
|
||||
let y = y + h - index;
|
||||
let key1 = buf.get_mut(x + 1, y);
|
||||
*key1 = cell_keys[(index % 6) as usize].clone();
|
||||
let key2 = buf.get_mut(x + 2, y);
|
||||
*key2 = cell_full.clone();
|
||||
match index % 6 {
|
||||
0 => {
|
||||
let key1 = buf.get_mut(x + 1, y);
|
||||
*key1 = cell_lo.clone();
|
||||
key1.set_fg(index_to_color(index as usize * 2, Color::White));
|
||||
key1.set_bg(index_to_color(index as usize * 2 + 1, Color::Black));
|
||||
let key2 = buf.get_mut(x + 2, y);
|
||||
*key2 = cell_lo.clone();
|
||||
key2.set_fg(index_to_color(index as usize * 2, Color::White));
|
||||
key2.set_bg(index_to_color(index as usize * 2 + 1, Color::White));
|
||||
},
|
||||
1 => {
|
||||
let key1 = buf.get_mut(x + 1, y);
|
||||
*key1 = cell_lo.clone();
|
||||
key1.set_fg(index_to_color(index as usize * 2, Color::White));
|
||||
key1.set_bg(index_to_color(index as usize * 2 + 1, Color::Black));
|
||||
let key2 = buf.get_mut(x + 2, y);
|
||||
*key2 = cell_lo.clone();
|
||||
key2.set_fg(index_to_color(index as usize * 2, Color::White));
|
||||
key2.set_bg(index_to_color(index as usize * 2 + 1, Color::White));
|
||||
},
|
||||
2 => {
|
||||
let key1 = buf.get_mut(x + 1, y);
|
||||
*key1 = cell_lo.clone();
|
||||
key1.set_fg(index_to_color(index as usize * 2, Color::White));
|
||||
key1.set_bg(index_to_color(index as usize * 2 + 1, Color::White));
|
||||
let key2 = buf.get_mut(x + 2, y);
|
||||
*key2 = cell_lo.clone();
|
||||
key2.set_fg(index_to_color(index as usize * 2, Color::White));
|
||||
key2.set_bg(index_to_color(index as usize * 2 + 1, Color::White));
|
||||
},
|
||||
3 => {
|
||||
let key1 = buf.get_mut(x + 1, y);
|
||||
*key1 = cell_lo.clone();
|
||||
key1.set_fg(index_to_color(index as usize * 2, Color::Black));
|
||||
key1.set_bg(index_to_color(index as usize * 2 + 1, Color::White));
|
||||
let key2 = buf.get_mut(x + 2, y);
|
||||
*key2 = cell_lo.clone();
|
||||
key2.set_fg(index_to_color(index as usize * 2, Color::White));
|
||||
key2.set_bg(index_to_color(index as usize * 2 + 1, Color::White));
|
||||
},
|
||||
4 => {
|
||||
let key1 = buf.get_mut(x + 1, y);
|
||||
*key1 = cell_lo.clone();
|
||||
key1.set_fg(index_to_color(index as usize * 2, Color::Black));
|
||||
key1.set_bg(index_to_color(index as usize * 2 + 1, Color::White));
|
||||
let key2 = buf.get_mut(x + 2, y);
|
||||
*key2 = cell_lo.clone();
|
||||
key2.set_fg(index_to_color(index as usize * 2, Color::White));
|
||||
key2.set_bg(index_to_color(index as usize * 2 + 1, Color::White));
|
||||
},
|
||||
5 => {
|
||||
let key1 = buf.get_mut(x + 1, y);
|
||||
*key1 = cell_lo.clone();
|
||||
key1.set_fg(index_to_color(index as usize * 2, Color::Black));
|
||||
key1.set_bg(index_to_color(index as usize * 2 + 1, Color::White));
|
||||
let key2 = buf.get_mut(x + 2, y);
|
||||
*key2 = cell_lo.clone();
|
||||
key2.set_fg(index_to_color(index as usize * 2, Color::White));
|
||||
key2.set_bg(index_to_color(index as usize * 2 + 1, Color::White));
|
||||
},
|
||||
_ => { unreachable!(); }
|
||||
}
|
||||
for x in x+5..x+width-1 {
|
||||
*buf.get_mut(x, y) = cell_bg.clone();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue