mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-09-18 12:56:42 +02:00
Compare commits
2 commits
ba8ff1ae69
...
8de62463c0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8de62463c0 | ||
|
|
5357e83245 |
7 changed files with 76 additions and 34 deletions
|
|
@ -131,7 +131,7 @@ impl MidiEditor {
|
|||
}
|
||||
|
||||
/// ```
|
||||
/// use tek::{*, tengri::{*, lang::*}};
|
||||
/// use tek::{*, tengri::*};
|
||||
///
|
||||
/// struct Test(Option<MidiEditor>);
|
||||
/// impl_as_ref_opt!(MidiEditor: |self: Test|self.0.as_ref());
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ impl PianoHorizontal {
|
|||
let note_lo = self.get_note_lo();
|
||||
let note_hi = self.get_note_hi();
|
||||
let buffer = self.buffer.clone();
|
||||
thunk(move|to: &mut Tui|{
|
||||
draw(move|to: &mut Tui|{
|
||||
let xywh = to.area().into();
|
||||
let XYWH(x0, y0, w, _h) = xywh;
|
||||
let source = buffer.read().unwrap();
|
||||
|
|
@ -175,7 +175,7 @@ impl PianoHorizontal {
|
|||
let time_start = self.get_time_start();
|
||||
let time_zoom = self.get_time_zoom();
|
||||
let style = Some(Style::default().fg(self.color.lightest.term));
|
||||
thunk(move|to: &mut Tui|{
|
||||
draw(move|to: &mut Tui|{
|
||||
let xywh = to.area().into();
|
||||
let XYWH(x0, y0, w, _h) = xywh;
|
||||
for (_area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) {
|
||||
|
|
@ -209,7 +209,7 @@ impl PianoHorizontal {
|
|||
let key_style = Some(Style::default().fg(Rgb(192, 192, 192)).bg(Rgb(0, 0, 0)));
|
||||
let off_style = Some(Style::default().fg(g(255)));
|
||||
let on_style = Some(Style::default().fg(Rgb(255,0,0)).bg(color.base.term).bold());
|
||||
thunk(move|to: &mut Tui|{
|
||||
draw(move|to: &mut Tui|{
|
||||
let xywh = to.area().into();
|
||||
let XYWH(x, y0, _w, _h) = xywh;
|
||||
for (_area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) {
|
||||
|
|
@ -228,7 +228,7 @@ impl PianoHorizontal {
|
|||
}
|
||||
|
||||
fn timeline (&self) -> impl Draw<Tui> + '_ {
|
||||
thunk(move|to: &mut Tui|{
|
||||
draw(move|to: &mut Tui|{
|
||||
let xywh = to.area().into();
|
||||
let XYWH(x, y, w, _h) = xywh;
|
||||
let style = Some(Style::default().dim());
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ impl ApplicationHandler for LV2PluginUI {
|
|||
}
|
||||
|
||||
impl Draw<Tui> for Lv2 {
|
||||
fn draw(self, to: &mut Tui) {
|
||||
fn draw (&self, to: &mut Tui) {
|
||||
let area = to.area();
|
||||
let XYWH(x, y, _, height) = area;
|
||||
let mut width = 20u16;
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ fn draw_list_item (sample: &Option<Arc<RwLock<Sample>>>) -> String {
|
|||
|
||||
fn draw_viewer (sample: Option<&Arc<RwLock<Sample>>>) -> impl Draw<Tui> + use<'_> {
|
||||
let min_db = -64.0;
|
||||
thunk(move|to: &mut Tui|{
|
||||
draw(move|to: &mut Tui|{
|
||||
let xywh = to.area().into();
|
||||
let XYWH(x, y, width, height) = xywh;
|
||||
let area = Rect { x, y, width, height };
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@
|
|||
:transport)
|
||||
|
||||
(mode :menu (name Menu) (info Mode selector.) (keys :axis/y :confirm)
|
||||
(view (bg (g 64)
|
||||
(bsp/s (max/xy 80 2 :transport)
|
||||
(view (bg (g 16)
|
||||
(bsp/s (fill/x (bg (g 32) (max/xy 80 2 :transport)))
|
||||
(bsp/s (max/y 3 (bg (g 80) :ports/out))
|
||||
(bsp/n (max/y 3 (bg (g 80) :ports/in))
|
||||
(bg (g 30) (bsp/s (max/y 6 :logo) :dialog/menu))))))))
|
||||
|
|
|
|||
90
src/tek.rs
90
src/tek.rs
|
|
@ -25,7 +25,7 @@ pub(crate) use ::{
|
|||
},
|
||||
tengri::{
|
||||
*,
|
||||
lang::*,
|
||||
dizzle::*,
|
||||
midly::{
|
||||
Smf, TrackEventKind, MidiMessage, Error as MidiError,
|
||||
num::*,
|
||||
|
|
@ -451,9 +451,11 @@ mod app {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_arc_str (&self, src: impl Language) -> Perhaps<Arc<str>> {
|
||||
Ok(src.src()?.map(|x|x.into()))
|
||||
}
|
||||
|
||||
fn get_u16 (&self, src: impl Language) -> Perhaps<u16> {
|
||||
Ok(Some(match src.word()? {
|
||||
Some(":w/sidebar") => self.project.w_sidebar(self.editor().is_some()),
|
||||
|
|
@ -461,6 +463,7 @@ mod app {
|
|||
_ => return try_to_u16(src)
|
||||
}))
|
||||
}
|
||||
|
||||
fn get_usize (&self, src: impl Language) -> Perhaps<usize> {
|
||||
Ok(Some(match src.word()? {
|
||||
Some(":scene-count") => self.scenes().len(),
|
||||
|
|
@ -471,6 +474,7 @@ mod app {
|
|||
_ => return try_to_usize(src)
|
||||
}))
|
||||
}
|
||||
|
||||
fn get_bool (&self, src: impl Language) -> Perhaps<bool> {
|
||||
src.word()?.map(|word|Ok(match word {
|
||||
"Y" => true,
|
||||
|
|
@ -491,6 +495,7 @@ mod app {
|
|||
_ => return Err(format!("not bool: {word}").into())
|
||||
})).transpose()
|
||||
}
|
||||
|
||||
fn get_selection (&self, src: impl Language) -> Perhaps<Selection> {
|
||||
src.word()?.map(|word|Ok(match word {
|
||||
":select/scene" => self.selection().select_scene(self.tracks().len()),
|
||||
|
|
@ -502,6 +507,7 @@ mod app {
|
|||
_ => return Err(format!("not selection: {word}").into())
|
||||
})).transpose()
|
||||
}
|
||||
|
||||
fn get_color (&self, src: impl Language) -> Perhaps<Color> {
|
||||
if let Some(expr) = src.expr()? {
|
||||
match (expr.head()?, expr.tail()?) {
|
||||
|
|
@ -531,6 +537,7 @@ mod app {
|
|||
return Err(format!("not a color: {:?}", src.src()?).into())
|
||||
}
|
||||
}
|
||||
|
||||
fn get_opt_u7 (&self, src: impl Language) -> Perhaps<Option<u7>> {
|
||||
src.word()?.map(|word|Ok(match word {
|
||||
":editor/pitch" => Some((
|
||||
|
|
@ -539,9 +546,11 @@ mod app {
|
|||
_ => return Err(format!("unknown midi note: {word}").into())
|
||||
})).transpose()
|
||||
}
|
||||
|
||||
fn get_opt_u16 (&self, _src: impl Language) -> Perhaps<Option<u16>> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn get_opt_usize (&self, src: impl Language) -> Perhaps<Option<usize>> {
|
||||
src.word()?.map(|word|Ok(match word {
|
||||
":selected/scene" => self.selection().scene(),
|
||||
|
|
@ -549,6 +558,7 @@ mod app {
|
|||
_ => return Err(format!("unknown opt<usize>: {word}").into())
|
||||
})).transpose()
|
||||
}
|
||||
|
||||
fn get_clip (&self, src: impl Language) -> Perhaps<Option<Arc<RwLock<MidiClip>>>> {
|
||||
src.word()?.map(|word|Ok(match word {
|
||||
":selected/clip" if let Selection::TrackClip { track, scene } = self.selection() =>
|
||||
|
|
@ -556,6 +566,7 @@ mod app {
|
|||
_ => return Err(format!("not a clip: {word}").into())
|
||||
})).transpose()
|
||||
}
|
||||
|
||||
pub fn inc (&mut self, axis: &ControlAxis) -> Perhaps<AppCommand> {
|
||||
Ok(match (&self.dialog, axis) {
|
||||
(Dialog::None, _) => todo!(),
|
||||
|
|
@ -564,6 +575,7 @@ mod app {
|
|||
_ => todo!()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn dec (&mut self, axis: &ControlAxis) -> Perhaps<AppCommand> {
|
||||
Ok(match (&self.dialog, axis) {
|
||||
(Dialog::None, _) => None,
|
||||
|
|
@ -572,6 +584,7 @@ mod app {
|
|||
_ => todo!()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn confirm (&mut self) -> Perhaps<AppCommand> {
|
||||
Ok(match &self.dialog {
|
||||
Dialog::Menu(index, items) => {
|
||||
|
|
@ -582,6 +595,7 @@ mod app {
|
|||
_ => todo!(),
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn swap_value <T: Clone + PartialEq, U> (
|
||||
|
|
@ -1033,6 +1047,26 @@ pub fn show_version () {
|
|||
//})?)?
|
||||
//}
|
||||
|
||||
/// Define an enum containing commands, and implement [Command] trait for over given `State`.
|
||||
#[macro_export] macro_rules! def_command (
|
||||
($Command:ident: |$state:ident: $State:ty| {
|
||||
// FIXME: support attrs (docstrings)
|
||||
$($Variant:ident$({$($arg:ident:$Arg:ty),+ $(,)?})?=>$body:expr),* $(,)?
|
||||
})=>{
|
||||
#[derive(Debug)] pub enum $Command {
|
||||
// FIXME: support attrs (docstrings)
|
||||
$($Variant $({ $($arg: $Arg),* })?),*
|
||||
}
|
||||
impl ::tengri::dizzle::Act<$State> for $Command {
|
||||
fn act (&self, $state: &mut $State) -> Perhaps<Self> {
|
||||
match self {
|
||||
$(Self::$Variant $({ $($arg),* })? => $body,)*
|
||||
_ => unimplemented!("Act<{}>: {self:?}", stringify!($State)),
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
pub use self::config::*;
|
||||
mod config {
|
||||
use crate::*;
|
||||
|
|
@ -1418,12 +1452,11 @@ mod draw {
|
|||
/// Then, every top-level form of the DSL description is rendered.
|
||||
impl View<Tui> for App {
|
||||
fn view (&self) -> impl Draw<Tui> {
|
||||
thunk(|to: &mut Tui|{
|
||||
draw(|to: &mut Tui|{
|
||||
let xywh = to.area().into();
|
||||
|
||||
if let Some(e) = self.error.read().unwrap().as_ref() {
|
||||
//to.show(area(xywh, format!("KYPbanica {xywh:?}").align_c()))?;
|
||||
to.show(e.as_ref().align_c())?;
|
||||
e.as_ref().align_c().draw(to)?;
|
||||
}
|
||||
|
||||
if let Some(ref mode) = self.mode {
|
||||
|
|
@ -1437,13 +1470,22 @@ mod draw {
|
|||
}
|
||||
}
|
||||
|
||||
to.show(ShowSize.align_se())?;
|
||||
ShowSize.align_se().draw(to)?;
|
||||
|
||||
Ok(Some(xywh))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Keywords<Tui, XYWH<u16>> for App {
|
||||
fn keywords () -> impl Iterator<Item = fn(&Self, &mut Tui, &str) -> Perhaps<XYWH<u16>>> {
|
||||
[
|
||||
kw_when, kw_either, kw_split, kw_align,
|
||||
kw_exact, kw_fixed, kw_min, kw_max, kw_push
|
||||
].into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl Interpret<Tui, Option<XYWH<u16>>> for App {
|
||||
fn interpret_expr <'a> (&'a self, to: &mut Tui, lang: &'a impl Expression) -> Drawn<u16> {
|
||||
tek_draw_expr(self, to, lang)
|
||||
|
|
@ -1456,7 +1498,7 @@ mod draw {
|
|||
fn tek_draw_expr (state: &App, to: &mut Tui, lang: &impl Expression) -> Drawn<u16> {
|
||||
Ok(Some(if let Some(area) = eval_view(state, to, lang)? {
|
||||
area
|
||||
} else if let Some(area) = eval_view_tui(state, to, lang)? {
|
||||
} else if let Some(area) = Tui::eval_view(state, to, lang)? {
|
||||
area
|
||||
} else {
|
||||
return Err(format!("App::interpret_expr: unexpected: {lang:?}").into())
|
||||
|
|
@ -1548,7 +1590,7 @@ mod draw {
|
|||
Some("menu") => if let Dialog::Menu(selected, items) = &state.dialog {
|
||||
let items = items.clone();
|
||||
let selected = selected;
|
||||
Some(thunk(move|to: &mut Tui|{
|
||||
Some(draw(move|to: &mut Tui|{
|
||||
for (index, MenuItem(item, _)) in items.0.iter().enumerate() {
|
||||
let f = if *selected == index { Rgb(240,200,180) } else { Rgb(200, 200, 200) };
|
||||
let b = if *selected == index { Rgb(80, 80, 50) } else { Rgb(30, 30, 30) };
|
||||
|
|
@ -1566,7 +1608,7 @@ mod draw {
|
|||
|
||||
pub fn draw_templates (to: &mut Tui, _frags: std::str::Split<&str>, state: &App) -> Drawn<u16> {
|
||||
let height = (state.config.modes.len() * 2) as u16;
|
||||
thunk(move |to: &mut Tui|{
|
||||
draw(move |to: &mut Tui|{
|
||||
let mut index = 0;
|
||||
state.config.modes.for_each(|id, profile| {
|
||||
let b = if index == 0 { Rgb(70,70,70) } else { Rgb(50,50,50) };
|
||||
|
|
@ -1620,7 +1662,7 @@ mod draw {
|
|||
let h = 6;
|
||||
let w = Some(30);
|
||||
let f = Rgb(224, 192, 128);
|
||||
thunk(move |to: &mut Tui|{
|
||||
draw(move |to: &mut Tui|{
|
||||
for (index, name) in ["session1", "session2", "session3"].iter().enumerate() {
|
||||
let b = if index == 0 { Rgb(50,50,50) } else { Rgb(40,40,40) };
|
||||
let y = (2 * index) as u16;
|
||||
|
|
@ -1698,11 +1740,11 @@ mod draw {
|
|||
pub fn button_play_pause (playing: bool, compact: bool) -> impl Draw<Tui> {
|
||||
bg(if playing { Rgb(0, 128, 0) } else { Rgb(128, 64, 0) },
|
||||
either(compact,
|
||||
thunk(move|to: &mut Tui|either(playing,
|
||||
draw(move|to: &mut Tui|either(playing,
|
||||
fg(Rgb(0, 255, 0), " PLAYING "),
|
||||
fg(Rgb(255, 128, 0), " STOPPED "),
|
||||
).exact_w(9).draw(to)),
|
||||
thunk(move|to: &mut Tui|either(playing,
|
||||
draw(move|to: &mut Tui|either(playing,
|
||||
fg(Rgb(0, 255, 0), south(" 🭍🭑🬽 ", " 🭞🭜🭘 ",)),
|
||||
fg(Rgb(255, 128, 0), south(" ▗▄▖ ", " ▝▀▘ ",)),
|
||||
).exact_w(5).draw(to)),
|
||||
|
|
@ -1769,7 +1811,7 @@ mod draw {
|
|||
}
|
||||
|
||||
pub fn view_sample_info (sample: Option<&Arc<RwLock<Sample>>>) -> impl Draw<Tui> + use<'_> {
|
||||
when(sample.is_some(), thunk(move|to: &mut Tui|{
|
||||
when(sample.is_some(), draw(move|to: &mut Tui|{
|
||||
let sample = sample.unwrap().read().unwrap();
|
||||
let theme = sample.color;
|
||||
east!(
|
||||
|
|
@ -1784,7 +1826,7 @@ mod draw {
|
|||
}
|
||||
|
||||
pub fn view_sample_info_v (sample: Option<&Arc<RwLock<Sample>>>) -> impl Draw<Tui> + use<'_> {
|
||||
let a = thunk(move|to: &mut Tui|{
|
||||
let a = draw(move|to: &mut Tui|{
|
||||
let sample = sample.unwrap().read().unwrap();
|
||||
let theme = sample.color;
|
||||
south!(
|
||||
|
|
@ -1797,7 +1839,7 @@ mod draw {
|
|||
).exact_w(20).draw(to)
|
||||
});
|
||||
|
||||
let b = thunk(|to: &mut Tui|fg(Red, south!(
|
||||
let b = draw(|to: &mut Tui|fg(Red, south!(
|
||||
bold(true, "× No sample."),
|
||||
"[r] record",
|
||||
"[Shift-F9] import",
|
||||
|
|
@ -1941,7 +1983,7 @@ mod draw {
|
|||
button_2("T", "+", false),
|
||||
button_2("S", "+", false));
|
||||
view_track_row_section(theme, button, button_2, bg(theme.darker.term,
|
||||
thunk(|to: &mut Tui|{
|
||||
draw(|to: &mut Tui|{
|
||||
for (index, track, x1, _x2) in tracks {
|
||||
let b = if selected.track() == Some(index) {
|
||||
track.color.light.term
|
||||
|
|
@ -1967,14 +2009,14 @@ mod draw {
|
|||
) -> impl Draw<Tui> {
|
||||
view_track_row_section(theme,
|
||||
south(button_2("o", "utput", false).align_w().full_w(),
|
||||
thunk(|to: &mut Tui|{
|
||||
draw(|to: &mut Tui|{
|
||||
for port in midi_outs {
|
||||
let _ = port.port_name().align_w().full_w().draw(to)?;
|
||||
}
|
||||
Ok(Some(XYWH(0, 0, 0, 0)))
|
||||
})),
|
||||
button_2("O", "+", false),
|
||||
bg(theme.darker.term, thunk(|to: &mut Tui|{
|
||||
bg(theme.darker.term, draw(|to: &mut Tui|{
|
||||
for (index, track, _x1, _x2) in tracks {
|
||||
let f = Rgb(255, 255, 255);
|
||||
let b = track.color.dark.term;
|
||||
|
|
@ -1993,7 +2035,7 @@ mod draw {
|
|||
theme: ItemTheme, tracks: impl TracksSizes<'a>, height: u16,
|
||||
) -> impl Draw<Tui> {
|
||||
view_track_row_section(theme, button_2("i", "nput", false), button_2("I", "+", false),
|
||||
bg(theme.darker.term, thunk(move|to: &mut Tui|{
|
||||
bg(theme.darker.term, draw(move|to: &mut Tui|{
|
||||
for (index, track, _x1, _x2) in tracks {
|
||||
south(
|
||||
bg(track.color.base.term,
|
||||
|
|
@ -2017,7 +2059,7 @@ mod draw {
|
|||
editor: Option<&MidiEditor>,
|
||||
editing: bool,
|
||||
) -> impl Draw<Tui> {
|
||||
thunk(move |to: &mut Tui|{
|
||||
draw(move |to: &mut Tui|{
|
||||
for (index, scene, ..) in scenes {
|
||||
view_scene_name(select, editor, index, scene, editing).draw(to)?;
|
||||
}
|
||||
|
|
@ -2088,7 +2130,7 @@ mod draw {
|
|||
) -> impl Draw<Tui> {
|
||||
let title_1 = button_3("i", "nput ", format!("{}", midi_ins.len()), false).align_w().exact_wh(20, 1);
|
||||
let title_2 = button_2("I", "+", false).exact_wh(4, 1);
|
||||
east(title_1, west(title_2, thunk(move|to: &mut Tui|{
|
||||
east(title_1, west(title_2, draw(move|to: &mut Tui|{
|
||||
for (_index, track, x1, _x2) in tracks {
|
||||
let _ = south(
|
||||
bg(track.color.dark.term, east!(
|
||||
|
|
@ -2096,7 +2138,7 @@ mod draw {
|
|||
either(track.sequencer.recording, fg(Red, "rec "), "rec "),
|
||||
either(track.sequencer.overdub, fg(Yellow, "dub "), "dub "),
|
||||
).exact_w(track.width as u16)).align_w().push_x(x1 as u16),
|
||||
thunk(move |to: &mut Tui|{
|
||||
draw(move |to: &mut Tui|{
|
||||
for (index, port) in midi_ins.iter().enumerate() {
|
||||
let _ = east(
|
||||
east(
|
||||
|
|
@ -2132,7 +2174,7 @@ mod draw {
|
|||
button_3(
|
||||
"o", "utput", format!("{}", midi_outs.len()), false
|
||||
).align_w().full_w().exact_h(1),
|
||||
thunk(|to: &mut Tui|{
|
||||
draw(|to: &mut Tui|{
|
||||
for (_index, port) in midi_outs.iter().enumerate() {
|
||||
east(
|
||||
east(" ● ", fg(Rgb(255,255,255), bold(true, port.port_name()))).align_w(),
|
||||
|
|
@ -2148,9 +2190,9 @@ mod draw {
|
|||
);
|
||||
|
||||
view_track_row_section(theme, list, button_2("O", "+", false),
|
||||
bg(theme.darker.term, thunk(|to: &mut Tui|{
|
||||
bg(theme.darker.term, draw(|to: &mut Tui|{
|
||||
for (index, track, _x1, _x2) in tracks {
|
||||
let _ = thunk(|to: &mut Tui|{
|
||||
let _ = draw(|to: &mut Tui|{
|
||||
east(
|
||||
either(true, fg(Green, "play "), "play "),
|
||||
either(false, fg(Yellow, "solo "), "solo "),
|
||||
|
|
|
|||
2
tengri
2
tengri
|
|
@ -1 +1 @@
|
|||
Subproject commit 5ca329292f808c137b6e2b7e80892e2a9e855696
|
||||
Subproject commit eb028c85fc94a1b86c44d4f079e5fb91667d4db2
|
||||
Loading…
Add table
Add a link
Reference in a new issue