mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
wip: adding edn parsing to mixer track
This commit is contained in:
parent
10f191282e
commit
a819e042c7
9 changed files with 89 additions and 74 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -2536,6 +2536,7 @@ dependencies = [
|
|||
"backtrace",
|
||||
"better-panic",
|
||||
"clap",
|
||||
"clojure-reader",
|
||||
"crossterm",
|
||||
"midly",
|
||||
"ratatui",
|
||||
|
|
|
|||
|
|
@ -41,12 +41,12 @@ fn handle_focused (state: &mut App, e: &AppEvent) -> Usually<bool> {
|
|||
AppFocus::Transport => state.transport.handle(e),
|
||||
AppFocus::Arranger => state.arranger.sequencer.handle(e),
|
||||
AppFocus::Sequencer => state.arranger.sequencer.handle(e),
|
||||
AppFocus::Chain => Ok(if state.entered {
|
||||
AppFocus::Chain => Ok(false)/*if state.entered {
|
||||
handle_device(state, e)? ||
|
||||
handle_keymap(state, e, crate::control::KEYMAP_CHAIN)?
|
||||
} else {
|
||||
handle_keymap(state, e, crate::control::KEYMAP_CHAIN)? || handle_device(state, e)?
|
||||
})
|
||||
})*/
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,10 +69,10 @@ impl App {
|
|||
}
|
||||
},
|
||||
Some(Edn::Symbol("scene")) => {
|
||||
Scene::load_edn(self, &items[1..])?;
|
||||
tek_sequencer::Scene::load_edn(self, &items[1..])?;
|
||||
},
|
||||
Some(Edn::Symbol("track")) => {
|
||||
Track::load_edn(self, &items[1..])?;
|
||||
tek_mixer::Track::load_edn(self, &items[1..])?;
|
||||
},
|
||||
Some(Edn::Symbol("midi-in")) => {
|
||||
self.midi_ins = items[1..].iter().map(|x|match x {
|
||||
|
|
@ -107,75 +107,6 @@ impl App {
|
|||
}
|
||||
}
|
||||
|
||||
impl Scene {
|
||||
fn load_edn <'a, 'e> (app: &'a mut App, args: &[Edn<'e>]) -> Usually<&'a mut Self> {
|
||||
let mut name = None;
|
||||
let mut clips = vec![];
|
||||
edn!(edn in args {
|
||||
Edn::Map(map) => {
|
||||
let key = map.get(&Edn::Key(":name"));
|
||||
if let Some(Edn::Str(n)) = key {
|
||||
name = Some(*n);
|
||||
} else {
|
||||
panic!("unexpected key in scene '{name:?}': {key:?}")
|
||||
}
|
||||
},
|
||||
Edn::Symbol("_") => {
|
||||
clips.push(None);
|
||||
},
|
||||
Edn::Int(i) => {
|
||||
clips.push(Some(*i as usize));
|
||||
},
|
||||
_ => panic!("unexpected in scene '{name:?}': {edn:?}")
|
||||
});
|
||||
let scene = app.arranger.scene_add(name)?;
|
||||
scene.clips = clips;
|
||||
Ok(scene)
|
||||
}
|
||||
}
|
||||
|
||||
impl Track {
|
||||
fn load_edn <'a, 'e> (app: &'a mut App, args: &[Edn<'e>]) -> Usually<&'a mut Self> {
|
||||
let ppq = app.transport.ppq();
|
||||
let mut name = None;
|
||||
let mut _gain = 0.0f64;
|
||||
let mut devices: Vec<JackDevice> = vec![];
|
||||
let mut phrases: Vec<Phrase> = vec![];
|
||||
edn!(edn in args {
|
||||
Edn::Map(map) => {
|
||||
if let Some(Edn::Str(n)) = map.get(&Edn::Key(":name")) {
|
||||
name = Some(*n);
|
||||
}
|
||||
if let Some(Edn::Double(g)) = map.get(&Edn::Key(":gain")) {
|
||||
_gain = f64::from(*g)
|
||||
}
|
||||
},
|
||||
Edn::List(args) => match args.get(0) {
|
||||
Some(Edn::Symbol("phrase")) => {
|
||||
phrases.push(Phrase::load_edn(ppq, &args[1..])?)
|
||||
},
|
||||
Some(Edn::Symbol("sampler")) => {
|
||||
devices.push(Sampler::load_edn(&args[1..])?)
|
||||
},
|
||||
Some(Edn::Symbol("lv2")) => {
|
||||
devices.push(LV2Plugin::load_edn(&args[1..])?)
|
||||
},
|
||||
None => panic!("empty list track {}",
|
||||
name.unwrap_or("")
|
||||
),
|
||||
_ => panic!("unexpected in track {}: {:?}",
|
||||
name.unwrap_or(""),
|
||||
args.get(0).unwrap()
|
||||
)
|
||||
},
|
||||
_ => {}
|
||||
});
|
||||
let track = app.arranger.track_add(name)?;
|
||||
for phrase in phrases { track.phrases.push(Arc::new(RwLock::new(phrase))); }
|
||||
for device in devices { track.add_device(device)?; }
|
||||
Ok(track)
|
||||
}
|
||||
}
|
||||
|
||||
impl Phrase {
|
||||
fn load_edn <'e> (ppq: usize, args: &[Edn<'e>]) -> Usually<Self> {
|
||||
|
|
|
|||
|
|
@ -11,3 +11,4 @@ toml = "0.8.12"
|
|||
better-panic = "0.3.0"
|
||||
midly = "0.5"
|
||||
clap = { version = "4.5.4", features = [ "derive" ] }
|
||||
clojure-reader = "0.1.0"
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ pub use std::collections::BTreeMap;
|
|||
pub use crossterm::event::{Event, KeyEvent, KeyCode, KeyModifiers};
|
||||
pub use ratatui::prelude::{Rect, Style, Color, Buffer};
|
||||
pub use ratatui::style::Stylize;
|
||||
pub use clojure_reader::{edn::{read, Edn}, error::Error as EdnError};
|
||||
|
||||
pub(crate) use std::error::Error;
|
||||
pub(crate) use std::io::{stdout};
|
||||
|
|
@ -42,6 +43,18 @@ submod! {
|
|||
exit render handle
|
||||
}
|
||||
|
||||
/// EDN parsing helper.
|
||||
#[macro_export] macro_rules! edn {
|
||||
($edn:ident { $($pat:pat => $expr:expr),* $(,)? }) => {
|
||||
match $edn { $($pat => $expr),* }
|
||||
};
|
||||
($edn:ident in $args:ident { $($pat:pat => $expr:expr),* $(,)? }) => {
|
||||
for $edn in $args {
|
||||
edn!($edn { $($pat => $expr),* })
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Standard result type.
|
||||
pub type Usually<T> = Result<T, Box<dyn Error>>;
|
||||
|
||||
|
|
|
|||
12
crates/tek_mixer/example.edn
Normal file
12
crates/tek_mixer/example.edn
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
(mixer
|
||||
(track
|
||||
(name "Drums")
|
||||
(sampler
|
||||
(dir "/home/user/Lab/Music/pak")
|
||||
(sample (midi 34) (name "808 D") (file "808.wav"))))
|
||||
(track
|
||||
(name "Lead")
|
||||
(lv2
|
||||
(name "Odin2")
|
||||
(path "file:///home/user/.lv2/Odin2.lv2"))
|
||||
(gain 0.0)))
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::*;
|
||||
use tek_core::edn;
|
||||
|
||||
/// TODO: A track in the mixer. (Integrate with [crate::model::Track]?)
|
||||
pub struct MixerTrack {
|
||||
|
|
@ -52,6 +53,44 @@ impl MixerTrack {
|
|||
}
|
||||
}
|
||||
|
||||
impl MixerTrack {
|
||||
fn load_edn <'a, 'e> (app: &'a mut App, args: &[Edn<'e>]) -> Usually<&'a mut Self> {
|
||||
let ppq = app.transport.ppq();
|
||||
let mut name = None;
|
||||
let mut _gain = 0.0f64;
|
||||
let mut devices: Vec<JackDevice> = vec![];
|
||||
edn!(edn in args {
|
||||
Edn::Map(map) => {
|
||||
if let Some(Edn::Str(n)) = map.get(&Edn::Key(":name")) {
|
||||
name = Some(*n);
|
||||
}
|
||||
if let Some(Edn::Double(g)) = map.get(&Edn::Key(":gain")) {
|
||||
_gain = f64::from(*g)
|
||||
}
|
||||
},
|
||||
Edn::List(args) => match args.get(0) {
|
||||
Some(Edn::Symbol("sampler")) => {
|
||||
devices.push(Sampler::load_edn(&args[1..])?)
|
||||
},
|
||||
Some(Edn::Symbol("lv2")) => {
|
||||
devices.push(LV2Plugin::load_edn(&args[1..])?)
|
||||
},
|
||||
None => panic!("empty list track {}",
|
||||
name.unwrap_or("")
|
||||
),
|
||||
_ => panic!("unexpected in track {}: {:?}",
|
||||
name.unwrap_or(""),
|
||||
args.get(0).unwrap()
|
||||
)
|
||||
},
|
||||
_ => {}
|
||||
});
|
||||
let track = app.arranger.track_add(name)?;
|
||||
for device in devices { track.add_device(device)?; }
|
||||
Ok(track)
|
||||
}
|
||||
}
|
||||
|
||||
//impl<W: Write> Input<TUI<W>, bool> for Mixer {
|
||||
//fn handle (&mut self, engine: &mut TUI<W>) -> Result<Option<bool>> {
|
||||
//Ok(None)
|
||||
|
|
|
|||
18
crates/tek_sequencer/example.edn
Normal file
18
crates/tek_sequencer/example.edn
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
(arranger
|
||||
(track
|
||||
(name "Drums")
|
||||
(phrase
|
||||
(name "4 kicks")
|
||||
(beats 4)
|
||||
(steps 16)
|
||||
(:00 (36 128))
|
||||
(:04 (36 100))
|
||||
(:08 (36 100))
|
||||
(:12 (36 100))))
|
||||
(track
|
||||
(name "Bass")
|
||||
(phrase
|
||||
(beats 4)
|
||||
(steps 16)
|
||||
(:04 (36 100))
|
||||
(:12 (36 100)))))
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::*;
|
||||
|
||||
impl Scene {
|
||||
fn load_edn <'a, 'e> (app: &'a mut App, args: &[Edn<'e>]) -> Usually<&'a mut Self> {
|
||||
pub fn load_edn <'a, 'e> (app: &'a mut App, args: &[Edn<'e>]) -> Usually<&'a mut Self> {
|
||||
let mut name = None;
|
||||
let mut clips = vec![];
|
||||
edn!(edn in args {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue