Compare commits

...

4 commits

Author SHA1 Message Date
b4761a9679 deps: tengri 0.13.0 + misc
Some checks are pending
/ build (push) Waiting to run
2025-05-03 02:15:01 +03:00
866327bbe7 expose mode flags for input layers 2025-05-03 02:12:52 +03:00
3fd045cf93 config: embed default configs 2025-05-03 01:51:36 +03:00
d427dc409d config: extract read_and_leak; almost done with layer-if 2025-05-03 01:47:32 +03:00
6 changed files with 182 additions and 72 deletions

59
Cargo.lock generated
View file

@ -166,9 +166,9 @@ checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06"
[[package]] [[package]]
name = "bytemuck" name = "bytemuck"
version = "1.22.0" version = "1.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c"
[[package]] [[package]]
name = "cassowary" name = "cassowary"
@ -471,9 +471,9 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.15.2" version = "0.15.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3"
dependencies = [ dependencies = [
"allocator-api2", "allocator-api2",
"equivalent", "equivalent",
@ -1156,9 +1156,9 @@ dependencies = [
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "1.0.5" version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
dependencies = [ dependencies = [
"bitflags 2.9.0", "bitflags 2.9.0",
"errno", "errno",
@ -1499,9 +1499,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.100" version = "2.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1564,13 +1564,13 @@ dependencies = [
"fastrand", "fastrand",
"getrandom 0.3.2", "getrandom 0.3.2",
"once_cell", "once_cell",
"rustix 1.0.5", "rustix 1.0.7",
"windows-sys 0.59.0", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
name = "tengri" name = "tengri"
version = "0.12.0" version = "0.13.0"
dependencies = [ dependencies = [
"tengri_dsl", "tengri_dsl",
"tengri_input", "tengri_input",
@ -1580,7 +1580,7 @@ dependencies = [
[[package]] [[package]]
name = "tengri_dsl" name = "tengri_dsl"
version = "0.12.0" version = "0.13.0"
dependencies = [ dependencies = [
"itertools 0.14.0", "itertools 0.14.0",
"konst", "konst",
@ -1589,21 +1589,21 @@ dependencies = [
[[package]] [[package]]
name = "tengri_input" name = "tengri_input"
version = "0.12.0" version = "0.13.0"
dependencies = [ dependencies = [
"tengri_dsl", "tengri_dsl",
] ]
[[package]] [[package]]
name = "tengri_output" name = "tengri_output"
version = "0.12.0" version = "0.13.0"
dependencies = [ dependencies = [
"tengri_dsl", "tengri_dsl",
] ]
[[package]] [[package]]
name = "tengri_tui" name = "tengri_tui"
version = "0.12.0" version = "0.13.0"
dependencies = [ dependencies = [
"atomic_float", "atomic_float",
"better-panic", "better-panic",
@ -1661,9 +1661,9 @@ dependencies = [
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.8.20" version = "0.8.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae"
dependencies = [ dependencies = [
"serde", "serde",
"serde_spanned", "serde_spanned",
@ -1673,26 +1673,33 @@ dependencies = [
[[package]] [[package]]
name = "toml_datetime" name = "toml_datetime"
version = "0.6.8" version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3"
dependencies = [ dependencies = [
"serde", "serde",
] ]
[[package]] [[package]]
name = "toml_edit" name = "toml_edit"
version = "0.22.24" version = "0.22.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"serde", "serde",
"serde_spanned", "serde_spanned",
"toml_datetime", "toml_datetime",
"toml_write",
"winnow", "winnow",
] ]
[[package]]
name = "toml_write"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076"
[[package]] [[package]]
name = "typewit" name = "typewit"
version = "1.11.0" version = "1.11.0"
@ -1974,9 +1981,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.7.6" version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10" checksum = "d9fb597c990f03753e08d3c29efbfcf2019a003b4bf4ba19225c158e1549f0f3"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
@ -1992,18 +1999,18 @@ dependencies = [
[[package]] [[package]]
name = "zerocopy" name = "zerocopy"
version = "0.8.24" version = "0.8.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb"
dependencies = [ dependencies = [
"zerocopy-derive", "zerocopy-derive",
] ]
[[package]] [[package]]
name = "zerocopy-derive" name = "zerocopy-derive"
version = "0.8.24" version = "0.8.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View file

@ -8,7 +8,24 @@ macro_rules! cmd { ($cmd:expr) => {{ $cmd; None }}; }
macro_rules! cmd_todo { ($msg:literal) => {{ println!($msg); None }}; } macro_rules! cmd_todo { ($msg:literal) => {{ println!($msg); None }}; }
expose!([self: Tek] expose!([self: Tek]
([bool]) ([bool]
(":mode-editor" self.is_editing())
(":mode-clip" !self.is_editing() && self.selected.is_clip())
(":mode-track" !self.is_editing() && self.selected.is_track())
(":mode-scene" !self.is_editing() && self.selected.is_scene())
(":mode-mix" !self.is_editing() && self.selected.is_mix())
(":mode-pool-import" matches!(
self.pool.as_ref().map(|p|p.mode.as_ref()).flatten(),
Some(PoolMode::Import(..))))
(":mode-pool-export" matches!(
self.pool.as_ref().map(|p|p.mode.as_ref()).flatten(),
Some(PoolMode::Export(..))))
(":mode-pool-rename" matches!(
self.pool.as_ref().map(|p|p.mode.as_ref()).flatten(),
Some(PoolMode::Rename(..))))
(":mode-pool-length" matches!(
self.pool.as_ref().map(|p|p.mode.as_ref()).flatten(),
Some(PoolMode::Length(..)))))
([isize]) ([isize])
([Color]) ([Color])
([Arc<RwLock<MidiClip>>]) ([Arc<RwLock<MidiClip>>])

View file

@ -1,8 +1,11 @@
use crate::*; use crate::*;
use std::path::PathBuf;
/// Configuration /// Configuration
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct Configuration { pub struct Configuration {
/// Path of configuration entrypoint
pub path: PathBuf,
/// Name of configuration /// Name of configuration
pub name: Option<Arc<str>>, pub name: Option<Arc<str>>,
/// Description of configuration /// Description of configuration
@ -14,20 +17,19 @@ pub struct Configuration {
} }
impl Configuration { impl Configuration {
pub fn from_file (path: &impl AsRef<Path>, _watch: bool) -> Usually<Self> {
Self::from_source(String::from_utf8(std::fs::read(path.as_ref())?)?) pub fn new (path: &impl AsRef<Path>, _watch: bool) -> Usually<Self> {
} let text = read_and_leak(path.as_ref())?;
pub fn from_source (source: impl AsRef<str> + 'static) -> Usually<Self> { let [name, info, view, keys] = Self::parse(TokenIter::from(text))?;
let source: Box<str> = source.as_ref().into();
let source: &'static str = Box::leak(source);
let [name, info, view, keys] = Self::parse(TokenIter::from(source.as_ref()))?;
Ok(Self { Ok(Self {
path: path.as_ref().into(),
info: info.map(Self::parse_info).flatten(), info: info.map(Self::parse_info).flatten(),
name: name.map(Self::parse_name).flatten(), name: name.map(Self::parse_name).flatten(),
view: Self::parse_view(view)?, view: Self::parse_view(view)?,
keys: Self::parse_keys(keys)?, keys: Self::parse_keys(&path, keys)?,
}) })
} }
fn parse (iter: TokenIter) -> Usually<[Option<TokenIter>;4]> { fn parse (iter: TokenIter) -> Usually<[Option<TokenIter>;4]> {
let mut name: Option<TokenIter> = None; let mut name: Option<TokenIter> = None;
let mut info: Option<TokenIter> = None; let mut info: Option<TokenIter> = None;
@ -59,6 +61,7 @@ impl Configuration {
} }
Ok([name, info, view, keys]) Ok([name, info, view, keys])
} }
fn parse_info (mut iter: TokenIter) -> Option<Arc<str>> { fn parse_info (mut iter: TokenIter) -> Option<Arc<str>> {
iter.next().and_then(|x|if let Value::Str(x) = x.value { iter.next().and_then(|x|if let Value::Str(x) = x.value {
Some(x.into()) Some(x.into())
@ -66,6 +69,7 @@ impl Configuration {
None None
}) })
} }
fn parse_name (mut iter: TokenIter) -> Option<Arc<str>> { fn parse_name (mut iter: TokenIter) -> Option<Arc<str>> {
iter.next().and_then(|x|if let Value::Str(x) = x.value { iter.next().and_then(|x|if let Value::Str(x) = x.value {
Some(x.into()) Some(x.into())
@ -73,6 +77,7 @@ impl Configuration {
None None
}) })
} }
fn parse_view (iter: Option<TokenIter>) -> Usually<TokenIter> { fn parse_view (iter: Option<TokenIter>) -> Usually<TokenIter> {
if let Some(view) = iter { if let Some(view) = iter {
Ok(view) Ok(view)
@ -80,36 +85,114 @@ impl Configuration {
Err(format!("missing view definition").into()) Err(format!("missing view definition").into())
} }
} }
fn parse_keys (iter: Option<TokenIter>)
fn parse_keys (base: &impl AsRef<Path>, iter: Option<TokenIter<'static>>)
-> Usually<InputMap<'static, Tek, TekCommand, TuiIn, TokenIter<'static>>> -> Usually<InputMap<'static, Tek, TekCommand, TuiIn, TokenIter<'static>>>
{ {
if let Some(mut keys) = iter { if iter.is_none() {
return Err(format!("missing keys definition").into())
}
let mut keys = iter.unwrap();
let mut map = InputMap::default(); let mut map = InputMap::default();
while let Some(token) = keys.next() { while let Some(token) = keys.next() {
match token.value { if let Value::Exp(_, mut exp) = token.value {
Value::Exp(_, mut exp) => {
let next = exp.next(); let next = exp.next();
match next { if let Some(Token { value: Value::Key(sym), .. }) = next {
Some(Token { value: Value::Key(sym), .. }) => match sym { match sym {
"layer" => { todo!() }, "layer" => {
"layer-if" => { todo!() }, let next = exp.next();
_ => return Err( if let Some(Token { value: Value::Str(path), .. }) = next {
format!("(e3) unexpected symbol {sym:?}").into() let path = base.as_ref().parent().unwrap().join(unquote(path));
) if !std::fs::exists(&path)? {
return Err(format!("(e5) not found: {path:?}").into())
} }
_ => return Err( map.add_layer(read_and_leak(path)?.into());
format!("(e2) unexpected exp {:?}", next.map(|x|x.value)).into() } else {
) return Err(format!("(e4) unexpected non-string {next:?}").into())
} }
}, },
t => return Err(
format!("(e1) unexpected token {token:?}").into() "layer-if" => {
) let mut cond = None;
let next = exp.next();
if let Some(Token { value: Value::Sym(sym), .. }) = next {
cond = Some(leak(sym));
} else {
return Err(format!("(e4) unexpected non-symbol {next:?}").into())
};
let next = exp.next();
if let Some(Token { value: Value::Str(path), .. }) = next {
let path = base.as_ref().parent().unwrap().join(unquote(path));
if !std::fs::exists(&path)? {
return Err(format!("(e5) not found: {path:?}").into())
}
print!("{path:?}...");
let keys = read_and_leak(path)?.into();
println!("ok");
let cond = cond.unwrap();
map.add_layer_if(
Box::new(|state|{
Context::get(state, &Value::Sym(cond)).unwrap_or(false)
}),
keys
);
} else {
return Err(format!("(e4) unexpected non-symbol {next:?}").into())
}
},
_ => return Err(format!("(e3) unexpected symbol {sym:?}").into())
}
} else {
return Err(format!("(e2) unexpected exp {:?}", next.map(|x|x.value)).into())
}
} else {
return Err(format!("(e1) unexpected token {token:?}").into())
} }
} }
Ok(map) Ok(map)
} else {
return Err(format!("missing keys definition").into())
} }
} }
fn read_and_leak (path: impl AsRef<Path>) -> Usually<&'static str> {
Ok(leak(String::from_utf8(std::fs::read(path.as_ref())?)?))
} }
fn leak (x: impl AsRef<str>) -> &'static str {
Box::leak(x.as_ref().into())
}
fn unquote (x: &str) -> &str {
let mut chars = x.chars();
chars.next();
//chars.next_back();
chars.as_str()
}
macro_rules! default_config { ($path:literal) => { ($path, include_str!($path)) }; }
pub const DEFAULT_CONFIGS: &'static [(&'static str, &'static str)] = &[
default_config!("../../../config/config_arranger.edn"),
default_config!("../../../config/config_groovebox.edn"),
default_config!("../../../config/config_sampler.edn"),
default_config!("../../../config/config_sequencer.edn"),
default_config!("../../../config/config_transport.edn"),
default_config!("../../../config/keys_arranger.edn"),
default_config!("../../../config/keys_clip.edn"),
default_config!("../../../config/keys_clip_length.edn"),
default_config!("../../../config/keys_clip_rename.edn"),
default_config!("../../../config/keys_clock.edn"),
default_config!("../../../config/keys_editor.edn"),
default_config!("../../../config/keys_global.edn"),
default_config!("../../../config/keys_groovebox.edn"),
default_config!("../../../config/keys_mix.edn"),
default_config!("../../../config/keys_pool.edn"),
default_config!("../../../config/keys_pool_file.edn"),
default_config!("../../../config/keys_sampler.edn"),
default_config!("../../../config/keys_scene.edn"),
default_config!("../../../config/keys_sequencer.edn"),
default_config!("../../../config/keys_track.edn"),
];

View file

@ -15,6 +15,7 @@
#![feature(trait_alias)] #![feature(trait_alias)]
#![feature(type_changing_struct_update)] #![feature(type_changing_struct_update)]
#![feature(let_chains)] #![feature(let_chains)]
#![feature(closure_lifetime_binder)]
/// Standard result type. /// Standard result type.
pub type Usually<T> = std::result::Result<T, Box<dyn std::error::Error>>; pub type Usually<T> = std::result::Result<T, Box<dyn std::error::Error>>;
/// Standard optional result type. /// Standard optional result type.

View file

@ -100,7 +100,16 @@ impl Cli {
for (index, connect) in midi_tos.iter().enumerate() { for (index, connect) in midi_tos.iter().enumerate() {
let port = JackMidiOut::new(jack, &format!("{index}/M"), &[connect.clone()])?; let port = JackMidiOut::new(jack, &format!("{index}/M"), &[connect.clone()])?;
midi_outs.push(port); midi_outs.push(port);
} };
let config_path = match mode {
LaunchMode::Clock => "config/config_transport.edn",
LaunchMode::Sequencer => "config/config_sequencer.edn",
LaunchMode::Groovebox => "config/config_groovebox.edn",
LaunchMode::Arranger { .. } => "config/config_arranger.edn",
LaunchMode::Sampler => "config/config_sampler.edn",
_ => todo!("{mode:?}"),
};
let config = Configuration::new(&config_path, false)?;
let mut app = Tek { let mut app = Tek {
jack: jack.clone(), jack: jack.clone(),
color: ItemTheme::random(), color: ItemTheme::random(),
@ -139,14 +148,7 @@ impl Cli {
}, },
scenes, scenes,
selected: Selection::TrackClip { track: 0, scene: 0 }, selected: Selection::TrackClip { track: 0, scene: 0 },
config: Configuration::from_file(match mode { config,
LaunchMode::Clock => &"config/config_transport.edn",
LaunchMode::Sequencer => &"config/config_sequencer.edn",
LaunchMode::Groovebox => &"config/config_groovebox.edn",
LaunchMode::Arranger { .. } => &"config/config_arranger.edn",
LaunchMode::Sampler => &"config/config_sampler.edn",
_ => todo!("{mode:?}"),
}, false)?,
..Default::default() ..Default::default()
}; };
if let &LaunchMode::Arranger { scenes, tracks, track_width, .. } = mode { if let &LaunchMode::Arranger { scenes, tracks, track_width, .. } = mode {

2
deps/tengri vendored

@ -1 +1 @@
Subproject commit 0d4ba4a54ef0528a0a45b58e21a1e4aa7ed5eaf9 Subproject commit 21f7f6b38afc966b7b45af442935d48c8c5067d3