mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 12:46:42 +01:00
wip: sequencer now copies from buffers
This commit is contained in:
parent
aa478099d9
commit
2fc8e84551
15 changed files with 310 additions and 256 deletions
|
|
@ -1,46 +1,160 @@
|
|||
use crate::{core::*, model::Phrase};
|
||||
use crate::{core::*, model::{FixedAxis, ScaledAxis, Phrase}};
|
||||
|
||||
pub struct Sequencer {
|
||||
pub phrase: Option<Arc<RwLock<Phrase>>>,
|
||||
pub mode: bool,
|
||||
pub buffer: Buffer,
|
||||
pub now: usize,
|
||||
pub ppq: usize,
|
||||
pub note_cursor: usize,
|
||||
pub note_start: usize,
|
||||
pub time_cursor: usize,
|
||||
pub time_start: usize,
|
||||
pub time_zoom: usize,
|
||||
|
||||
pub focused: bool,
|
||||
pub entered: bool,
|
||||
pub mode: bool,
|
||||
pub focused: bool,
|
||||
pub entered: bool,
|
||||
|
||||
pub phrase: Option<Arc<RwLock<Phrase>>>,
|
||||
pub buffer: Buffer,
|
||||
pub keys: Buffer,
|
||||
/// Highlight input keys
|
||||
pub notes_in: [bool; 128],
|
||||
pub keys_in: [bool; 128],
|
||||
/// Highlight output keys
|
||||
pub notes_out: [bool; 128],
|
||||
pub keys_out: [bool; 128],
|
||||
|
||||
pub now: usize,
|
||||
pub ppq: usize,
|
||||
pub note_axis: FixedAxis<u16>,
|
||||
pub time_axis: ScaledAxis<u16>,
|
||||
|
||||
}
|
||||
|
||||
impl Sequencer {
|
||||
pub fn new () -> Self {
|
||||
Self {
|
||||
buffer: Buffer::empty(Rect::default()),
|
||||
entered: false,
|
||||
focused: false,
|
||||
mode: false,
|
||||
note_cursor: 0,
|
||||
note_start: 0,
|
||||
notes_in: [false;128],
|
||||
notes_out: [false;128],
|
||||
phrase: None,
|
||||
time_cursor: 0,
|
||||
time_start: 0,
|
||||
time_zoom: 12,
|
||||
now: 0,
|
||||
ppq: 96
|
||||
buffer: Buffer::empty(Rect::default()),
|
||||
keys: keys_vert(),
|
||||
entered: false,
|
||||
focused: false,
|
||||
mode: false,
|
||||
keys_in: [false;128],
|
||||
keys_out: [false;128],
|
||||
phrase: None,
|
||||
now: 0,
|
||||
ppq: 96,
|
||||
note_axis: FixedAxis {
|
||||
start: 12,
|
||||
point: Some(36)
|
||||
},
|
||||
time_axis: ScaledAxis {
|
||||
start: 0,
|
||||
scale: 24,
|
||||
point: Some(0)
|
||||
},
|
||||
}
|
||||
}
|
||||
pub fn show (&mut self, phrase: Option<&Arc<RwLock<Phrase>>>) {
|
||||
/// Select which pattern to display. This pre-renders it to the buffer at full resolution.
|
||||
/// FIXME: Support phrases longer that 65536 ticks
|
||||
pub fn show (&mut self, phrase: Option<&Arc<RwLock<Phrase>>>) -> Usually<()> {
|
||||
self.phrase = phrase.map(Clone::clone);
|
||||
if let Some(ref phrase) = self.phrase {
|
||||
let width = u16::MAX.min(phrase.read().unwrap().length as u16);
|
||||
let mut buffer = Buffer::empty(Rect { x: 0, y: 0, width, height: 64 });
|
||||
let phrase = phrase.read().unwrap();
|
||||
fill_seq_bg(&mut buffer, phrase.length, self.ppq)?;
|
||||
fill_seq_fg(&mut buffer, &phrase)?;
|
||||
self.buffer = buffer;
|
||||
} else {
|
||||
self.buffer = Buffer::empty(Rect::default())
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn keys_vert () -> Buffer {
|
||||
let area = Rect { x: 0, y: 0, width: 5, height: 64 };
|
||||
let mut buffer = Buffer::empty(area);
|
||||
buffer_update(&mut buffer, area, &|cell, x, y| {
|
||||
cell.set_char('▀');
|
||||
match x {
|
||||
0 => {
|
||||
let (fg, bg) = key_colors(y);
|
||||
cell.set_fg(fg);
|
||||
cell.set_bg(bg);
|
||||
},
|
||||
1 => {
|
||||
cell.set_fg(Color::White);
|
||||
cell.set_bg(Color::White);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
buffer
|
||||
}
|
||||
|
||||
fn key_colors (index: u16) -> (Color, Color) {
|
||||
match index % 6 {
|
||||
0 => (Color::White, Color::Black),
|
||||
1 => (Color::White, Color::Black),
|
||||
2 => (Color::White, Color::White),
|
||||
3 => (Color::Black, Color::White),
|
||||
4 => (Color::Black, Color::White),
|
||||
5 => (Color::Black, Color::White),
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
fn fill_seq_bg (buf: &mut Buffer, length: usize, ppq: usize) -> Usually<()> {
|
||||
for x in 0 .. buf.area.width - buf.area.x {
|
||||
if x as usize >= length {
|
||||
break
|
||||
}
|
||||
let style = Style::default();
|
||||
let cell = buf.get_mut(x, buf.area.y);
|
||||
cell.set_char('-');
|
||||
cell.set_style(style);
|
||||
let character = if ppq > 0 && x as usize % ppq == 0 { '|' } else { '·' };
|
||||
for y in 0 .. buf.area.height - buf.area.y {
|
||||
let cell = buf.get_mut(x, y);
|
||||
cell.set_char(character);
|
||||
cell.set_fg(Color::Gray);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fill_seq_fg (buf: &mut Buffer, phrase: &Phrase) -> Usually<()> {
|
||||
let mut notes_on = [false;128];
|
||||
for x in 0 .. buf.area.width - buf.area.x {
|
||||
if x as usize >= phrase.length {
|
||||
break
|
||||
}
|
||||
if let Some(notes) = phrase.notes.get(x as usize) {
|
||||
for note in notes {
|
||||
if phrase.percussive {
|
||||
match note {
|
||||
MidiMessage::NoteOn { key, .. } =>
|
||||
notes_on[key.as_int() as usize] = true,
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
match note {
|
||||
MidiMessage::NoteOn { key, .. } =>
|
||||
notes_on[key.as_int() as usize] = true,
|
||||
MidiMessage::NoteOff { key, .. } =>
|
||||
notes_on[key.as_int() as usize] = false,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
for y in 0 .. (buf.area.height - buf.area.y) / 2 {
|
||||
if y >= 64 {
|
||||
break
|
||||
}
|
||||
if let Some(block) = half_block(
|
||||
notes_on[y as usize * 2],
|
||||
notes_on[y as usize * 2 + 1],
|
||||
) {
|
||||
let cell = buf.get_mut(x, y);
|
||||
cell.set_char(block);
|
||||
cell.set_fg(Color::White);
|
||||
}
|
||||
}
|
||||
if phrase.percussive {
|
||||
notes_on.fill(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue