mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
instant crash
This commit is contained in:
parent
a6643ab990
commit
2401dc8fcd
5 changed files with 105 additions and 122 deletions
|
|
@ -12,42 +12,35 @@ pub trait HasEditor {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Contains state for viewing and editing a phrase
|
||||
pub struct MidiEditor {
|
||||
pub mode: PianoHorizontal,
|
||||
pub size: Measure<TuiOut>
|
||||
}
|
||||
|
||||
from!(|phrase: &Arc<RwLock<MidiClip>>|MidiEditor = {
|
||||
let mut model = Self::from(Some(phrase.clone()));
|
||||
let model = Self::from(Some(phrase.clone()));
|
||||
model.redraw();
|
||||
model
|
||||
});
|
||||
|
||||
from!(|phrase: Option<Arc<RwLock<MidiClip>>>|MidiEditor = {
|
||||
let mut model = Self::default();
|
||||
*model.phrase_mut() = phrase;
|
||||
model.redraw();
|
||||
model
|
||||
});
|
||||
|
||||
impl Default for MidiEditor {
|
||||
fn default () -> Self {
|
||||
let mut mode = PianoHorizontal::new(None);
|
||||
let mode = PianoHorizontal::new(None);
|
||||
mode.redraw();
|
||||
Self { mode, size: Measure::new() }
|
||||
}
|
||||
}
|
||||
|
||||
has_size!(<TuiOut>|self: MidiEditor|&self.size);
|
||||
|
||||
render!(TuiOut: (self: MidiEditor) => {
|
||||
self.autoscroll();
|
||||
self.autozoom();
|
||||
Fill::xy(Bsp::b(&self.size, &self.mode))
|
||||
});
|
||||
|
||||
impl TimeRange for MidiEditor {
|
||||
fn time_len (&self) -> &AtomicUsize { self.mode.time_len() }
|
||||
fn time_zoom (&self) -> &AtomicUsize { self.mode.time_zoom() }
|
||||
|
|
@ -55,42 +48,27 @@ impl TimeRange for MidiEditor {
|
|||
fn time_start (&self) -> &AtomicUsize { self.mode.time_start() }
|
||||
fn time_axis (&self) -> &AtomicUsize { self.mode.time_axis() }
|
||||
}
|
||||
|
||||
impl NoteRange for MidiEditor {
|
||||
fn note_lo (&self) -> &AtomicUsize { self.mode.note_lo() }
|
||||
fn note_axis (&self) -> &AtomicUsize { self.mode.note_axis() }
|
||||
}
|
||||
|
||||
impl NotePoint for MidiEditor {
|
||||
fn note_len (&self) -> usize { self.mode.note_len() }
|
||||
fn set_note_len (&self, x: usize) { self.mode.set_note_len(x) }
|
||||
fn note_point (&self) -> usize { self.mode.note_point() }
|
||||
fn note_len (&self) -> usize { self.mode.note_len() }
|
||||
fn set_note_len (&self, x: usize) { self.mode.set_note_len(x) }
|
||||
fn note_point (&self) -> usize { self.mode.note_point() }
|
||||
fn set_note_point (&self, x: usize) { self.mode.set_note_point(x) }
|
||||
}
|
||||
|
||||
impl TimePoint for MidiEditor {
|
||||
fn time_point (&self) -> usize { self.mode.time_point() }
|
||||
fn time_point (&self) -> usize { self.mode.time_point() }
|
||||
fn set_time_point (&self, x: usize) { self.mode.set_time_point(x) }
|
||||
}
|
||||
|
||||
impl MidiViewer for MidiEditor {
|
||||
fn buffer_size (&self, phrase: &MidiClip) -> (usize, usize) {
|
||||
self.mode.buffer_size(phrase)
|
||||
}
|
||||
fn redraw (&self) {
|
||||
self.mode.redraw()
|
||||
}
|
||||
fn phrase (&self) -> &Option<Arc<RwLock<MidiClip>>> {
|
||||
self.mode.phrase()
|
||||
}
|
||||
fn phrase_mut (&mut self) -> &mut Option<Arc<RwLock<MidiClip>>> {
|
||||
self.mode.phrase_mut()
|
||||
}
|
||||
fn set_phrase (&mut self, phrase: Option<&Arc<RwLock<MidiClip>>>) {
|
||||
self.mode.set_phrase(phrase)
|
||||
}
|
||||
fn buffer_size (&self, phrase: &MidiClip) -> (usize, usize) { self.mode.buffer_size(phrase) }
|
||||
fn redraw (&self) { self.mode.redraw() }
|
||||
fn phrase (&self) -> &Option<Arc<RwLock<MidiClip>>> { self.mode.phrase() }
|
||||
fn phrase_mut (&mut self) -> &mut Option<Arc<RwLock<MidiClip>>> { self.mode.phrase_mut() }
|
||||
fn set_phrase (&mut self, p: Option<&Arc<RwLock<MidiClip>>>) { self.mode.set_phrase(p) }
|
||||
}
|
||||
|
||||
impl MidiEditor {
|
||||
/// Put note at current position
|
||||
pub fn put_note (&mut self, advance: bool) {
|
||||
|
|
@ -136,27 +114,23 @@ impl MidiEditor {
|
|||
}
|
||||
|
||||
pub fn edit_status (&self) -> impl Content<TuiOut> + '_ {
|
||||
let (color, name, length, looped) = if let Some(phrase) = self.phrase().as_ref().map(|p|p.read().unwrap()) {
|
||||
(phrase.color, phrase.name.clone(), phrase.length, phrase.looped)
|
||||
let (color, length) = if let Some(phrase) = self.phrase().as_ref().map(|p|p.read().unwrap()) {
|
||||
(phrase.color, phrase.length)
|
||||
} else {
|
||||
(ItemPalette::from(TuiTheme::g(64)), String::new().into(), 0, false)
|
||||
(ItemPalette::from(TuiTheme::g(64)), 0)
|
||||
};
|
||||
let time_point = self.time_point();
|
||||
let time_start = self.time_start();
|
||||
let time_end = self.time_end();
|
||||
let time_axis = self.time_axis().get();
|
||||
let time_zoom = self.time_zoom().get();
|
||||
let time_lock = if self.time_lock().get() { "[lock]" } else { " " };
|
||||
let time_field = FieldV(color, "Time", format!("{length}/{time_zoom}+{time_point} {time_lock}"));
|
||||
|
||||
let note_point = format!("{:>3}", self.note_point());
|
||||
let note_name = format!("{:4}", Note::pitch_to_name(self.note_point()));
|
||||
let note_len = format!("{:>4}", self.note_len());;;;
|
||||
let note_field = FieldV(color, "Note", format!("{note_name} {note_point} {note_len}"));
|
||||
Bsp::e(time_field, note_field,)
|
||||
let note_len = format!("{:>4}", self.note_len());
|
||||
Bsp::e(
|
||||
FieldV(color, "Time", format!("{length}/{time_zoom}+{time_point} {time_lock}")),
|
||||
FieldV(color, "Note", format!("{note_name} {note_point} {note_len}")),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for MidiEditor {
|
||||
fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
|
||||
f.debug_struct("MidiEditor")
|
||||
|
|
@ -164,7 +138,6 @@ impl std::fmt::Debug for MidiEditor {
|
|||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum MidiEditCommand {
|
||||
// TODO: 1-9 seek markers that by default start every 8th of the phrase
|
||||
|
|
@ -179,9 +152,7 @@ pub enum MidiEditCommand {
|
|||
SetTimeLock(bool),
|
||||
Show(Option<Arc<RwLock<MidiClip>>>),
|
||||
}
|
||||
|
||||
handle!(TuiIn: |self: MidiEditor, input|MidiEditCommand::execute_with_state(self, input.event()));
|
||||
|
||||
keymap!(KEYS_MIDI_EDITOR = |s: MidiEditor, _input: Event| MidiEditCommand {
|
||||
key(Up) => SetNoteCursor(s.note_point() + 1),
|
||||
key(Char('w')) => SetNoteCursor(s.note_point() + 1),
|
||||
|
|
@ -217,13 +188,11 @@ keymap!(KEYS_MIDI_EDITOR = |s: MidiEditor, _input: Event| MidiEditCommand {
|
|||
//// TODO: kpat!(Char('/')) => // toggle 3plet
|
||||
//// TODO: kpat!(Char('?')) => // toggle dotted
|
||||
});
|
||||
|
||||
impl MidiEditor {
|
||||
fn phrase_length (&self) -> usize {
|
||||
self.phrase().as_ref().map(|p|p.read().unwrap().length).unwrap_or(1)
|
||||
}
|
||||
}
|
||||
|
||||
impl Command<MidiEditor> for MidiEditCommand {
|
||||
fn execute (self, state: &mut MidiEditor) -> Perhaps<Self> {
|
||||
use MidiEditCommand::*;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
use crate::*;
|
||||
use super::*;
|
||||
|
||||
pub(crate) fn note_y_iter (note_lo: usize, note_hi: usize, y0: u16) -> impl Iterator<Item=(usize, u16, usize)> {
|
||||
(note_lo..=note_hi).rev().enumerate().map(move|(y, n)|(y, y0 + y as u16, n))
|
||||
}
|
||||
|
||||
render!(TuiOut: (self: PianoHorizontal) => Bsp::s(
|
||||
render!(TuiOut: (self: PianoHorizontal) => Bsp::s( // the freeze is in the piano
|
||||
Fixed::y(1, Bsp::e(
|
||||
Fixed::x(self.keys_width, ""),
|
||||
Fill::x(PianoHorizontalTimeline(self)),
|
||||
|
|
@ -18,7 +16,6 @@ render!(TuiOut: (self: PianoHorizontal) => Bsp::s(
|
|||
))),
|
||||
)),
|
||||
));
|
||||
|
||||
impl PianoHorizontal {
|
||||
/// Draw the piano roll foreground using full blocks on note on and half blocks on legato: █▄ █▄ █▄
|
||||
fn draw_bg (buf: &mut BigBuffer, phrase: &MidiClip, zoom: usize, note_len: usize) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue