mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
Compare commits
2 commits
04af945ea0
...
a8be2e9dad
| Author | SHA1 | Date | |
|---|---|---|---|
| a8be2e9dad | |||
| a6100ab1d6 |
9 changed files with 227 additions and 212 deletions
|
|
@ -53,12 +53,62 @@ impl Tek {
|
|||
matches!(self.pool.as_ref().map(|p|p.mode.as_ref()).flatten(), Some(PoolMode::Length(..)))
|
||||
}
|
||||
fn editor_pitch (&self) -> Option<u7> {
|
||||
(self.editor().map(|e|e.note_pos()).unwrap() as u8).into()
|
||||
Some((self.editor().map(|e|e.note_pos()).unwrap() as u8).into())
|
||||
}
|
||||
fn w_sidebar (&self) -> Option<u7> {
|
||||
self.w_sidebar()
|
||||
/// Width of display
|
||||
pub(crate) fn w (&self) -> u16 {
|
||||
self.size.w() as u16
|
||||
}
|
||||
fn scene_count (&self) -> Option<usize> {
|
||||
/// Width allocated for sidebar.
|
||||
pub(crate) fn w_sidebar (&self) -> u16 {
|
||||
self.w() / if self.is_editing() { 16 } else { 8 } as u16
|
||||
}
|
||||
/// Width taken by all tracks.
|
||||
pub(crate) fn w_tracks (&self) -> u16 {
|
||||
self.tracks_with_sizes().last().map(|(_, _, _, x)|x as u16).unwrap_or(0)
|
||||
}
|
||||
/// Width available to display tracks.
|
||||
pub(crate) fn w_tracks_area (&self) -> u16 {
|
||||
self.w().saturating_sub(2 * self.w_sidebar())
|
||||
}
|
||||
/// Height of display
|
||||
pub(crate) fn h (&self) -> u16 {
|
||||
self.size.h() as u16
|
||||
}
|
||||
/// Height available to display track headers.
|
||||
pub(crate) fn h_tracks_area (&self) -> u16 {
|
||||
5 // FIXME
|
||||
//self.h().saturating_sub(self.h_inputs() + self.h_outputs())
|
||||
}
|
||||
/// Height available to display tracks.
|
||||
pub(crate) fn h_scenes_area (&self) -> u16 {
|
||||
//15
|
||||
self.h().saturating_sub(
|
||||
self.h_inputs() +
|
||||
self.h_outputs() +
|
||||
self.h_devices() +
|
||||
13 // FIXME
|
||||
)
|
||||
}
|
||||
/// Height taken by all scenes.
|
||||
pub(crate) fn h_scenes (&self) -> u16 {
|
||||
self.scenes_with_sizes(self.is_editing(), Self::H_SCENE, Self::H_EDITOR).last()
|
||||
.map(|(_, _, _, y)|y as u16).unwrap_or(0)
|
||||
}
|
||||
/// Height taken by all inputs.
|
||||
pub(crate) fn h_inputs (&self) -> u16 {
|
||||
self.inputs_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
|
||||
}
|
||||
/// Height taken by all outputs.
|
||||
pub(crate) fn h_outputs (&self) -> u16 {
|
||||
self.outputs_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
|
||||
}
|
||||
/// Height taken by visible device slots.
|
||||
pub(crate) fn h_devices (&self) -> u16 {
|
||||
2
|
||||
//1 + self.devices_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
|
||||
}
|
||||
fn scene_count (&self) -> usize {
|
||||
self.scenes.len()
|
||||
}
|
||||
fn scene_selected (&self) -> Option<usize> {
|
||||
|
|
@ -70,7 +120,7 @@ impl Tek {
|
|||
fn scene_select_prev (&self) -> Selection {
|
||||
self.selected.scene_prev()
|
||||
}
|
||||
fn track_count (&self) -> Option<usize> {
|
||||
fn track_count (&self) -> usize {
|
||||
self.tracks.len()
|
||||
}
|
||||
fn track_selected (&self) -> Option<usize> {
|
||||
|
|
@ -139,64 +189,70 @@ impl MidiPool {
|
|||
#[tengri_proc::expose]
|
||||
impl MidiEditor {
|
||||
fn time_lock (&self) -> bool {
|
||||
self.time_lock().get()
|
||||
self.get_time_lock()
|
||||
}
|
||||
fn time_lock_toggle (&self) -> bool {
|
||||
!self.time_lock().get()
|
||||
fn time_lock_toggled (&self) -> bool {
|
||||
!self.get_time_lock()
|
||||
}
|
||||
|
||||
fn note_length (&self) -> usize {
|
||||
self.note_len()
|
||||
self.get_note_len()
|
||||
}
|
||||
|
||||
fn note_pos (&self) -> usize {
|
||||
self.note_pos()
|
||||
self.get_note_pos()
|
||||
}
|
||||
fn note_pos_next (&self) -> usize {
|
||||
self.note_pos() + 1
|
||||
self.get_note_pos() + 1
|
||||
}
|
||||
fn note_pos_next_octave (&self) -> usize {
|
||||
self.note_pos() + 12
|
||||
self.get_note_pos() + 12
|
||||
}
|
||||
fn note_pos_prev (&self) -> usize {
|
||||
self.note_pos().saturating_sub(1)
|
||||
self.get_note_pos().saturating_sub(1)
|
||||
}
|
||||
fn note_pos_prev_octave (&self) -> usize {
|
||||
self.note_pos().saturating_sub(12)
|
||||
self.get_note_pos().saturating_sub(12)
|
||||
}
|
||||
|
||||
fn note_len (&self) -> usize {
|
||||
self.note_len()
|
||||
self.get_note_len()
|
||||
}
|
||||
fn note_len_next (&self) -> usize {
|
||||
self.note_len() + 1
|
||||
self.get_note_len() + 1
|
||||
}
|
||||
fn note_len_prev (&self) -> usize {
|
||||
self.note_len().saturating_sub(1)
|
||||
self.get_note_len().saturating_sub(1)
|
||||
}
|
||||
|
||||
fn note_range (&self) -> usize {
|
||||
self.note_axis()
|
||||
self.get_note_axis()
|
||||
}
|
||||
fn note_range_next (&self) -> usize {
|
||||
self.note_axis() + 1
|
||||
self.get_note_axis() + 1
|
||||
}
|
||||
fn note_range_prev (&self) -> usize {
|
||||
self.note_axis().saturating_sub(1)
|
||||
self.get_note_axis().saturating_sub(1)
|
||||
}
|
||||
|
||||
fn time_pos (&self) -> usize {
|
||||
self.time_pos()
|
||||
self.get_time_pos()
|
||||
}
|
||||
fn time_pos_next (&self) -> usize {
|
||||
self.time_pos() + self.time_zoom().get()
|
||||
self.get_time_pos() + self.time_zoom()
|
||||
}
|
||||
fn time_pos_prev (&self) -> usize {
|
||||
self.time_pos().saturating_sub(self.time_zoom().get())
|
||||
self.get_time_pos().saturating_sub(self.time_zoom())
|
||||
}
|
||||
|
||||
fn time_zoom (&self) -> usize {
|
||||
self.time_zoom()
|
||||
self.get_time_zoom()
|
||||
}
|
||||
fn time_zoom_next (&self) -> usize {
|
||||
self.time_zoom() + 1
|
||||
self.get_time_zoom() + 1
|
||||
}
|
||||
fn time_zoom_prev (&self) -> usize {
|
||||
self.time_zoom().get().saturating_sub(1).max(1)
|
||||
self.get_time_zoom().saturating_sub(1).max(1)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -214,6 +270,18 @@ impl MidiEditor {
|
|||
|
||||
#[tengri_proc::command(Tek)]
|
||||
impl TekCommand {
|
||||
fn toggle_help (&self, state: &mut Tek, value: Option<bool>) -> Option<Self> {
|
||||
//(ToggleHelp [] cmd!(app.toggle_dialog(Some(Dialog::Help))))
|
||||
None
|
||||
}
|
||||
fn toggle_menu (&self, state: &mut Tek, value: Option<bool>) -> Option<Self> {
|
||||
//(ToggleMenu [] cmd!(app.toggle_dialog(Some(Dialog::Menu))))
|
||||
None
|
||||
}
|
||||
fn toggle_edit (&self, state: &mut Tek, value: Option<bool>) -> Option<Self> {
|
||||
//(Edit [value: Option<bool>] cmd!(app.toggle_editor(value)))
|
||||
None
|
||||
}
|
||||
//(Sampler [cmd: SamplerCommand] app.sampler_mut().map(|s|cmd.delegate(s, Self::Sampler)).transpose()?.flatten())
|
||||
//(Scene [cmd: SceneCommand] cmd.delegate(app, Self::Scene)?)
|
||||
//(Track [cmd: TrackCommand] cmd.delegate(app, Self::Track)?)
|
||||
|
|
@ -225,13 +293,10 @@ impl TekCommand {
|
|||
//(Message [cmd: MessageCommand] cmd.delegate(app, Self::Message)?)
|
||||
//(Editor [cmd: MidiEditCommand] delegate_to_editor(app, cmd)?)
|
||||
//(Pool [cmd: PoolCommand] delegate_to_pool(app, cmd)?)
|
||||
//(ToggleHelp [] cmd!(app.toggle_dialog(Some(Dialog::Help))))
|
||||
//(ToggleMenu [] cmd!(app.toggle_dialog(Some(Dialog::Menu))))
|
||||
//(Color [p: ItemTheme] app.set_color(Some(p)).map(Self::Color))
|
||||
//(Enqueue [c: MaybeClip] cmd_todo!("\n\rtodo: enqueue {c:?}"))
|
||||
//(History [d: isize] cmd_todo!("\n\rtodo: history {d:?}"))
|
||||
//(Zoom [z: Option<usize>] cmd_todo!("\n\rtodo: zoom {z:?}"))
|
||||
//(Edit [value: Option<bool>] cmd!(app.toggle_editor(value)))
|
||||
//(Launch [] cmd!(app.launch()))
|
||||
//(Select [s: Selection] cmd!(app.select(s)))
|
||||
//(StopAll [] cmd!(app.stop_all())))
|
||||
|
|
@ -268,17 +333,17 @@ impl TekCommand {
|
|||
|
||||
#[tengri_proc::command(Tek)]
|
||||
impl InputCommand {
|
||||
fn add (&self, state: &mut tek) -> option<self> {
|
||||
fn add (&self, state: &mut Tek) -> Option<Self> {
|
||||
state.midi_in_add()?;
|
||||
none
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[tengri_proc::command(Tek)]
|
||||
impl OutputCommand {
|
||||
fn add (&self, state: &mut tek) -> option<self> {
|
||||
fn add (&self, state: &mut Tek) -> Option<Self> {
|
||||
state.midi_out_add()?;
|
||||
none
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -93,12 +93,13 @@ impl MidiEditor {
|
|||
let (color, length) = if let Some(clip) = self.clip().as_ref().map(|p|p.read().unwrap()) {
|
||||
(clip.color, clip.length)
|
||||
} else { (ItemTheme::G[64], 0) };
|
||||
let time_pos = self.time_pos();
|
||||
let time_zoom = self.time_zoom().get();
|
||||
let time_lock = if self.time_lock().get() { "[lock]" } else { " " };
|
||||
let note_pos = format!("{:>3}", self.note_pos());
|
||||
let note_name = format!("{:4}", Note::pitch_to_name(self.note_pos()));
|
||||
let note_len = format!("{:>4}", self.note_len());
|
||||
let time_pos = self.get_time_pos();
|
||||
let time_zoom = self.get_time_zoom();
|
||||
let time_lock = if self.get_time_lock() { "[lock]" } else { " " };
|
||||
let note_pos = self.get_note_pos();
|
||||
let note_name = format!("{:4}", Note::pitch_to_name(note_pos));
|
||||
let note_pos = format!("{:>3}", note_pos);
|
||||
let note_len = format!("{:>4}", self.get_note_len());
|
||||
Bsp::e(
|
||||
FieldH(color, "Time", format!("{length}/{time_zoom}+{time_pos} {time_lock}")),
|
||||
FieldH(color, "Note", format!("{note_name} {note_pos} {note_len}")),
|
||||
|
|
@ -120,15 +121,12 @@ impl NoteRange for MidiEditor {
|
|||
}
|
||||
|
||||
impl NotePoint for MidiEditor {
|
||||
fn note_len (&self) -> usize { self.mode.note_len() }
|
||||
fn set_note_len (&self, x: usize) -> usize { self.mode.set_note_len(x) }
|
||||
fn note_pos (&self) -> usize { self.mode.note_pos() }
|
||||
fn set_note_pos (&self, x: usize) -> usize { self.mode.set_note_pos(x) }
|
||||
fn note_len (&self) -> &AtomicUsize { self.mode.note_len() }
|
||||
fn note_pos (&self) -> &AtomicUsize { self.mode.note_pos() }
|
||||
}
|
||||
|
||||
impl TimePoint for MidiEditor {
|
||||
fn time_pos (&self) -> usize { self.mode.time_pos() }
|
||||
fn set_time_pos (&self, x: usize) -> usize { self.mode.set_time_pos(x) }
|
||||
fn time_pos (&self) -> &AtomicUsize { self.mode.time_pos() }
|
||||
}
|
||||
|
||||
impl MidiViewer for MidiEditor {
|
||||
|
|
|
|||
|
|
@ -4,13 +4,9 @@ pub(crate) use ::tengri::tui::ratatui::prelude::Position;
|
|||
|
||||
#[tengri_proc::view(TuiOut)]
|
||||
impl Tek {
|
||||
|
||||
#[tengri::view(":nil")]
|
||||
fn view_nil (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
"nil"
|
||||
}
|
||||
|
||||
#[tengri::view(":status")]
|
||||
fn view_status (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
self.update_clock();
|
||||
let cache = self.view_cache.read().unwrap();
|
||||
|
|
@ -19,8 +15,6 @@ impl Tek {
|
|||
cache.sr.view.clone(), cache.buf.view.clone(), cache.lat.view.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
#[tengri::view(":transport")]
|
||||
fn view_transport (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
self.update_clock();
|
||||
let cache = self.view_cache.read().unwrap();
|
||||
|
|
@ -29,38 +23,24 @@ impl Tek {
|
|||
cache.bpm.view.clone(), cache.beat.view.clone(), cache.time.view.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
#[tengri::view(":arranger")]
|
||||
fn view_arranger (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
ArrangerView::new(self)
|
||||
}
|
||||
|
||||
#[tengri::view(":pool")]
|
||||
fn view_pool (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
self.pool().map(|p|Fixed::x(self.w_sidebar(), PoolView(self.is_editing(), p)))
|
||||
}
|
||||
|
||||
#[tengri::view(":editor")]
|
||||
fn view_editor (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
self.editor().map(|e|Bsp::n(Bsp::e(e.clip_status(), e.edit_status()), e))
|
||||
}
|
||||
|
||||
#[tengri::view(":samples-keys")]
|
||||
fn view_samples_keys (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
self.sampler().map(|s|s.view_list(false, self.editor().unwrap()))
|
||||
}
|
||||
|
||||
#[tengri::view(":samples-grid")]
|
||||
fn view_samples_grid (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
self.sampler().map(|s|s.view_grid())
|
||||
}
|
||||
|
||||
#[tengri::view(":sample-viewer")]
|
||||
fn view_sample_viewer (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
self.sampler().map(|s|s.view_sample(self.editor().unwrap().note_pos()))
|
||||
self.sampler().map(|s|s.view_sample(self.editor().unwrap().get_note_pos()))
|
||||
}
|
||||
|
||||
#[tengri::view(":dialog")]
|
||||
fn view_dialog (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
When::new(self.dialog.is_some(), Bsp::b(
|
||||
Fill::xy(Tui::fg_bg(Rgb(64,64,64), Rgb(32,32,32), "")),
|
||||
|
|
@ -135,69 +115,6 @@ impl Tek {
|
|||
/// Default editor height.
|
||||
pub(crate) const H_EDITOR: usize = 15;
|
||||
|
||||
/// Width of display
|
||||
pub(crate) fn w (&self) -> u16 {
|
||||
self.size.w() as u16
|
||||
}
|
||||
|
||||
pub(crate) fn w_sidebar (&self) -> u16 {
|
||||
self.w() / if self.is_editing() { 16 } else { 8 } as u16
|
||||
}
|
||||
|
||||
/// Width taken by all tracks.
|
||||
pub(crate) fn w_tracks (&self) -> u16 {
|
||||
self.tracks_with_sizes().last().map(|(_, _, _, x)|x as u16).unwrap_or(0)
|
||||
}
|
||||
|
||||
/// Width available to display tracks.
|
||||
pub(crate) fn w_tracks_area (&self) -> u16 {
|
||||
self.w().saturating_sub(2 * self.w_sidebar())
|
||||
}
|
||||
|
||||
/// Height of display
|
||||
pub(crate) fn h (&self) -> u16 {
|
||||
self.size.h() as u16
|
||||
}
|
||||
|
||||
/// Height available to display track headers.
|
||||
pub(crate) fn h_tracks_area (&self) -> u16 {
|
||||
5 // FIXME
|
||||
//self.h().saturating_sub(self.h_inputs() + self.h_outputs())
|
||||
}
|
||||
|
||||
/// Height available to display tracks.
|
||||
pub(crate) fn h_scenes_area (&self) -> u16 {
|
||||
//15
|
||||
self.h().saturating_sub(
|
||||
self.h_inputs() +
|
||||
self.h_outputs() +
|
||||
self.h_devices() +
|
||||
13 // FIXME
|
||||
)
|
||||
}
|
||||
|
||||
/// Height taken by all inputs.
|
||||
pub(crate) fn h_inputs (&self) -> u16 {
|
||||
self.inputs_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
|
||||
}
|
||||
|
||||
/// Height taken by all outputs.
|
||||
pub(crate) fn h_outputs (&self) -> u16 {
|
||||
self.outputs_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
|
||||
}
|
||||
|
||||
/// Height taken by visible device slots.
|
||||
pub(crate) fn h_devices (&self) -> u16 {
|
||||
2
|
||||
//1 + self.devices_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
|
||||
}
|
||||
|
||||
/// Height taken by all scenes.
|
||||
pub(crate) fn h_scenes (&self) -> u16 {
|
||||
self.scenes_with_sizes(self.is_editing(), Self::H_SCENE, Self::H_EDITOR).last()
|
||||
.map(|(_, _, _, y)|y as u16).unwrap_or(0)
|
||||
}
|
||||
|
||||
pub(crate) fn inputs_with_sizes (&self) -> impl PortsSizes<'_> {
|
||||
let mut y = 0;
|
||||
self.midi_ins.iter().enumerate().map(move|(i, input)|{
|
||||
|
|
@ -1138,9 +1055,9 @@ impl PianoHorizontal {
|
|||
}
|
||||
}
|
||||
fn notes (&self) -> impl Content<TuiOut> {
|
||||
let time_start = self.time_start().get();
|
||||
let note_lo = self.note_lo().get();
|
||||
let note_hi = self.note_hi();
|
||||
let time_start = self.get_time_start();
|
||||
let note_lo = self.get_note_lo();
|
||||
let note_hi = self.get_note_hi();
|
||||
let buffer = self.buffer.clone();
|
||||
ThunkRender::new(move|to: &mut TuiOut|{
|
||||
let source = buffer.read().unwrap();
|
||||
|
|
@ -1169,14 +1086,14 @@ impl PianoHorizontal {
|
|||
})
|
||||
}
|
||||
fn cursor (&self) -> impl Content<TuiOut> {
|
||||
let note_hi = self.get_note_hi();
|
||||
let note_lo = self.get_note_lo();
|
||||
let note_pos = self.get_note_pos();
|
||||
let note_len = self.get_note_len();
|
||||
let time_pos = self.get_time_pos();
|
||||
let time_start = self.get_time_start();
|
||||
let time_zoom = self.get_time_zoom();
|
||||
let style = Some(Style::default().fg(self.color.lightest.rgb));
|
||||
let note_hi = self.note_hi();
|
||||
let note_lo = self.note_lo().get();
|
||||
let note_pos = self.note_pos();
|
||||
let note_len = self.note_len();
|
||||
let time_pos = self.time_pos();
|
||||
let time_start = self.time_start().get();
|
||||
let time_zoom = self.time_zoom().get();
|
||||
ThunkRender::new(move|to: &mut TuiOut|{
|
||||
let [x0, y0, w, _] = to.area().xywh();
|
||||
for (_area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) {
|
||||
|
|
@ -1202,9 +1119,9 @@ impl PianoHorizontal {
|
|||
fn keys (&self) -> impl Content<TuiOut> {
|
||||
let state = self;
|
||||
let color = state.color;
|
||||
let note_lo = state.note_lo().get();
|
||||
let note_hi = state.note_hi();
|
||||
let note_pos = state.note_pos();
|
||||
let note_lo = state.get_note_lo();
|
||||
let note_hi = state.get_note_hi();
|
||||
let note_pos = state.get_note_pos();
|
||||
let key_style = Some(Style::default().fg(Rgb(192, 192, 192)).bg(Rgb(0, 0, 0)));
|
||||
let off_style = Some(Style::default().fg(Tui::g(255)));
|
||||
let on_style = Some(Style::default().fg(Rgb(255,0,0)).bg(color.base.rgb).bold());
|
||||
|
|
@ -1254,15 +1171,12 @@ impl NoteRange for PianoHorizontal {
|
|||
}
|
||||
|
||||
impl NotePoint for PianoHorizontal {
|
||||
fn note_len (&self) -> usize { self.point.note_len() }
|
||||
fn set_note_len (&self, x: usize) -> usize { self.point.set_note_len(x) }
|
||||
fn note_pos (&self) -> usize { self.point.note_pos() }
|
||||
fn set_note_pos (&self, x: usize) -> usize { self.point.set_note_pos(x) }
|
||||
fn note_len (&self) -> &AtomicUsize { self.point.note_len() }
|
||||
fn note_pos (&self) -> &AtomicUsize { self.point.note_pos() }
|
||||
}
|
||||
|
||||
impl TimePoint for PianoHorizontal {
|
||||
fn time_pos (&self) -> usize { self.point.time_pos() }
|
||||
fn set_time_pos (&self, x: usize) -> usize { self.point.set_time_pos(x) }
|
||||
fn time_pos (&self) -> &AtomicUsize { self.point.time_pos() }
|
||||
}
|
||||
|
||||
impl MidiViewer for PianoHorizontal {
|
||||
|
|
|
|||
|
|
@ -93,13 +93,19 @@ impl NoteRange for Sampler {
|
|||
}
|
||||
|
||||
impl NotePoint for Sampler {
|
||||
fn note_len (&self) -> usize {
|
||||
0 /*TODO?*/
|
||||
fn note_len (&self) -> &AtomicUsize {
|
||||
unreachable!();
|
||||
}
|
||||
fn get_note_len (&self) -> usize {
|
||||
0
|
||||
}
|
||||
fn set_note_len (&self, x: usize) -> usize {
|
||||
0 /*TODO?*/
|
||||
}
|
||||
fn note_pos (&self) -> usize {
|
||||
fn note_pos (&self) -> &AtomicUsize {
|
||||
&self.note_pt
|
||||
}
|
||||
fn get_note_pos (&self) -> usize {
|
||||
self.note_pt.load(Relaxed)
|
||||
}
|
||||
fn set_note_pos (&self, x: usize) -> usize {
|
||||
|
|
|
|||
|
|
@ -56,9 +56,9 @@ impl Sampler {
|
|||
pub fn view_list <'a, T: NotePoint + NoteRange> (
|
||||
&'a self, compact: bool, editor: &T
|
||||
) -> impl Content<TuiOut> + 'a {
|
||||
let note_lo = editor.note_lo().load(Relaxed);
|
||||
let note_pt = editor.note_pos();
|
||||
let note_hi = editor.note_hi();
|
||||
let note_lo = editor.get_note_lo();
|
||||
let note_pt = editor.get_note_pos();
|
||||
let note_hi = editor.get_note_hi();
|
||||
Fixed::x(12, Map::south(
|
||||
1,
|
||||
move||(note_lo..=note_hi).rev(),
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ pub trait MidiViewer: HasSize<TuiOut> + MidiRange + MidiPoint + Debug + Send + S
|
|||
}
|
||||
/// Make sure cursor is within note range
|
||||
fn autoscroll (&self) {
|
||||
let note_pos = self.note_pos().min(127);
|
||||
let note_lo = self.note_lo().get();
|
||||
let note_hi = self.note_hi();
|
||||
let note_pos = self.get_note_pos().min(127);
|
||||
let note_lo = self.get_note_lo();
|
||||
let note_hi = self.get_note_hi();
|
||||
if note_pos < note_lo {
|
||||
self.note_lo().set(note_pos);
|
||||
} else if note_pos > note_hi {
|
||||
|
|
@ -23,9 +23,9 @@ pub trait MidiViewer: HasSize<TuiOut> + MidiRange + MidiPoint + Debug + Send + S
|
|||
/// Make sure time range is within display
|
||||
fn autozoom (&self) {
|
||||
if self.time_lock().get() {
|
||||
let time_len = self.time_len().get();
|
||||
let time_axis = self.time_axis().get();
|
||||
let time_zoom = self.time_zoom().get();
|
||||
let time_len = self.get_time_len();
|
||||
let time_axis = self.get_time_axis();
|
||||
let time_zoom = self.get_time_zoom();
|
||||
loop {
|
||||
let time_zoom = self.time_zoom().get();
|
||||
let time_area = time_axis * time_zoom;
|
||||
|
|
|
|||
|
|
@ -20,53 +20,60 @@ impl Default for MidiPointModel {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait NotePoint {
|
||||
/// Get the current length of the note cursor.
|
||||
fn note_len (&self) -> usize;
|
||||
/// Set the length of the note cursor, returning the previous value.
|
||||
fn set_note_len (&self, x: usize) -> usize;
|
||||
/// Get the current pitch of the note cursor.
|
||||
fn note_pos (&self) -> usize;
|
||||
/// Set the current pitch fo the note cursor, returning the previous value.
|
||||
fn set_note_pos (&self, x: usize) -> usize;
|
||||
}
|
||||
|
||||
pub trait TimePoint {
|
||||
/// Get the current time position of the note cursor.
|
||||
fn time_pos (&self) -> usize;
|
||||
/// Set the current time position of the note cursor, returning the previous value.
|
||||
fn set_time_pos (&self, x: usize) -> usize;
|
||||
}
|
||||
|
||||
pub trait MidiPoint: NotePoint + TimePoint {
|
||||
/// Get the current end of the note cursor.
|
||||
fn note_end (&self) -> usize {
|
||||
self.time_pos() + self.note_len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NotePoint + TimePoint> MidiPoint for T {}
|
||||
|
||||
impl NotePoint for MidiPointModel {
|
||||
fn note_len (&self) -> usize {
|
||||
self.note_len.load(Relaxed)
|
||||
fn note_len (&self) -> &AtomicUsize {
|
||||
&self.note_len
|
||||
}
|
||||
fn set_note_len (&self, x: usize) -> usize {
|
||||
self.note_len.swap(x, Relaxed)
|
||||
}
|
||||
fn note_pos (&self) -> usize {
|
||||
self.note_pos.load(Relaxed).min(127)
|
||||
}
|
||||
fn set_note_pos (&self, x: usize) -> usize {
|
||||
self.note_pos.swap(x.min(127), Relaxed)
|
||||
fn note_pos (&self) -> &AtomicUsize {
|
||||
&self.note_pos
|
||||
}
|
||||
}
|
||||
|
||||
impl TimePoint for MidiPointModel {
|
||||
fn time_pos (&self) -> usize {
|
||||
self.time_pos.load(Relaxed)
|
||||
}
|
||||
fn set_time_pos (&self, x: usize) -> usize {
|
||||
self.time_pos.swap(x, Relaxed)
|
||||
fn time_pos (&self) -> &AtomicUsize {
|
||||
self.time_pos.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait NotePoint {
|
||||
fn note_len (&self) -> &AtomicUsize;
|
||||
/// Get the current length of the note cursor.
|
||||
fn get_note_len (&self) -> usize {
|
||||
self.note_len().load(Relaxed)
|
||||
}
|
||||
/// Set the length of the note cursor, returning the previous value.
|
||||
fn set_note_len (&self, x: usize) -> usize {
|
||||
self.note_len().swap(x, Relaxed)
|
||||
}
|
||||
|
||||
fn note_pos (&self) -> &AtomicUsize;
|
||||
/// Get the current pitch of the note cursor.
|
||||
fn get_note_pos (&self) -> usize {
|
||||
self.note_pos().load(Relaxed).min(127)
|
||||
}
|
||||
/// Set the current pitch fo the note cursor, returning the previous value.
|
||||
fn set_note_pos (&self, x: usize) -> usize {
|
||||
self.note_pos().swap(x.min(127), Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TimePoint {
|
||||
fn time_pos (&self) -> &AtomicUsize;
|
||||
/// Get the current time position of the note cursor.
|
||||
fn get_time_pos (&self) -> usize {
|
||||
self.time_pos().load(Relaxed)
|
||||
}
|
||||
/// Set the current time position of the note cursor, returning the previous value.
|
||||
fn set_time_pos (&self, x: usize) -> usize {
|
||||
self.time_pos().swap(x, Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait MidiPoint: NotePoint + TimePoint {
|
||||
/// Get the current end of the note cursor.
|
||||
fn get_note_end (&self) -> usize {
|
||||
self.get_time_pos() + self.get_note_len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NotePoint + TimePoint> MidiPoint for T {}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::*;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MidiRangeModel {
|
||||
|
|
@ -29,19 +30,43 @@ from!(|data:(usize, bool)|MidiRangeModel = Self {
|
|||
|
||||
pub trait TimeRange {
|
||||
fn time_len (&self) -> &AtomicUsize;
|
||||
fn get_time_len (&self) -> usize {
|
||||
self.time_len().load(Ordering::Relaxed)
|
||||
}
|
||||
fn time_zoom (&self) -> &AtomicUsize;
|
||||
fn get_time_zoom (&self) -> usize {
|
||||
self.time_zoom().load(Ordering::Relaxed)
|
||||
}
|
||||
fn time_lock (&self) -> &AtomicBool;
|
||||
fn get_time_lock (&self) -> bool {
|
||||
self.time_lock().load(Ordering::Relaxed)
|
||||
}
|
||||
fn time_start (&self) -> &AtomicUsize;
|
||||
fn get_time_start (&self) -> usize {
|
||||
self.time_start().load(Ordering::Relaxed)
|
||||
}
|
||||
fn time_axis (&self) -> &AtomicUsize;
|
||||
fn time_end (&self) -> usize {
|
||||
fn get_time_axis (&self) -> usize {
|
||||
self.time_axis().load(Ordering::Relaxed)
|
||||
}
|
||||
fn get_time_end (&self) -> usize {
|
||||
self.time_start().get() + self.time_axis().get() * self.time_zoom().get()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait NoteRange {
|
||||
fn note_lo (&self) -> &AtomicUsize;
|
||||
fn get_note_lo (&self) -> usize {
|
||||
self.note_lo().load(Ordering::Relaxed)
|
||||
}
|
||||
fn set_note_lo (&self, x: usize) -> usize {
|
||||
self.note_lo().swap(x, Ordering::Relaxed)
|
||||
}
|
||||
fn note_axis (&self) -> &AtomicUsize;
|
||||
fn note_hi (&self) -> usize {
|
||||
fn get_note_axis (&self) -> usize {
|
||||
self.note_axis().load(Ordering::Relaxed)
|
||||
}
|
||||
fn get_note_hi (&self) -> usize {
|
||||
(self.note_lo().get() + self.note_axis().get().saturating_sub(1)).min(127)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
deps/tengri
vendored
2
deps/tengri
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit 7df7cb839c14c0e010ce36519c75ffacc0e76c18
|
||||
Subproject commit fa10f7d4d36924beae83d2136d180c2006508ae9
|
||||
Loading…
Add table
Add a link
Reference in a new issue