mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
This commit is contained in:
parent
99d9da6ffd
commit
fc038dbd97
10 changed files with 71 additions and 89 deletions
|
|
@ -7,7 +7,7 @@
|
||||||
(@shift-O project output-add)
|
(@shift-O project output-add)
|
||||||
(@shift-S project scene-add)
|
(@shift-S project scene-add)
|
||||||
(@shift-T project track-add)
|
(@shift-T project track-add)
|
||||||
(@shift-D dialog :dialog-device)
|
(@shift-D dialog open :dialog-device)
|
||||||
|
|
||||||
(@up select :select-scene-prev)
|
(@up select :select-scene-prev)
|
||||||
(@down select :select-scene-next)
|
(@down select :select-scene-next)
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ macro_rules! cmd_todo { ($msg:literal) => {{ println!($msg); None }}; }
|
||||||
handle!(TuiIn: |self: App, input|self.handle_tui_key_with_history(input));
|
handle!(TuiIn: |self: App, input|self.handle_tui_key_with_history(input));
|
||||||
impl App {
|
impl App {
|
||||||
fn handle_tui_key_with_history (&mut self, input: &TuiIn) -> Perhaps<bool> {
|
fn handle_tui_key_with_history (&mut self, input: &TuiIn) -> Perhaps<bool> {
|
||||||
Ok(if let Some(command) = self.config.keys.command(self, input) {
|
Ok(if let Some(command) = self.config.keys.keybind_resolve(self, input)? {
|
||||||
// FIXME failed commands not persisted in undo history
|
// FIXME failed commands not persisted in undo history
|
||||||
let undo = command.clone().execute(self)?;
|
let undo = command.clone().execute(self)?;
|
||||||
self.history.push((command, undo));
|
self.history.push((command, undo));
|
||||||
|
|
@ -38,6 +38,7 @@ impl AppCommand {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn dialog (app: &mut App, command: DialogCommand) -> Perhaps<Self> {
|
fn dialog (app: &mut App, command: DialogCommand) -> Perhaps<Self> {
|
||||||
|
panic!("dialog");
|
||||||
Ok(command.delegate(&mut app.dialog, |command|Self::Dialog{command})?)
|
Ok(command.delegate(&mut app.dialog, |command|Self::Dialog{command})?)
|
||||||
}
|
}
|
||||||
fn project (app: &mut App, command: ArrangementCommand) -> Perhaps<Self> {
|
fn project (app: &mut App, command: ArrangementCommand) -> Perhaps<Self> {
|
||||||
|
|
@ -111,33 +112,10 @@ impl AppCommand {
|
||||||
//Ok(None)
|
//Ok(None)
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
impl<'state> Context<'state, ClockCommand> for App {
|
|
||||||
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<ClockCommand> {
|
dsl!(ClockCommand: |self: App, iter|self.clock().take(iter));
|
||||||
Context::get(&self.clock(), iter)
|
dsl!(MidiEditCommand: |self: App, iter|Ok(self.editor().map(|x|x.take(iter)).transpose()?.flatten()));
|
||||||
}
|
dsl!(PoolCommand: |self: App, iter|self.pool.take(iter));
|
||||||
}
|
dsl!(SamplerCommand: |self: App, iter|Ok(self.project.sampler().map(|x|x.take(iter)).transpose()?.flatten()));
|
||||||
impl<'state> Context<'state, MidiEditCommand> for App {
|
dsl!(ArrangementCommand: |self: App, iter|self.project.take(iter));
|
||||||
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<MidiEditCommand> {
|
dsl!(DialogCommand: |self: App, iter|Dsl::take(&self.dialog, iter));
|
||||||
self.editor().map(|e|Context::get(e, iter)).flatten()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'state> Context<'state, PoolCommand> for App {
|
|
||||||
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<PoolCommand> {
|
|
||||||
Context::get(&self.pool, iter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'state> Context<'state, SamplerCommand> for App {
|
|
||||||
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<SamplerCommand> {
|
|
||||||
self.project.sampler().map(|p|Context::get(p, iter)).flatten()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'state> Context<'state, ArrangementCommand> for App {
|
|
||||||
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<ArrangementCommand> {
|
|
||||||
Context::get(&self.project, iter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'state> Context<'state, DialogCommand> for App {
|
|
||||||
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<DialogCommand> {
|
|
||||||
Context::get(&self, iter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -332,7 +332,7 @@ pub struct Configuration {
|
||||||
/// View definition
|
/// View definition
|
||||||
pub view: TokenIter<'static>,
|
pub view: TokenIter<'static>,
|
||||||
// Input keymap
|
// Input keymap
|
||||||
pub keys: InputMap<'static, App, AppCommand, TuiIn, TokenIter<'static>>,
|
pub keys: InputMap<App, AppCommand, TuiIn, TokenIter<'static>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Configuration {
|
impl Configuration {
|
||||||
|
|
@ -406,7 +406,7 @@ impl Configuration {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_keys (base: &impl AsRef<Path>, iter: Option<TokenIter<'static>>)
|
fn parse_keys (base: &impl AsRef<Path>, iter: Option<TokenIter<'static>>)
|
||||||
-> Usually<InputMap<'static, App, AppCommand, TuiIn, TokenIter<'static>>>
|
-> Usually<InputMap<App, AppCommand, TuiIn, TokenIter<'static>>>
|
||||||
{
|
{
|
||||||
if iter.is_none() {
|
if iter.is_none() {
|
||||||
return Err(format!("missing keys definition").into())
|
return Err(format!("missing keys definition").into())
|
||||||
|
|
@ -435,15 +435,13 @@ impl Configuration {
|
||||||
"layer-if" => {
|
"layer-if" => {
|
||||||
let mut cond = None;
|
let mut cond = None;
|
||||||
|
|
||||||
let next = exp.next();
|
if let Some(Token { value: Value::Sym(sym), .. }) = exp.next() {
|
||||||
if let Some(Token { value: Value::Sym(sym), .. }) = next {
|
|
||||||
cond = Some(leak(sym));
|
cond = Some(leak(sym));
|
||||||
} else {
|
} else {
|
||||||
return Err(format!("(e4) unexpected non-symbol {next:?}").into())
|
return Err(format!("(e4) unexpected non-symbol {next:?}").into())
|
||||||
};
|
};
|
||||||
|
|
||||||
let token = exp.peek();
|
if let Some(Token { value: Value::Str(path), .. }) = exp.peek() {
|
||||||
if let Some(Token { value: Value::Str(path), .. }) = token {
|
|
||||||
let path = base.as_ref().parent().unwrap().join(unquote(path));
|
let path = base.as_ref().parent().unwrap().join(unquote(path));
|
||||||
if !std::fs::exists(&path)? {
|
if !std::fs::exists(&path)? {
|
||||||
return Err(format!("(e5) not found: {path:?}").into())
|
return Err(format!("(e5) not found: {path:?}").into())
|
||||||
|
|
@ -454,13 +452,10 @@ impl Configuration {
|
||||||
let cond = cond.unwrap();
|
let cond = cond.unwrap();
|
||||||
println!("ok");
|
println!("ok");
|
||||||
map.add_layer_if(
|
map.add_layer_if(
|
||||||
Box::new(move |state: &App|{
|
Box::new(move |state: &App|Dsl::take_or_fail(
|
||||||
Context::get(state,
|
state, &mut exp.clone(),
|
||||||
&mut format!("{cond}").as_str().into())
|
format!("missing input layer conditional")
|
||||||
.unwrap_or_else(||panic!(
|
)), keys
|
||||||
"missing input layer conditional {cond} from {exp:?}"))
|
|
||||||
}),
|
|
||||||
keys
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return Err(format!("(e4) unexpected non-symbol {next:?}").into())
|
return Err(format!("(e4) unexpected non-symbol {next:?}").into())
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,13 @@ impl Arrangement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dsl!(TrackCommand: |self: Arrangement, iter|self.take(iter));
|
||||||
|
dsl!(MidiInputCommand: |self: Arrangement, iter|self.take(iter));
|
||||||
|
dsl!(MidiOutputCommand: |self: Arrangement, iter|self.take(iter));
|
||||||
|
dsl!(DeviceCommand: |self: Arrangement, iter|self.take(iter));
|
||||||
|
dsl!(SceneCommand: |self: Arrangement, iter|self.take(iter));
|
||||||
|
dsl!(ClipCommand: |self: Arrangement, iter|self.take(iter));
|
||||||
|
|
||||||
#[tengri_proc::command(Arrangement)]
|
#[tengri_proc::command(Arrangement)]
|
||||||
impl ArrangementCommand {
|
impl ArrangementCommand {
|
||||||
fn home (arranger: &mut Arrangement) -> Perhaps<Self> {
|
fn home (arranger: &mut Arrangement) -> Perhaps<Self> {
|
||||||
|
|
@ -243,39 +250,3 @@ impl ArrangementCommand {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'state> Context<'state, TrackCommand> for Arrangement {
|
|
||||||
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<TrackCommand> {
|
|
||||||
Context::get(&self, iter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'state> Context<'state, MidiInputCommand> for Arrangement {
|
|
||||||
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<MidiInputCommand> {
|
|
||||||
Context::get(&self, iter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'state> Context<'state, MidiOutputCommand> for Arrangement {
|
|
||||||
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<MidiOutputCommand> {
|
|
||||||
Context::get(&self, iter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'state> Context<'state, DeviceCommand> for Arrangement {
|
|
||||||
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<DeviceCommand> {
|
|
||||||
Context::get(&self, iter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'state> Context<'state, SceneCommand> for Arrangement {
|
|
||||||
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<SceneCommand> {
|
|
||||||
Context::get(&self, iter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'state> Context<'state, ClipCommand> for Arrangement {
|
|
||||||
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<ClipCommand> {
|
|
||||||
Context::get(&self, iter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,47 @@ use crate::*;
|
||||||
|
|
||||||
#[tengri_proc::command(Option<Dialog>)]
|
#[tengri_proc::command(Option<Dialog>)]
|
||||||
impl DialogCommand {
|
impl DialogCommand {
|
||||||
fn dismiss (dialog: &mut Option<Dialog>) -> Perhaps<Self> {
|
fn open (dialog: &mut Option<Dialog>, new: Dialog) -> Perhaps<Self> {
|
||||||
|
*dialog = Some(new);
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
fn close (dialog: &mut Option<Dialog>) -> Perhaps<Self> {
|
||||||
*dialog = None;
|
*dialog = None;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//#[derive(Clone, Debug)]
|
||||||
|
//pub enum DialogCommand {
|
||||||
|
//Open { dialog: Dialog },
|
||||||
|
//Close
|
||||||
|
//}
|
||||||
|
|
||||||
|
//impl Command<Option<Dialog>> for DialogCommand {
|
||||||
|
//fn execute (self, state: &mut Option<Dialog>) -> Perhaps<Self> {
|
||||||
|
//match self {
|
||||||
|
//Self::Open { dialog } => {
|
||||||
|
//*state = Some(dialog);
|
||||||
|
//},
|
||||||
|
//Self::Close => {
|
||||||
|
//*state = None;
|
||||||
|
//}
|
||||||
|
//};
|
||||||
|
//Ok(None)
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
||||||
|
//dsl!(DialogCommand: |self: Dialog, iter|todo!());
|
||||||
|
//Dsl::take(&mut self.dialog, iter));
|
||||||
|
|
||||||
|
//#[tengri_proc::command(Option<Dialog>)]//Nope.
|
||||||
|
//impl DialogCommand {
|
||||||
|
//fn open (dialog: &mut Option<Dialog>, new: Dialog) -> Perhaps<Self> {
|
||||||
|
//*dialog = Some(new);
|
||||||
|
//Ok(None)
|
||||||
|
//}
|
||||||
|
//fn close (dialog: &mut Option<Dialog>) -> Perhaps<Self> {
|
||||||
|
//*dialog = None;
|
||||||
|
//Ok(None)
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
|
||||||
|
|
@ -81,11 +81,8 @@ impl PoolCommand {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'state> Context<'state, BrowserCommand> for Pool {
|
dsl!(BrowserCommand: |self: Pool, iter|Ok(self.browser
|
||||||
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<BrowserCommand> {
|
.as_ref().map(|p|p.take(iter)).transpose()?.flatten()));
|
||||||
self.browser.as_ref().map(|p|Context::get(p, iter)).flatten()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tengri_proc::command(Pool)]
|
#[tengri_proc::command(Pool)]
|
||||||
impl PoolClipCommand {
|
impl PoolClipCommand {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ pub(crate) use std::sync::{Arc, atomic::{AtomicUsize, AtomicBool, Ordering::Rela
|
||||||
pub(crate) use std::fmt::Debug;
|
pub(crate) use std::fmt::Debug;
|
||||||
pub(crate) use std::ops::{Add, Sub, Mul, Div, Rem};
|
pub(crate) use std::ops::{Add, Sub, Mul, Div, Rem};
|
||||||
|
|
||||||
pub(crate) use ::tengri::{from, Usually, Perhaps, Has, has, maybe_has, tui::*};
|
pub(crate) use ::tengri::{from, Usually, Perhaps, Has, has, maybe_has, tui::*, dsl::*};
|
||||||
|
|
||||||
pub use ::atomic_float; pub(crate) use atomic_float::*;
|
pub use ::atomic_float; pub(crate) use atomic_float::*;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ impl JackMidiIn {
|
||||||
|
|
||||||
#[tengri_proc::command(JackMidiIn)]
|
#[tengri_proc::command(JackMidiIn)]
|
||||||
impl MidiInputCommand {
|
impl MidiInputCommand {
|
||||||
|
fn _todo_ (_port: &mut JackMidiIn) -> Perhaps<Self> { Ok(None) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Has<Vec<JackMidiIn>>> HasMidiIns for T {
|
impl<T: Has<Vec<JackMidiIn>>> HasMidiIns for T {
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,7 @@ impl JackPortAutoconnect for JackMidiOut {
|
||||||
|
|
||||||
#[tengri_proc::command(JackMidiOut)]
|
#[tengri_proc::command(JackMidiOut)]
|
||||||
impl MidiOutputCommand {
|
impl MidiOutputCommand {
|
||||||
|
fn _todo_ (_port: &mut JackMidiOut) -> Perhaps<Self> { Ok(None) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Has<Vec<JackMidiOut>>> HasMidiOuts for T {
|
impl<T: Has<Vec<JackMidiOut>>> HasMidiOuts for T {
|
||||||
|
|
|
||||||
2
deps/tengri
vendored
2
deps/tengri
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 3bc739328eed0c8fa67b432c7354c7929ddb505f
|
Subproject commit 90f5699fff48d2e8e0a24c36741a7d4ff771385d
|
||||||
Loading…
Add table
Add a link
Reference in a new issue