wip: decruft

This commit is contained in:
🪞👃🪞 2024-07-01 14:35:02 +03:00
parent 78e5469b32
commit 55a8b67bfb
7 changed files with 125 additions and 180 deletions

View file

@ -254,7 +254,7 @@ fn trigger (state: &mut Sampler) -> Usually<bool> {
Ok(true) Ok(true)
} }
fn select (state: &mut Sampler) -> Usually<bool> { fn select (state: &mut Sampler) -> Usually<bool> {
for (i, sample) in state.samples.values().enumerate() { for (i, _sample) in state.samples.values().enumerate() {
if i == state.cursor.0 { if i == state.cursor.0 {
//state.voices.push(sample.play(0)) //state.voices.push(sample.play(0))
} }

View file

@ -50,7 +50,7 @@ fn duplicate (_: &mut Launcher) -> Usually<bool> {
} }
fn activate (state: &mut Launcher) -> Usually<bool> { fn activate (state: &mut Launcher) -> Usually<bool> {
if let ( if let (
Some((scene_id, scene)), Some((_scene_id, scene)),
Some((track_id, track)), Some((track_id, track)),
) = (state.scene(), state.track()) { ) = (state.scene(), state.track()) {
// Launch clip // Launch clip
@ -61,7 +61,7 @@ fn activate (state: &mut Launcher) -> Usually<bool> {
state.transport.start()?; state.transport.start()?;
state.playing = TransportState::Starting; state.playing = TransportState::Starting;
} }
} else if let Some((scene_id, scene)) = state.scene() { } else if let Some((_scene_id, scene)) = state.scene() {
// Launch scene // Launch scene
for (track_id, track) in state.tracks.iter().enumerate() { for (track_id, track) in state.tracks.iter().enumerate() {
if let Some(phrase_id) = scene.clips.get(track_id) { if let Some(phrase_id) = scene.clips.get(track_id) {
@ -72,7 +72,7 @@ fn activate (state: &mut Launcher) -> Usually<bool> {
state.transport.start()?; state.transport.start()?;
state.playing = TransportState::Starting; state.playing = TransportState::Starting;
} }
} else if let Some((track_id, track)) = state.track() { } else if let Some((_track_id, _track)) = state.track() {
// Rename track? // Rename track?
} }

View file

@ -186,12 +186,15 @@ pub fn render (state: &Launcher, buf: &mut Buffer, mut area: Rect) -> Usually<Re
//area.width = 80; // DOS mode //area.width = 80; // DOS mode
//area.height = 25; //area.height = 25;
let Rect { x, y, width, height } = area; let Rect { x, y, width, height } = area;
crate::device::transport::draw_play_stop(buf, x + 1, y, &state.playing); {
crate::device::transport::draw_rec(buf, x + 12, y, state.recording); use crate::device::transport::*;
crate::device::transport::draw_mon(buf, x + 19, y, state.monitoring); draw_play_stop(buf, x + 1, y, &state.playing);
crate::device::transport::draw_dub(buf, x + 26, y, state.overdub); draw_rec(buf, x + 12, y, state.recording);
crate::device::transport::draw_bpm(buf, x + 33, y, state.timebase.bpm()); draw_mon(buf, x + 19, y, state.monitoring);
crate::device::transport::draw_timer(buf, x + width - 1, y, &state.timebase, state.position); draw_dub(buf, x + 26, y, state.overdub);
draw_bpm(buf, x + 33, y, state.timebase.bpm());
draw_timer(buf, x + width - 1, y, &state.timebase, state.position);
}
let mut y = y + 1; let mut y = y + 1;
y = y + LauncherGrid::new( y = y + LauncherGrid::new(
state, buf, Rect { x, y, width, height: height / 3 }, state.view.is_tracks() state, buf, Rect { x, y, width, height: height / 3 }, state.view.is_tracks()
@ -223,38 +226,25 @@ fn draw_section_sequencer (state: &Launcher, buf: &mut Buffer, area: Rect) -> Us
} }
let track = track.unwrap().1; let track = track.unwrap().1;
let sequencer = track.sequencer.state(); let sequencer = track.sequencer.state();
crate::device::sequencer::horizontal::timer( {
buf, x+5, y, use crate::device::sequencer::horizontal::*;
sequencer.time_axis.0, timer(buf, x+5, y, sequencer.time_start, sequencer.time_start + area.width as usize, 0);
sequencer.time_axis.0 + area.width, keys(buf, Rect { x, y: y + 1, width, height }, sequencer.note_start)?;
0 if let Some(Some(phrase)) = state.phrase_id().map(|id|sequencer.phrases.get(id)) {
); let ppq = sequencer.timebase.ppq() as u32;
crate::device::sequencer::horizontal::keys( let zoom = sequencer.time_zoom as u32;
buf, Rect { x, y: y + 1, width, height }, let t0 = sequencer.time_start as u32;
sequencer.note_axis.1 let t1 = t0 + area.width as u32;
)?; let n0 = sequencer.note_start as u32;
if let Some(id) = state.phrase_id() { let n1 = n0 + area.height as u32;
if let Some(phrase) = sequencer.phrases.get(id) { lanes(buf, x, y + 1, &phrase, ppq, zoom, t0, t1, n0, n1);
crate::device::sequencer::horizontal::lanes(
buf, x, y + 1,
&phrase,
sequencer.timebase.ppq() as u32,
sequencer.time_zoom as u32,
sequencer.time_axis.0 as u32,
sequencer.time_axis.0 as u32 + area.width as u32,
sequencer.note_axis.0 as u32,
sequencer.note_axis.1 as u32,
);
} }
let cursor_style = match view {
LauncherView::Sequencer => Style::default().green().not_dim(),
_ => Style::default().green().dim(),
};
cursor(buf, x, y + 1, cursor_style, sequencer.time_cursor, sequencer.note_cursor);
} }
let cursor_style = match view {
LauncherView::Sequencer => Style::default().green().not_dim(),
_ => Style::default().green().dim(),
};
crate::device::sequencer::horizontal::cursor(buf, x, y + 1, cursor_style,
sequencer.time_cursor,
sequencer.note_cursor
);
Ok(area) Ok(area)
} }
fn draw_section_chains (state: &Launcher, buf: &mut Buffer, area: Rect) -> Usually<Rect> { fn draw_section_chains (state: &Launcher, buf: &mut Buffer, area: Rect) -> Usually<Rect> {

View file

@ -50,10 +50,10 @@ fn note_add (s: &mut Sequencer) -> Usually<bool> {
if s.sequence.is_none() { if s.sequence.is_none() {
return Ok(false) return Ok(false)
} }
let step = (s.time_axis.0 + s.time_cursor) as u32; let step = (s.time_start + s.time_cursor) as u32;
let start = (step as usize * s.timebase.ppq() / s.time_zoom) as u32; let start = (step as usize * s.timebase.ppq() / s.time_zoom) as u32;
let end = ((step + 1) as usize * s.timebase.ppq() / s.time_zoom) as u32; let end = ((step + 1) as usize * s.timebase.ppq() / s.time_zoom) as u32;
let key = u7::from_int_lossy((s.note_cursor + s.note_axis.0) as u8); let key = u7::from_int_lossy((s.note_cursor + s.note_start) as u8);
let note_on = MidiMessage::NoteOn { key, vel: 100.into() }; let note_on = MidiMessage::NoteOn { key, vel: 100.into() };
let note_off = MidiMessage::NoteOff { key, vel: 100.into() }; let note_off = MidiMessage::NoteOff { key, vel: 100.into() };
let sequence = &mut s.phrases[s.sequence.unwrap()].notes; let sequence = &mut s.phrases[s.sequence.unwrap()].notes;
@ -73,27 +73,23 @@ fn note_del (_: &mut Sequencer) -> Usually<bool> {
Ok(true) Ok(true)
} }
fn time_cursor_inc (s: &mut Sequencer) -> Usually<bool> { fn time_cursor_inc (s: &mut Sequencer) -> Usually<bool> {
let time = s.time_axis.1 - s.time_axis.0; s.time_cursor = s.time_cursor + 1;
s.time_cursor = ((time + s.time_cursor) + 1) % time;
Ok(true) Ok(true)
} }
fn time_cursor_dec (s: &mut Sequencer) -> Usually<bool> { fn time_cursor_dec (s: &mut Sequencer) -> Usually<bool> {
let time = s.time_axis.1 - s.time_axis.0; s.time_cursor = s.time_cursor.saturating_sub(1);
s.time_cursor = ((time + s.time_cursor) - 1) % time;
Ok(true) Ok(true)
} }
fn note_cursor_inc (s: &mut Sequencer) -> Usually<bool> { fn note_cursor_inc (s: &mut Sequencer) -> Usually<bool> {
let note = s.note_axis.1 - s.note_axis.0; s.note_cursor = s.note_cursor + 1;
s.note_cursor = ((note + s.note_cursor) + 1) % note;
Ok(true) Ok(true)
} }
fn note_cursor_dec (s: &mut Sequencer) -> Usually<bool> { fn note_cursor_dec (s: &mut Sequencer) -> Usually<bool> {
let note = s.note_axis.1 - s.note_axis.0; s.note_cursor = s.note_cursor.saturating_sub(1);
s.note_cursor = ((note + s.note_cursor) - 1) % note;
Ok(true) Ok(true)
} }
fn cursor_up (s: &mut Sequencer) -> Usually<bool> { fn cursor_up (s: &mut Sequencer) -> Usually<bool> {
match s.mode { match s.view {
SequencerView::Vertical => time_cursor_dec(s), SequencerView::Vertical => time_cursor_dec(s),
SequencerView::Horizontal => note_cursor_dec(s), SequencerView::Horizontal => note_cursor_dec(s),
_ => Ok(false) _ => Ok(false)
@ -101,7 +97,7 @@ fn cursor_up (s: &mut Sequencer) -> Usually<bool> {
Ok(true) Ok(true)
} }
fn cursor_down (s: &mut Sequencer) -> Usually<bool> { fn cursor_down (s: &mut Sequencer) -> Usually<bool> {
match s.mode { match s.view {
SequencerView::Vertical => time_cursor_inc(s), SequencerView::Vertical => time_cursor_inc(s),
SequencerView::Horizontal => note_cursor_inc(s), SequencerView::Horizontal => note_cursor_inc(s),
_ => Ok(false) _ => Ok(false)
@ -109,7 +105,7 @@ fn cursor_down (s: &mut Sequencer) -> Usually<bool> {
Ok(true) Ok(true)
} }
fn cursor_left (s: &mut Sequencer) -> Usually<bool> { fn cursor_left (s: &mut Sequencer) -> Usually<bool> {
match s.mode { match s.view {
SequencerView::Vertical => note_cursor_dec(s), SequencerView::Vertical => note_cursor_dec(s),
SequencerView::Horizontal => time_cursor_dec(s), SequencerView::Horizontal => time_cursor_dec(s),
_ => Ok(false) _ => Ok(false)
@ -117,7 +113,7 @@ fn cursor_left (s: &mut Sequencer) -> Usually<bool> {
Ok(true) Ok(true)
} }
fn cursor_right (s: &mut Sequencer) -> Usually<bool> { fn cursor_right (s: &mut Sequencer) -> Usually<bool> {
match s.mode { match s.view {
SequencerView::Vertical => note_cursor_inc(s), SequencerView::Vertical => note_cursor_inc(s),
SequencerView::Horizontal => time_cursor_inc(s), SequencerView::Horizontal => time_cursor_inc(s),
_ => Ok(false) _ => Ok(false)
@ -133,7 +129,7 @@ fn cursor_duration_dec (_: &mut Sequencer) -> Usually<bool> {
Ok(true) Ok(true)
} }
fn mode_next (s: &mut Sequencer) -> Usually<bool> { fn mode_next (s: &mut Sequencer) -> Usually<bool> {
s.mode = s.mode.next(); s.view = s.view.next();
Ok(true) Ok(true)
} }
impl SequencerView { impl SequencerView {

View file

@ -5,40 +5,44 @@ pub fn draw (
s: &Sequencer, s: &Sequencer,
buf: &mut Buffer, buf: &mut Buffer,
mut area: Rect, mut area: Rect,
beat: usize
) -> Usually<Rect> { ) -> Usually<Rect> {
area.x = area.x + 13; area.x = area.x + 13;
let Rect { x, y, width, .. } = area; let Rect { x, y, width, height } = area;
keys(buf, area, s.note_axis.1)?; keys(buf, area, s.note_start)?;
timer(buf, x+6, y-1, s.time_axis.0, s.time_axis.1, beat as u16); timer(buf, x+6, y-1, s.time_start, s.time_start + area.width as usize, 0);
let height = 32.max(s.note_axis.1 - s.note_axis.0) / 2;
if let Some(phrase) = s.phrase() { if let Some(phrase) = s.phrase() {
lanes(buf, x, y, lanes(buf, x, y,
phrase, phrase,
s.timebase.ppq() as u32, s.timebase.ppq() as u32,
s.time_zoom as u32, s.time_zoom as u32,
s.time_axis.0 as u32, s.time_start as u32,
s.time_axis.1 as u32, s.time_start as u32 + area.width as u32,
s.note_axis.0 as u32, s.note_start as u32,
s.note_axis.1 as u32, s.note_start as u32 + area.height as u32,
); );
} }
cursor(buf, x, y, Style::default().green().not_dim(), cursor(
buf,
x,
y,
Style::default().green().not_dim(),
s.time_cursor, s.time_cursor,
s.note_cursor s.note_cursor
); );
footer(s, buf, x, y, width, height); footer(s, buf, x, y, width, height);
Ok(Rect { Ok(Rect { x: x - 13, y, width, height })
x: x - 13,
y: y,
width: s.time_axis.1 - s.time_axis.0 + 19,
height: height + 3
})
} }
pub fn timer (buf: &mut Buffer, x: u16, y: u16, time0: u16, time1: u16, now: u16) { pub fn timer (
buf: &mut Buffer,
x: u16,
y: u16,
time0: usize,
time1: usize,
now: usize
) {
for step in time0..time1 { for step in time0..time1 {
buf.set_string(x + step, y, &"-", if step == now { buf.set_string(x + step as u16, y, &"-", if step == now {
Style::default().yellow().bold().not_dim() Style::default().yellow().bold().not_dim()
} else { } else {
Style::default() Style::default()
@ -46,18 +50,21 @@ pub fn timer (buf: &mut Buffer, x: u16, y: u16, time0: u16, time1: u16, now: u16
} }
} }
pub fn keys (buf: &mut Buffer, area: Rect, note1: u16) -> Usually<Rect> { pub fn keys (
buf: &mut Buffer, area: Rect, note_start: usize
) -> Usually<Rect> {
let bw = Style::default().dim(); let bw = Style::default().dim();
let Rect { x, y, width, height } = area; let Rect { x, y, width, height } = area;
let h = height.saturating_sub(2); let h = height.saturating_sub(2);
for i in 0..h { for i in 0..h {
let y = y + i; let y = y + i;
buf.set_string(x + 1, y, KEYS_VERTICAL[(i % 6) as usize], bw); let key = KEYS_VERTICAL[(i % 6) as usize];
buf.set_string(x + 2, y, "", bw); key.blit(buf, x + 1, y, Some(bw));
buf.set_string(x + 5, y, &"·".repeat(width.saturating_sub(6) as usize), bw.black()); "".blit(buf, x + 2, y, Some(bw));
"·".repeat(width.saturating_sub(6) as usize).blit(buf, x + 5, y, Some(bw.black()));
//buf.set_string(x + 3, y, &format!("{i}"), Style::default()); //buf.set_string(x + 3, y, &format!("{i}"), Style::default());
if i % 6 == 0 { if i % 6 == 0 {
let octave = format!("C{}", ((note1 - i) / 6) as i8 - 4); let octave = format!("C{}", ((note_start - i as usize) / 6) as i8 - 4);
buf.set_string(x + 3, y, &octave, Style::default()); buf.set_string(x + 3, y, &octave, Style::default());
} }
} }
@ -105,13 +112,11 @@ pub fn lanes (
} }
} }
pub fn cursor (buf: &mut Buffer, x: u16, y: u16, style: Style, time_cursor: u16, note_cursor: u16) { pub fn cursor (buf: &mut Buffer, x: u16, y: u16, style: Style, time: usize, note: usize) {
buf.set_string( let x = x + 5 + time as u16;
x + 5 + time_cursor, let y = y + note as u16 / 2;
y + note_cursor / 2, let c = if note % 2 == 0 { "" } else { "" };
if note_cursor % 2 == 0 { "" } else { "" }, c.blit(buf, x, y, Some(style));
style
);
} }
pub fn footer (s: &Sequencer, buf: &mut Buffer, mut x: u16, y: u16, width: u16, height: u16) { pub fn footer (s: &Sequencer, buf: &mut Buffer, mut x: u16, y: u16, width: u16, height: u16) {
@ -125,13 +130,13 @@ pub fn footer (s: &Sequencer, buf: &mut Buffer, mut x: u16, y: u16, width: u16,
["S", &format!("ync"), &format!("<4/4>")], ["S", &format!("ync"), &format!("<4/4>")],
["Q", &format!("uant"), &format!("<1/{}>", 4 * s.time_zoom)], ["Q", &format!("uant"), &format!("<1/{}>", 4 * s.time_zoom)],
["N", &format!("ote"), &format!("{} ({}-{})", ["N", &format!("ote"), &format!("{} ({}-{})",
s.note_axis.0 + s.note_cursor, s.note_start + s.note_cursor,
s.note_axis.0, s.note_start,
s.note_axis.1 - 1)], "X")],
["T", &format!("ime"), &format!("{} ({}-{})", ["T", &format!("ime"), &format!("{} ({}-{})",
s.time_axis.0 + s.time_cursor + 1, s.time_start + s.time_cursor + 1,
s.time_axis.0 + 1, s.time_start + 1,
s.time_axis.1)], "X")],
].iter().enumerate() { ].iter().enumerate() {
buf.set_string(x, y + height + 1, letter, Style::default().bold().yellow().dim()); buf.set_string(x, y + height + 1, letter, Style::default().bold().yellow().dim());
x = x + 1; x = x + 1;

View file

@ -34,17 +34,17 @@ pub struct Sequencer {
/// Don't delete when recording. /// Don't delete when recording.
pub overdub: bool, pub overdub: bool,
/// Display mode /// Display mode
pub mode: SequencerView, pub view: SequencerView,
/// Range of notes to display /// Range of notes to display
pub note_axis: (u16, u16), pub note_start: usize,
/// Position of cursor within note range /// Position of cursor within note range
pub note_cursor: u16, pub note_cursor: usize,
/// PPM per display unit /// PPM per display unit
pub time_zoom: usize, pub time_zoom: usize,
/// Range of time steps to display /// Range of time steps to display
pub time_axis: (u16, u16), pub time_start: usize,
/// Position of cursor within time range /// Position of cursor within time range
pub time_cursor: u16, pub time_cursor: usize,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -65,22 +65,22 @@ impl Sequencer {
timebase: timebase.clone(), timebase: timebase.clone(),
sequence: Some(0), sequence: Some(0),
phrases: phrases.unwrap_or(vec![ phrases: phrases.unwrap_or_else(||vec![
Phrase::new("Phrase0", 4*timebase.ppq() as u32, None) Phrase::new("Phrase0", 4*timebase.ppq() as u32, None)
]), ]),
notes_on: vec![false;128],
transport,
playing: TransportState::Starting, playing: TransportState::Starting,
monitoring: true, monitoring: true,
recording: true, recording: true,
overdub: true, overdub: true,
transport,
mode: SequencerView::Horizontal, view: SequencerView::Horizontal,
note_axis: (36, 68), notes_on: vec![false;128],
note_start: 36,
note_cursor: 0, note_cursor: 0,
time_zoom: 24, time_zoom: 24,
time_axis: (0, 64), time_start: 0,
time_cursor: 0, time_cursor: 0,
}).activate(client) }).activate(client)
} }
@ -89,76 +89,51 @@ impl Sequencer {
self.phrases.get(self.sequence?) self.phrases.get(self.sequence?)
} }
} }
impl PortList for Sequencer { impl PortList for Sequencer {
fn midi_ins (&self) -> Usually<Vec<String>> { fn midi_ins (&self) -> Usually<Vec<String>> { Ok(vec![self.midi_in.name()?]) }
Ok(vec![self.midi_in.name()?]) fn midi_outs (&self) -> Usually<Vec<String>> { Ok(vec![self.midi_out.name()?]) }
}
fn midi_outs (&self) -> Usually<Vec<String>> {
Ok(vec![self.midi_out.name()?])
}
} }
fn render (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually<Rect> { fn render (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
let Rect { x, y, width, .. } = area; let Rect { x, y, width, height } = area;
let (time0, time1) = s.time_axis;
let (note0, note1) = s.note_axis;
let pos = s.transport.query().unwrap().pos; let pos = s.transport.query().unwrap().pos;
let frame = pos.frame(); let frame = pos.frame();
let usecs = s.timebase.frame_to_usec(frame as usize); let usecs = s.timebase.frame_to_usec(frame as usize);
let ustep = s.timebase.usec_per_step(s.time_zoom as usize); let ustep = s.timebase.usec_per_step(s.time_zoom as usize);
let steps = usecs / ustep; let steps = usecs / ustep;
let header = draw_header(s, buf, area, steps)?; let header = draw_header(s, buf, area, steps)?;
let piano = match s.mode { let piano = match s.view {
SequencerView::Tiny => Rect { x, y, width, height: 0 }, SequencerView::Tiny => Rect { x, y, width, height: 0 },
SequencerView::Compact => Rect { x, y, width, height: 0 }, SequencerView::Compact => Rect { x, y, width, height: 0 },
SequencerView::Vertical => SequencerView::Vertical => self::vertical::draw(s, buf, Rect {
self::vertical::draw(s, buf, Rect { x, y: y + header.height, width, height,
x, }, steps)?,
y: y + header.height, SequencerView::Horizontal => self::horizontal::draw(s, buf, Rect {
width: 3 + note1 - note0, x, y: y + header.height, width, height,
height: 3 + time1 - time0, })?,
}, steps)?,
SequencerView::Horizontal =>
self::horizontal::draw(s, buf, Rect {
x,
y: y + header.height,
width: area.width.max(3 + time1 - time0),
height: 3 + note1 - note0,
}, steps)?,
}; };
Ok(draw_box(buf, Rect { Ok(draw_box(buf, Rect {
x, x, y,
y,
width: header.width.max(piano.width), width: header.width.max(piano.width),
height: header.height + piano.height height: header.height + piano.height
})) }))
} }
pub fn draw_header (s: &Sequencer, buf: &mut Buffer, area: Rect, _: usize) -> Usually<Rect> {
pub fn draw_header (s: &Sequencer, buf: &mut Buffer, area: Rect, beat: usize) -> Usually<Rect> { let Rect { x, y, width, .. } = area;
let Rect { x, y, .. } = area;
//let rep = beat / s.steps;
//let step = beat % s.steps;
//let reps = s.steps / s.time_zoom;
//let steps = s.steps % s.time_zoom;
//draw_timer(buf, x + width - 2, y + 1, &format!("{rep}.{step:02} / {reps}.{steps}"));
let style = Style::default().gray(); let style = Style::default().gray();
crate::device::transport::draw_play_stop(buf, x + 2, y + 1, &s.playing); crate::device::transport::draw_play_stop(buf, x + 2, y + 1, &s.playing);
let separator = format!("{}", "-".repeat((area.width - 2).into())); let separator = format!("{}", "-".repeat((width - 2).into()));
separator.blit(buf, x, y + 2, Some(style.dim())); separator.blit(buf, x, y + 2, Some(style.dim()));
crate::device::transport::draw_rec(buf, x + 13, y + 1, s.recording); crate::device::transport::draw_rec(buf, x + 13, y + 1, s.recording);
crate::device::transport::draw_dub(buf, x + 20, y + 1, s.overdub); crate::device::transport::draw_dub(buf, x + 20, y + 1, s.overdub);
crate::device::transport::draw_mon(buf, x + 27, y + 1, s.monitoring); crate::device::transport::draw_mon(buf, x + 27, y + 1, s.monitoring);
let _ = draw_clips(s, buf, area)?; let _ = draw_clips(s, buf, area)?;
Ok(Rect { x, y, width: area.width, height: 3 }) Ok(Rect { x, y, width, height: 3 })
} }
pub fn draw_timer ( pub fn draw_timer (buf: &mut Buffer, x: u16, y: u16, timer: &str) {
buf: &mut Buffer, x: u16, y: u16, timer: &str
) {
let style = Some(Style::default().gray().bold().not_dim()); let style = Some(Style::default().gray().bold().not_dim());
timer.blit(buf, x - timer.len() as u16, y, style); timer.blit(buf, x - timer.len() as u16, y, style);
} }
fn draw_clips (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually<Rect> { pub 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();
for (i, sequence) in s.phrases.iter().enumerate() { for (i, sequence) in s.phrases.iter().enumerate() {

View file

@ -8,13 +8,10 @@ pub fn draw (
beat: usize beat: usize
) -> Usually<Rect> { ) -> Usually<Rect> {
area.x = area.x + 13; area.x = area.x + 13;
let Rect { x, y, .. } = area;
keys(s, buf, area, beat); keys(s, buf, area, beat);
steps(s, buf, area, beat); steps(s, buf, area, beat);
let height = (s.time_axis.1-s.time_axis.0)/2; playhead(s, buf, area.x, area.y);
footer(s, buf, x, y, height); Ok(area)
playhead(s, buf, x, y);
Ok(Rect { x, y, width: area.width, height: height + 3 })
} }
pub fn steps (s: &Sequencer, buf: &mut Buffer, area: Rect, beat: usize) { pub fn steps (s: &Sequencer, buf: &mut Buffer, area: Rect, beat: usize) {
@ -26,16 +23,14 @@ pub fn steps (s: &Sequencer, buf: &mut Buffer, area: Rect, beat: usize) {
let bw = bg.dim(); let bw = bg.dim();
let wh = bg.white(); let wh = bg.white();
let Rect { x, y, .. } = area; let Rect { x, y, .. } = area;
let (time0, time1) = s.time_axis; for step in s.time_start..s.time_start+area.height as usize {
let (note0, note1) = s.note_axis; let y = y - (s.time_start + step / 2) as u16;
for step in time0..time1 {
let y = y - time0 + step / 2;
let step = step as usize; let step = step as usize;
//buf.set_string(x + 5, y, &" ".repeat(32.max(note1-note0)as usize), bg); //buf.set_string(x + 5, y, &" ".repeat(32.max(note1-s.note_start)as usize), bg);
if step % s.time_zoom == 0 { if step % s.time_zoom == 0 {
buf.set_string(x + 2, y, &format!("{:2} ", step + 1), Style::default()); buf.set_string(x + 2, y, &format!("{:2} ", step + 1), Style::default());
} }
for k in note0..note1 { for k in s.note_start..s.note_start+area.width as usize {
let key = ::midly::num::u7::from_int_lossy(k as u8); let key = ::midly::num::u7::from_int_lossy(k as u8);
if step % 2 == 0 { if step % 2 == 0 {
let (a, b, c) = ( let (a, b, c) = (
@ -52,12 +47,12 @@ pub fn steps (s: &Sequencer, buf: &mut Buffer, area: Rect, beat: usize) {
(false, true) => ("", wh), (false, true) => ("", wh),
(false, false) => ("·", bw), (false, false) => ("·", bw),
}; };
buf.set_string(x + 5 + k - note0, y, character, style); character.blit(buf, x + (5 + k - s.note_start) as u16, y, Some(style));
} }
} }
if beat == step as usize { if beat == step as usize {
buf.set_string(x + 4, y, if beat % 2 == 0 { "" } else { "" }, Style::default().yellow()); buf.set_string(x + 4, y, if beat % 2 == 0 { "" } else { "" }, Style::default().yellow());
for key in note0..note1 { for key in s.note_start..s.note_start+area.width as usize {
let _color = if s.notes_on[key as usize] { let _color = if s.notes_on[key as usize] {
Style::default().red() Style::default().red()
} else { } else {
@ -68,34 +63,18 @@ pub fn steps (s: &Sequencer, buf: &mut Buffer, area: Rect, beat: usize) {
} }
} }
pub fn footer (s: &Sequencer, buf: &mut Buffer, x: u16, y: u16, height: u16) {
buf.set_string(x + 2, y + height + 1, format!(
"Q 1/{} | N {} ({}-{}) | T {} ({}-{})",
4 * s.time_zoom,
s.note_axis.0 + s.note_cursor,
s.note_axis.0,
s.note_axis.1 - 1,
s.time_axis.0 + s.time_cursor + 1,
s.time_axis.0 + 1,
s.time_axis.1,
), Style::default().dim());
}
pub fn playhead (s: &Sequencer, buf: &mut Buffer, x: u16, y: u16) { pub fn playhead (s: &Sequencer, buf: &mut Buffer, x: u16, y: u16) {
buf.set_string( let x = x + 5 + s.note_cursor as u16;
x + 5 + s.note_cursor, let y = y + s.time_cursor as u16 / 2;
y + s.time_cursor / 2, let c = if s.time_cursor % 2 == 0 { "" } else { "" };
if s.time_cursor % 2 == 0 { "" } else { "" }, buf.set_string(x, y, c, Style::default());
Style::default()
);
} }
pub fn keys (s: &Sequencer, buf: &mut Buffer, area: Rect, beat: usize) { pub fn keys (s: &Sequencer, buf: &mut Buffer, area: Rect, beat: usize) {
let ppq = s.timebase.ppq() as u32; let ppq = s.timebase.ppq() as u32;
let Rect { x, y, .. } = area; let Rect { x, y, .. } = area;
let (note0, note1) = s.note_axis; for key in s.note_start..s.note_start+area.width as usize {
for key in note0..note1 { let x = x + (5 + key - s.note_start) as u16;
let x = x + 5 + key - note0;
if key % 12 == 0 { if key % 12 == 0 {
let octave = format!("C{}", (key / 12) as i8 - 4); let octave = format!("C{}", (key / 12) as i8 - 4);
buf.set_string(x, y, &octave, Style::default()); buf.set_string(x, y, &octave, Style::default());