mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-04-03 21:00:44 +02:00
parent
54f0a95f3a
commit
0577309b19
4 changed files with 92 additions and 69 deletions
|
|
@ -14,7 +14,7 @@ path = "app/tek.rs"
|
|||
rustflags = ["-C", "link-arg=-fuse-ld=mold"]
|
||||
|
||||
[dependencies]
|
||||
tengri = { path = "./tengri", features = [ "tui", "dsl" ] }
|
||||
tengri = { path = "./tengri", features = [ "term", "lang" ] }
|
||||
|
||||
ansi_term = { version = "0.12.1" }
|
||||
atomic_float = { version = "1.0.0" }
|
||||
|
|
|
|||
28
app/tek.rs
28
app/tek.rs
|
|
@ -20,6 +20,12 @@ pub(crate) use ::midly::{Smf, TrackEventKind, MidiMessage, Error as MidiError, n
|
|||
pub extern crate tengri;
|
||||
pub(crate) use tengri::{
|
||||
*,
|
||||
lang::*,
|
||||
play::*,
|
||||
sing::*,
|
||||
time::*,
|
||||
draw::*,
|
||||
tui::*,
|
||||
crossterm::event::{Event, KeyEvent},
|
||||
ratatui::{
|
||||
self,
|
||||
|
|
@ -62,8 +68,26 @@ pub(crate) use ConnectStatus::*;
|
|||
|
||||
/// Command-line entrypoint.
|
||||
#[cfg(feature = "cli")] pub fn main () -> Usually<()> {
|
||||
use clap::Parser;
|
||||
Cli::parse().run()
|
||||
Config::watch(|config|{
|
||||
Exit::enter(|exit|{
|
||||
Jack::connect("tek", |jack|{
|
||||
let state = Arc::new(RwLock::new(App {
|
||||
color: ItemTheme::random(),
|
||||
config: Config::init(),
|
||||
dialog: Dialog::welcome(),
|
||||
jack: jack.clone(),
|
||||
mode: ":menu",
|
||||
project: Arrangement::new(&jack, &Clock::new(&jack, 51)),
|
||||
..Default::default()
|
||||
}));
|
||||
// TODO: Sync these timings with main clock, so that things
|
||||
// "accidentally" fall on the beat in overload conditions.
|
||||
let keyboard = run_tui_in(&exit, &state, Duration::from_millis(100))?;
|
||||
let terminal = run_tui_out(&exit, &state, Duration::from_millis(10))?;
|
||||
(keyboard, terminal)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// Create a new application from a backend, project, config, and mode
|
||||
|
|
|
|||
129
app/tek_impls.rs
129
app/tek_impls.rs
|
|
@ -1,6 +1,69 @@
|
|||
use crate::*;
|
||||
use std::fmt::Write;
|
||||
|
||||
/// Implement an arithmetic operation for a unit of time
|
||||
#[macro_export] macro_rules! impl_op {
|
||||
($T:ident, $Op:ident, $method:ident, |$a:ident,$b:ident|{$impl:expr}) => {
|
||||
impl $Op<Self> for $T {
|
||||
type Output = Self; #[inline] fn $method (self, other: Self) -> Self::Output {
|
||||
let $a = self.get(); let $b = other.get(); Self($impl.into())
|
||||
}
|
||||
}
|
||||
impl $Op<usize> for $T {
|
||||
type Output = Self; #[inline] fn $method (self, other: usize) -> Self::Output {
|
||||
let $a = self.get(); let $b = other as f64; Self($impl.into())
|
||||
}
|
||||
}
|
||||
impl $Op<f64> for $T {
|
||||
type Output = Self; #[inline] fn $method (self, other: f64) -> Self::Output {
|
||||
let $a = self.get(); let $b = other; Self($impl.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Define and implement a unit of time
|
||||
#[macro_export] macro_rules! impl_time_unit {
|
||||
($T:ident) => {
|
||||
impl Gettable<f64> for $T {
|
||||
fn get (&self) -> f64 { self.0.load(Relaxed) }
|
||||
}
|
||||
impl InteriorMutable<f64> for $T {
|
||||
fn set (&self, value: f64) -> f64 {
|
||||
let old = self.get();
|
||||
self.0.store(value, Relaxed);
|
||||
old
|
||||
}
|
||||
}
|
||||
impl TimeUnit for $T {}
|
||||
impl_op!($T, Add, add, |a, b|{a + b});
|
||||
impl_op!($T, Sub, sub, |a, b|{a - b});
|
||||
impl_op!($T, Mul, mul, |a, b|{a * b});
|
||||
impl_op!($T, Div, div, |a, b|{a / b});
|
||||
impl_op!($T, Rem, rem, |a, b|{a % b});
|
||||
impl From<f64> for $T { fn from (value: f64) -> Self { Self(value.into()) } }
|
||||
impl From<usize> for $T { fn from (value: usize) -> Self { Self((value as f64).into()) } }
|
||||
impl From<$T> for f64 { fn from (value: $T) -> Self { value.get() } }
|
||||
impl From<$T> for usize { fn from (value: $T) -> Self { value.get() as usize } }
|
||||
impl From<&$T> for f64 { fn from (value: &$T) -> Self { value.get() } }
|
||||
impl From<&$T> for usize { fn from (value: &$T) -> Self { value.get() as usize } }
|
||||
impl Clone for $T { fn clone (&self) -> Self { Self(self.get().into()) } }
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export] macro_rules! impl_has_clips {
|
||||
(|$self:ident:$Struct:ident$(<$($L:lifetime),*$($T:ident$(:$U:path)?),*>)?|$cb:expr) => {
|
||||
impl $(<$($L),*$($T $(: $U)?),*>)? HasClips for $Struct $(<$($L),*$($T),*>)? {
|
||||
fn clips <'a> (&'a $self) -> std::sync::RwLockReadGuard<'a, ClipPool> {
|
||||
$cb.read().unwrap()
|
||||
}
|
||||
fn clips_mut <'a> (&'a $self) -> std::sync::RwLockWriteGuard<'a, ClipPool> {
|
||||
$cb.write().unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl <T: AsRef<Clock>+AsMut<Clock>> HasClock for T {}
|
||||
impl <T: AsRef<Selection>+AsMut<Selection>> HasSelection for T {}
|
||||
impl <T: AsRef<Sequencer>+AsMut<Sequencer>> HasSequencer for T {}
|
||||
|
|
@ -40,7 +103,7 @@ mod app {
|
|||
impl Draw<TuiOut> for App {
|
||||
fn draw (&self, to: &mut TuiOut) {
|
||||
if let Some(e) = self.error.read().unwrap().as_ref() {
|
||||
to.place_at(to.area(), e);
|
||||
to.show(to.area(), e);
|
||||
}
|
||||
for (index, dsl) in self.mode.view.iter().enumerate() {
|
||||
if let Err(e) = self.understand(to, dsl) {
|
||||
|
|
@ -51,7 +114,6 @@ mod app {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a> Namespace<'a, AppCommand> for App {
|
||||
symbols!('a |app| -> AppCommand {
|
||||
"x/inc" => AppCommand::Inc { axis: ControlAxis::X },
|
||||
|
|
@ -1082,9 +1144,6 @@ impl<J: HasJack<'static>> RegisterPorts for J {
|
|||
impl_debug!(MenuItem |self, w| { write!(w, "{}", &self.0) });
|
||||
impl_debug!(Condition |self, w| { write!(w, "*") });
|
||||
|
||||
macro_rules!primitive(($T:ty: $name:ident)=>{
|
||||
fn $name (src: impl Language) -> Perhaps<$T> {
|
||||
Ok(if let Some(src) = src.src()? { Some(to_number(src)? as $T) } else { None }) } });
|
||||
primitive!(u8: try_to_u8);
|
||||
primitive!(u16: try_to_u16);
|
||||
primitive!(usize: try_to_usize);
|
||||
|
|
@ -1364,54 +1423,6 @@ mod time {
|
|||
}
|
||||
}
|
||||
|
||||
/// Implement an arithmetic operation for a unit of time
|
||||
#[macro_export] macro_rules! impl_op {
|
||||
($T:ident, $Op:ident, $method:ident, |$a:ident,$b:ident|{$impl:expr}) => {
|
||||
impl $Op<Self> for $T {
|
||||
type Output = Self; #[inline] fn $method (self, other: Self) -> Self::Output {
|
||||
let $a = self.get(); let $b = other.get(); Self($impl.into())
|
||||
}
|
||||
}
|
||||
impl $Op<usize> for $T {
|
||||
type Output = Self; #[inline] fn $method (self, other: usize) -> Self::Output {
|
||||
let $a = self.get(); let $b = other as f64; Self($impl.into())
|
||||
}
|
||||
}
|
||||
impl $Op<f64> for $T {
|
||||
type Output = Self; #[inline] fn $method (self, other: f64) -> Self::Output {
|
||||
let $a = self.get(); let $b = other; Self($impl.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Define and implement a unit of time
|
||||
#[macro_export] macro_rules! impl_time_unit {
|
||||
($T:ident) => {
|
||||
impl Gettable<f64> for $T {
|
||||
fn get (&self) -> f64 { self.0.load(Relaxed) }
|
||||
}
|
||||
impl InteriorMutable<f64> for $T {
|
||||
fn set (&self, value: f64) -> f64 {
|
||||
let old = self.get();
|
||||
self.0.store(value, Relaxed);
|
||||
old
|
||||
}
|
||||
}
|
||||
impl TimeUnit for $T {}
|
||||
impl_op!($T, Add, add, |a, b|{a + b});
|
||||
impl_op!($T, Sub, sub, |a, b|{a - b});
|
||||
impl_op!($T, Mul, mul, |a, b|{a * b});
|
||||
impl_op!($T, Div, div, |a, b|{a / b});
|
||||
impl_op!($T, Rem, rem, |a, b|{a % b});
|
||||
impl From<f64> for $T { fn from (value: f64) -> Self { Self(value.into()) } }
|
||||
impl From<usize> for $T { fn from (value: usize) -> Self { Self((value as f64).into()) } }
|
||||
impl From<$T> for f64 { fn from (value: $T) -> Self { value.get() } }
|
||||
impl From<$T> for usize { fn from (value: $T) -> Self { value.get() as usize } }
|
||||
impl From<&$T> for f64 { fn from (value: &$T) -> Self { value.get() } }
|
||||
impl From<&$T> for usize { fn from (value: &$T) -> Self { value.get() as usize } }
|
||||
impl Clone for $T { fn clone (&self) -> Self { Self(self.get().into()) } }
|
||||
}
|
||||
}
|
||||
impl_time_unit!(SampleCount);
|
||||
impl_time_unit!(SampleRate);
|
||||
impl_time_unit!(Microsecond);
|
||||
|
|
@ -3495,18 +3506,6 @@ mod pool {
|
|||
format!("{:>02}", self.ticks()).into()
|
||||
}
|
||||
}
|
||||
#[macro_export] macro_rules! has_clips {
|
||||
(|$self:ident:$Struct:ident$(<$($L:lifetime),*$($T:ident$(:$U:path)?),*>)?|$cb:expr) => {
|
||||
impl $(<$($L),*$($T $(: $U)?),*>)? HasClips for $Struct $(<$($L),*$($T),*>)? {
|
||||
fn clips <'a> (&'a $self) -> std::sync::RwLockReadGuard<'a, ClipPool> {
|
||||
$cb.read().unwrap()
|
||||
}
|
||||
fn clips_mut <'a> (&'a $self) -> std::sync::RwLockWriteGuard<'a, ClipPool> {
|
||||
$cb.write().unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Pool {
|
||||
fn _todo_usize_ (&self) -> usize { todo!() }
|
||||
|
|
|
|||
2
tengri
2
tengri
|
|
@ -1 +1 @@
|
|||
Subproject commit f1dda6af07b94928481d062c3d3fda5b9e969633
|
||||
Subproject commit 9dbf4fcab5f31a68e3d24c8f8f7fc866159e89f1
|
||||
Loading…
Add table
Add a link
Reference in a new issue