mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-07-17 15:56:57 +02:00
wip: simplify and document
This commit is contained in:
parent
701a651fbd
commit
b9e7b9732e
12 changed files with 116 additions and 72 deletions
|
|
@ -35,7 +35,7 @@ pub mod size; pub use self::size::*;
|
||||||
/// Must not be dropped for the duration of the process
|
/// Must not be dropped for the duration of the process
|
||||||
pub jack: Jack<'static>,
|
pub jack: Jack<'static>,
|
||||||
/// Display size
|
/// Display size
|
||||||
pub size: Size,
|
pub size: Sizer,
|
||||||
/// Performance counter
|
/// Performance counter
|
||||||
pub perf: PerfModel,
|
pub perf: PerfModel,
|
||||||
/// Available view modes and input bindings
|
/// Available view modes and input bindings
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,25 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
tui_view!(|self: App| {
|
|
||||||
""
|
|
||||||
});
|
|
||||||
|
|
||||||
/// The [Draw] implementation for [App] handles the loaded view,
|
/// The [Draw] implementation for [App] handles the loaded view,
|
||||||
/// which is defined in terms of [dizzle] DSL.
|
/// which is defined in terms of [dizzle] DSL.
|
||||||
///
|
///
|
||||||
/// If there is an error, the error is displayed. FIXME: overlay it
|
/// If there is an error, the error is displayed. FIXME: overlay it
|
||||||
/// Then, every top-level form of the DSL description is rendered.
|
/// Then, every top-level form of the DSL description is rendered.
|
||||||
impl Draw<Tui> for App {
|
impl View<Tui> for App {
|
||||||
fn draw (self, to: &mut Tui) -> Usually<XYWH<u16>> {
|
fn view (&self) -> impl Draw<Tui> {
|
||||||
let xywh = to.area().into();
|
thunk(|to: &mut Tui|{
|
||||||
if let Some(e) = self.error.read().unwrap().as_ref() {
|
let xywh = to.area().into();
|
||||||
to.show(xywh, e.as_ref())?;
|
if let Some(e) = self.error.read().unwrap().as_ref() {
|
||||||
}
|
to.show(Layout::XYWH(xywh, e.as_ref()))?;
|
||||||
for (index, dsl) in self.mode.view.iter().enumerate() {
|
|
||||||
if let Err(e) = self.interpret(to, dsl) {
|
|
||||||
*self.error.write().unwrap() = Some(format!("view #{index}: {e}").into());
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
for (index, dsl) in self.mode.view.iter().enumerate() {
|
||||||
Ok(xywh)
|
if let Err(e) = self.interpret(to, dsl) {
|
||||||
|
*self.error.write().unwrap() = Some(format!("view #{index}: {e}").into());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(xywh)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,7 +125,7 @@ pub fn draw_dialog (
|
||||||
if *selected == index { Rgb(240,200,180) } else { Rgb(200, 200, 200) },
|
if *selected == index { Rgb(240,200,180) } else { Rgb(200, 200, 200) },
|
||||||
if *selected == index { Rgb(80, 80, 50) } else { Rgb(30, 30, 30) },
|
if *selected == index { Rgb(80, 80, 50) } else { Rgb(30, 30, 30) },
|
||||||
h_exact(2, origin_n(w_full(item)))
|
h_exact(2, origin_n(w_full(item)))
|
||||||
)).draw(to);
|
)).draw(to)?;
|
||||||
}
|
}
|
||||||
Ok(to.area().into())
|
Ok(to.area().into())
|
||||||
})))
|
})))
|
||||||
|
|
@ -364,7 +362,7 @@ pub fn view_scenes_clips <'a, S: ScenesSizes<'a>> (
|
||||||
tracks: impl TracksSizes<'a>,
|
tracks: impl TracksSizes<'a>,
|
||||||
select: &Selection,
|
select: &Selection,
|
||||||
editor: Option<&MidiEditor>,
|
editor: Option<&MidiEditor>,
|
||||||
size: &Size,
|
size: &Sizer,
|
||||||
editing: bool,
|
editing: bool,
|
||||||
) -> impl Draw<Tui> {
|
) -> impl Draw<Tui> {
|
||||||
let status = wh_full(origin_se(fg(Green, format!("{}x{}", size.w(), size.h()))));
|
let status = wh_full(origin_se(fg(Green, format!("{}x{}", size.w(), size.h()))));
|
||||||
|
|
@ -465,7 +463,7 @@ pub fn view_track_names (
|
||||||
}, south(w_full(origin_nw(east(
|
}, south(w_full(origin_nw(east(
|
||||||
format!("·t{index:02} "),
|
format!("·t{index:02} "),
|
||||||
fg(Rgb(255, 255, 255), bold(true, &track.name))
|
fg(Rgb(255, 255, 255), bold(true, &track.name))
|
||||||
))), ""))) ).draw(to);
|
))), ""))) ).draw(to)?;
|
||||||
}
|
}
|
||||||
Ok(XYWH(0, 0, 0, 0))
|
Ok(XYWH(0, 0, 0, 0))
|
||||||
}))))
|
}))))
|
||||||
|
|
@ -490,7 +488,7 @@ pub fn view_track_outputs (
|
||||||
h_exact(1, bg(track.color.dark.term, w_full(origin_w(
|
h_exact(1, bg(track.color.dark.term, w_full(origin_w(
|
||||||
format!("·o{index:02} {}", port.port_name()))))));
|
format!("·o{index:02} {}", port.port_name()))))));
|
||||||
w_exact(track_width(index, track),
|
w_exact(track_width(index, track),
|
||||||
origin_nw(h_full(iter_south(iter, draw)))).draw(to);
|
origin_nw(h_full(iter_south(iter, draw)))).draw(to)?;
|
||||||
}
|
}
|
||||||
Ok(XYWH(0, 0, 0, 0))
|
Ok(XYWH(0, 0, 0, 0))
|
||||||
}))))
|
}))))
|
||||||
|
|
@ -513,7 +511,7 @@ pub fn view_track_inputs (
|
||||||
iter_south(||track.sequencer.midi_ins.iter(),
|
iter_south(||track.sequencer.midi_ins.iter(),
|
||||||
|port, _|fg_bg(Rgb(255, 255, 255), track.color.dark.term,
|
|port, _|fg_bg(Rgb(255, 255, 255), track.color.dark.term,
|
||||||
w_full(origin_w(format!("·i{index:02} {}", port.port_name()))))))))
|
w_full(origin_w(format!("·i{index:02} {}", port.port_name()))))))))
|
||||||
.draw(to);
|
.draw(to)?;
|
||||||
}
|
}
|
||||||
Ok(XYWH(0, 0, 0, 0))
|
Ok(XYWH(0, 0, 0, 0))
|
||||||
}))))
|
}))))
|
||||||
|
|
@ -527,7 +525,7 @@ pub fn view_scenes_names (
|
||||||
) -> impl Draw<Tui> {
|
) -> impl Draw<Tui> {
|
||||||
w_exact(20, thunk(move |to: &mut Tui|{
|
w_exact(20, thunk(move |to: &mut Tui|{
|
||||||
for (index, scene, ..) in scenes {
|
for (index, scene, ..) in scenes {
|
||||||
view_scene_name(select, editor, index, scene, editing).draw(to);
|
view_scene_name(select, editor, index, scene, editing).draw(to)?;
|
||||||
}
|
}
|
||||||
Ok(XYWH(1, 1, 1, 1))
|
Ok(XYWH(1, 1, 1, 1))
|
||||||
}))
|
}))
|
||||||
|
|
@ -639,10 +637,10 @@ pub fn view_outputs (
|
||||||
origin_w(east(" ● ", fg(Rgb(255,255,255), bold(true, port.port_name())))),
|
origin_w(east(" ● ", fg(Rgb(255,255,255), bold(true, port.port_name())))),
|
||||||
w_full(origin_e(format!("{}/{} ",
|
w_full(origin_e(format!("{}/{} ",
|
||||||
port.port().get_connections().len(),
|
port.port().get_connections().len(),
|
||||||
port.connections.len())))))).draw(to);
|
port.connections.len())))))).draw(to)?;
|
||||||
for (index, conn) in port.connections.iter().enumerate() {
|
for (index, conn) in port.connections.iter().enumerate() {
|
||||||
h_exact(1, w_full(origin_w(format!(" c{index:02}{}", conn.info()))))
|
h_exact(1, w_full(origin_w(format!(" c{index:02}{}", conn.info()))))
|
||||||
.draw(to);
|
.draw(to)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
todo!();
|
todo!();
|
||||||
|
|
@ -658,14 +656,14 @@ pub fn view_outputs (
|
||||||
h_exact(1, origin_w(east(
|
h_exact(1, origin_w(east(
|
||||||
either(true, fg(Green, "play "), "play "),
|
either(true, fg(Green, "play "), "play "),
|
||||||
either(false, fg(Yellow, "solo "), "solo "),
|
either(false, fg(Yellow, "solo "), "solo "),
|
||||||
))).draw(to);
|
))).draw(to)?;
|
||||||
for (_index, port) in midi_outs.iter().enumerate() {
|
for (_index, port) in midi_outs.iter().enumerate() {
|
||||||
h_exact(1, origin_w(east(
|
h_exact(1, origin_w(east(
|
||||||
either(true, fg(Green, " ● "), " · "),
|
either(true, fg(Green, " ● "), " · "),
|
||||||
either(false, fg(Yellow, " ● "), " · "),
|
either(false, fg(Yellow, " ● "), " · "),
|
||||||
))).draw(to);
|
))).draw(to)?;
|
||||||
for (_index, _conn) in port.connections.iter().enumerate() {
|
for (_index, _conn) in port.connections.iter().enumerate() {
|
||||||
h_exact(1, w_full("")).draw(to);
|
h_exact(1, w_full("")).draw(to)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
todo!()
|
todo!()
|
||||||
|
|
@ -734,7 +732,7 @@ pub fn view_sessions () -> impl Draw<Tui> {
|
||||||
let b = if index == 0 { Rgb(50,50,50) } else { Rgb(40,40,40) };
|
let b = if index == 0 { Rgb(50,50,50) } else { Rgb(40,40,40) };
|
||||||
let y = (2 * index) as u16;
|
let y = (2 * index) as u16;
|
||||||
let h = 2;
|
let h = 2;
|
||||||
y_push(y, &h_exact(h, w_full(bg(b, origin_w(fg(f, name)))))).draw(to);
|
y_push(y, h_exact(h, w_full(bg(b, origin_w(fg(f, *name)))))).draw(to)?;
|
||||||
}
|
}
|
||||||
Ok(to.area().into())
|
Ok(to.area().into())
|
||||||
})))
|
})))
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
impl_has!(Size: |self: App|self.size);
|
impl_has!(Sizer: |self: App|self.size);
|
||||||
|
|
||||||
/// Define a type alias for iterators of sized items (columns).
|
/// Define a type alias for iterators of sized items (columns).
|
||||||
macro_rules! def_sizes_iter {
|
macro_rules! def_sizes_iter {
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,9 @@ use crate::*;
|
||||||
/// TODO rename to "render_cache" or smth
|
/// TODO rename to "render_cache" or smth
|
||||||
pub arranger: Arc<RwLock<Buffer>>,
|
pub arranger: Arc<RwLock<Buffer>>,
|
||||||
/// Display size
|
/// Display size
|
||||||
pub size: Size,
|
pub size: Sizer,
|
||||||
/// Display size of clips area
|
/// Display size of clips area
|
||||||
pub size_inner: Size,
|
pub size_inner: Sizer,
|
||||||
/// Source of time
|
/// Source of time
|
||||||
#[cfg(feature = "clock")] pub clock: Clock,
|
#[cfg(feature = "clock")] pub clock: Clock,
|
||||||
/// Allows one MIDI clip to be edited
|
/// Allows one MIDI clip to be edited
|
||||||
|
|
@ -47,7 +47,7 @@ use crate::*;
|
||||||
|
|
||||||
impl HasJack<'static> for Arrangement { fn jack (&self) -> &Jack<'static> { &self.jack } }
|
impl HasJack<'static> for Arrangement { fn jack (&self) -> &Jack<'static> { &self.jack } }
|
||||||
impl_has!(Jack<'static>: |self: Arrangement| self.jack);
|
impl_has!(Jack<'static>: |self: Arrangement| self.jack);
|
||||||
impl_has!(Size: |self: Arrangement| self.size);
|
impl_has!(Sizer: |self: Arrangement| self.size);
|
||||||
impl_has!(Vec<MidiInput>: |self: Arrangement| self.midi_ins);
|
impl_has!(Vec<MidiInput>: |self: Arrangement| self.midi_ins);
|
||||||
impl_has!(Vec<MidiOutput>: |self: Arrangement| self.midi_outs);
|
impl_has!(Vec<MidiOutput>: |self: Arrangement| self.midi_outs);
|
||||||
impl_has!(Clock: |self: Arrangement| self.clock);
|
impl_has!(Clock: |self: Arrangement| self.clock);
|
||||||
|
|
|
||||||
|
|
@ -37,10 +37,6 @@ pub trait ClipsView: TracksView + ScenesView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasClipsSize for Arrangement {
|
|
||||||
fn clips_size (&self) -> &Size { &self.size_inner }
|
|
||||||
}
|
|
||||||
|
|
||||||
def_command!(ClipCommand: |clip: MidiClip| {
|
def_command!(ClipCommand: |clip: MidiClip| {
|
||||||
SetColor { color: Option<ItemTheme> } => {
|
SetColor { color: Option<ItemTheme> } => {
|
||||||
//(SetColor [t: usize, s: usize, c: ItemTheme]
|
//(SetColor [t: usize, s: usize, c: ItemTheme]
|
||||||
|
|
@ -86,8 +82,14 @@ impl Arrangement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait HasClipsSize { fn clips_size (&self) -> &Size; }
|
pub trait HasClipsSize {
|
||||||
|
fn clips_size (&self) -> &Sizer;
|
||||||
|
}
|
||||||
|
|
||||||
impl HasClipsSize for App {
|
impl HasClipsSize for App {
|
||||||
fn clips_size (&self) -> &Size { &self.project.size_inner }
|
fn clips_size (&self) -> &Sizer { &self.project.size_inner }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HasClipsSize for Arrangement {
|
||||||
|
fn clips_size (&self) -> &Sizer { &self.size_inner }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ def_command!(FileBrowserCommand: |sampler: Sampler|{
|
||||||
pub filter: String,
|
pub filter: String,
|
||||||
pub index: usize,
|
pub index: usize,
|
||||||
pub scroll: usize,
|
pub scroll: usize,
|
||||||
pub size: Size,
|
pub size: Sizer,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct EntriesIterator<'a, S: Screen> {
|
pub(crate) struct EntriesIterator<'a, S: Screen> {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,12 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use ::std::sync::{Arc, RwLock, atomic::{AtomicUsize, Ordering::*}};
|
use ::std::sync::{Arc, RwLock, atomic::AtomicUsize};
|
||||||
use ::atomic_float::AtomicF64;
|
use ::atomic_float::AtomicF64;
|
||||||
use ::tengri::{draw::*, term::*};
|
|
||||||
|
mod memo; pub use self::memo::*;
|
||||||
|
mod moment; pub use self::moment::*;
|
||||||
|
mod ticker; pub use self::ticker::*;
|
||||||
|
mod timebase; pub use self::timebase::*;
|
||||||
|
mod clock_view; pub use self::clock_view::*;
|
||||||
|
|
||||||
impl <T: AsRef<Clock>+AsMut<Clock>> HasClock for T {}
|
impl <T: AsRef<Clock>+AsMut<Clock>> HasClock for T {}
|
||||||
pub trait HasClock: AsRef<Clock> + AsMut<Clock> {
|
pub trait HasClock: AsRef<Clock> + AsMut<Clock> {
|
||||||
|
|
@ -396,8 +401,3 @@ impl_time_unit!(Ppq);
|
||||||
impl_time_unit!(Pulse);
|
impl_time_unit!(Pulse);
|
||||||
impl_time_unit!(Bpm);
|
impl_time_unit!(Bpm);
|
||||||
impl_time_unit!(LaunchSync);
|
impl_time_unit!(LaunchSync);
|
||||||
|
|
||||||
mod moment; pub use self::moment::*;
|
|
||||||
mod ticker; pub use self::ticker::*;
|
|
||||||
mod timebase; pub use self::timebase::*;
|
|
||||||
mod clock_view; pub use self::clock_view::*;
|
|
||||||
|
|
|
||||||
53
src/device/clock/memo.rs
Normal file
53
src/device/clock/memo.rs
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
#[macro_export] macro_rules! rewrite {
|
||||||
|
($buf:ident, $($rest:tt)*) => {
|
||||||
|
|$buf,_,_|{
|
||||||
|
$buf.clear();
|
||||||
|
write!($buf, $($rest)*)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Memo<T, U> {
|
||||||
|
value: T,
|
||||||
|
view: U,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, U> Memo<T, U> {
|
||||||
|
pub fn new (value: T, view: U) -> Self {
|
||||||
|
Self { value, view }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: PartialEq + Debug, U: Debug> Debug for Memo<T, U> {
|
||||||
|
fn fmt (&self, _: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: PartialEq, U> Memo<T, U> {
|
||||||
|
pub fn update <R> (&mut self, newval: T, render: impl Fn(&mut U, &T, &T)->R) -> Option<R> {
|
||||||
|
if newval != self.value {
|
||||||
|
let result = render(&mut self.view, &newval, &self.value);
|
||||||
|
self.value = newval;
|
||||||
|
return Some(result);
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Gettable<T> {
|
||||||
|
/// Returns current value
|
||||||
|
fn get (&self) -> T;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Mutable<T>: Gettable<T> {
|
||||||
|
/// Sets new value, returns old
|
||||||
|
fn set (&mut self, value: T) -> T;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait InteriorMutable<T>: Gettable<T> {
|
||||||
|
/// Sets new value, returns old
|
||||||
|
fn set (&self, value: T) -> T;
|
||||||
|
}
|
||||||
|
|
@ -19,12 +19,12 @@ pub struct MidiEditor {
|
||||||
/// View mode and state of editor
|
/// View mode and state of editor
|
||||||
pub mode: PianoHorizontal,
|
pub mode: PianoHorizontal,
|
||||||
/// Size of editor on screen
|
/// Size of editor on screen
|
||||||
pub size: Size,
|
pub size: Sizer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_default!(MidiEditor: Self {
|
impl_default!(MidiEditor: Self {
|
||||||
mode: PianoHorizontal::new(None),
|
mode: PianoHorizontal::new(None),
|
||||||
size: Size(
|
size: Sizer(
|
||||||
Arc::new(0usize.into()),
|
Arc::new(0usize.into()),
|
||||||
Arc::new(0usize.into()),
|
Arc::new(0usize.into()),
|
||||||
),
|
),
|
||||||
|
|
@ -255,13 +255,7 @@ pub trait MidiViewer: MidiRange + MidiPoint + Debug + Send + Sync {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_has!(Size: |self: MidiEditor| self.size);
|
impl_has!(Sizer: |self: MidiEditor| self.size);
|
||||||
|
|
||||||
impl Draw<Tui> for MidiEditor {
|
|
||||||
fn draw (self, to: &mut Tui) -> Usually<XYWH<u16>> {
|
|
||||||
self.mode.tui().draw(to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Debug for MidiEditor {
|
impl std::fmt::Debug for MidiEditor {
|
||||||
fn fmt (&self, f: &mut Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
|
fn fmt (&self, f: &mut Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
|
||||||
|
|
@ -303,7 +297,7 @@ impl View<Tui> for MidiEditor {
|
||||||
fn view (&self) -> impl Draw<Tui> {
|
fn view (&self) -> impl Draw<Tui> {
|
||||||
self.autoscroll();
|
self.autoscroll();
|
||||||
/*self.autozoom();*/
|
/*self.autozoom();*/
|
||||||
self.size.of(&self.mode)
|
self.size.of(self.mode.view())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ pub struct PianoHorizontal {
|
||||||
/// Buffer where the whole clip is rerendered on change
|
/// Buffer where the whole clip is rerendered on change
|
||||||
pub buffer: Arc<RwLock<BigBuffer>>,
|
pub buffer: Arc<RwLock<BigBuffer>>,
|
||||||
/// Size of actual notes area
|
/// Size of actual notes area
|
||||||
pub size: Size,
|
pub size: Sizer,
|
||||||
/// The display window
|
/// The display window
|
||||||
pub range: MidiSelection,
|
pub range: MidiSelection,
|
||||||
/// The note cursor
|
/// The note cursor
|
||||||
|
|
@ -22,17 +22,21 @@ pub struct PianoHorizontal {
|
||||||
pub keys_width: u16,
|
pub keys_width: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_has!(Size: |self: PianoHorizontal| self.size);
|
impl_has!(Sizer: |self: PianoHorizontal| self.size);
|
||||||
impl Draw<Tui> for PianoHorizontal {
|
|
||||||
fn draw (self, to: &mut Tui) -> Usually<XYWH<u16>> {
|
impl View<Tui> for PianoHorizontal {
|
||||||
self.tui().draw(to)
|
fn view (&self) -> impl Draw<Tui> {
|
||||||
|
south(
|
||||||
|
east(w_exact(5, format!("{}x{}", self.size.w(), self.size.h())), self.timeline()),
|
||||||
|
east(self.keys(), self.size.of(below(wh_full(self.notes()), wh_full(self.cursor())))),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PianoHorizontal {
|
impl PianoHorizontal {
|
||||||
|
|
||||||
pub fn new (clip: Option<&Arc<RwLock<MidiClip>>>) -> Self {
|
pub fn new (clip: Option<&Arc<RwLock<MidiClip>>>) -> Self {
|
||||||
let size = Size::default();
|
let size = Sizer::default();
|
||||||
let mut range = MidiSelection::from((12, true));
|
let mut range = MidiSelection::from((12, true));
|
||||||
range.time_axis = size.0.clone();
|
range.time_axis = size.0.clone();
|
||||||
range.note_axis = size.1.clone();
|
range.note_axis = size.1.clone();
|
||||||
|
|
@ -49,13 +53,6 @@ impl PianoHorizontal {
|
||||||
piano
|
piano
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tui (&self) -> impl Draw<Tui> {
|
|
||||||
south(
|
|
||||||
east(w_exact(5, format!("{}x{}", self.size.w(), self.size.h())), self.timeline()),
|
|
||||||
east(self.keys(), self.size.of(below(wh_full(self.notes()), wh_full(self.cursor())))),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Draw the piano roll background.
|
/// Draw the piano roll background.
|
||||||
///
|
///
|
||||||
/// This mode uses full blocks on note on and half blocks on legato: █▄ █▄ █▄
|
/// This mode uses full blocks on note on and half blocks on legato: █▄ █▄ █▄
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ mod sample_kit; pub use self::sample_kit::*;
|
||||||
/// Currently active modal, if any.
|
/// Currently active modal, if any.
|
||||||
pub mode: Option<SamplerMode>,
|
pub mode: Option<SamplerMode>,
|
||||||
/// Size of rendered sampler.
|
/// Size of rendered sampler.
|
||||||
pub size: Size,
|
pub size: Sizer,
|
||||||
/// Lowest note displayed.
|
/// Lowest note displayed.
|
||||||
pub note_lo: AtomicUsize,
|
pub note_lo: AtomicUsize,
|
||||||
/// Currently selected note.
|
/// Currently selected note.
|
||||||
|
|
|
||||||
2
tengri
2
tengri
|
|
@ -1 +1 @@
|
||||||
Subproject commit 90ebae0f26fc4524659704df274d0aec815dba2e
|
Subproject commit 0b9e9c06962e5cd55b639d9c0a7cef6f11405d81
|
||||||
Loading…
Add table
Add a link
Reference in a new issue