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"]
|
rustflags = ["-C", "link-arg=-fuse-ld=mold"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tengri = { path = "./tengri", features = [ "tui", "dsl" ] }
|
tengri = { path = "./tengri", features = [ "term", "lang" ] }
|
||||||
|
|
||||||
ansi_term = { version = "0.12.1" }
|
ansi_term = { version = "0.12.1" }
|
||||||
atomic_float = { version = "1.0.0" }
|
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 extern crate tengri;
|
||||||
pub(crate) use tengri::{
|
pub(crate) use tengri::{
|
||||||
*,
|
*,
|
||||||
|
lang::*,
|
||||||
|
play::*,
|
||||||
|
sing::*,
|
||||||
|
time::*,
|
||||||
|
draw::*,
|
||||||
|
tui::*,
|
||||||
crossterm::event::{Event, KeyEvent},
|
crossterm::event::{Event, KeyEvent},
|
||||||
ratatui::{
|
ratatui::{
|
||||||
self,
|
self,
|
||||||
|
|
@ -62,8 +68,26 @@ pub(crate) use ConnectStatus::*;
|
||||||
|
|
||||||
/// Command-line entrypoint.
|
/// Command-line entrypoint.
|
||||||
#[cfg(feature = "cli")] pub fn main () -> Usually<()> {
|
#[cfg(feature = "cli")] pub fn main () -> Usually<()> {
|
||||||
use clap::Parser;
|
Config::watch(|config|{
|
||||||
Cli::parse().run()
|
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
|
/// 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 crate::*;
|
||||||
use std::fmt::Write;
|
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<Clock>+AsMut<Clock>> HasClock for T {}
|
||||||
impl <T: AsRef<Selection>+AsMut<Selection>> HasSelection for T {}
|
impl <T: AsRef<Selection>+AsMut<Selection>> HasSelection for T {}
|
||||||
impl <T: AsRef<Sequencer>+AsMut<Sequencer>> HasSequencer for T {}
|
impl <T: AsRef<Sequencer>+AsMut<Sequencer>> HasSequencer for T {}
|
||||||
|
|
@ -40,7 +103,7 @@ mod app {
|
||||||
impl Draw<TuiOut> for App {
|
impl Draw<TuiOut> for App {
|
||||||
fn draw (&self, to: &mut TuiOut) {
|
fn draw (&self, to: &mut TuiOut) {
|
||||||
if let Some(e) = self.error.read().unwrap().as_ref() {
|
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() {
|
for (index, dsl) in self.mode.view.iter().enumerate() {
|
||||||
if let Err(e) = self.understand(to, dsl) {
|
if let Err(e) = self.understand(to, dsl) {
|
||||||
|
|
@ -51,7 +114,6 @@ mod app {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<'a> Namespace<'a, AppCommand> for App {
|
impl<'a> Namespace<'a, AppCommand> for App {
|
||||||
symbols!('a |app| -> AppCommand {
|
symbols!('a |app| -> AppCommand {
|
||||||
"x/inc" => AppCommand::Inc { axis: ControlAxis::X },
|
"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!(MenuItem |self, w| { write!(w, "{}", &self.0) });
|
||||||
impl_debug!(Condition |self, w| { write!(w, "*") });
|
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!(u8: try_to_u8);
|
||||||
primitive!(u16: try_to_u16);
|
primitive!(u16: try_to_u16);
|
||||||
primitive!(usize: try_to_usize);
|
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!(SampleCount);
|
||||||
impl_time_unit!(SampleRate);
|
impl_time_unit!(SampleRate);
|
||||||
impl_time_unit!(Microsecond);
|
impl_time_unit!(Microsecond);
|
||||||
|
|
@ -3495,18 +3506,6 @@ mod pool {
|
||||||
format!("{:>02}", self.ticks()).into()
|
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 {
|
impl Pool {
|
||||||
fn _todo_usize_ (&self) -> usize { todo!() }
|
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