mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
wip: decruft
This commit is contained in:
parent
78e5469b32
commit
55a8b67bfb
7 changed files with 125 additions and 180 deletions
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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> {
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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() {
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue