mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +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",
|
"backtrace",
|
||||||
"better-panic",
|
"better-panic",
|
||||||
"clap",
|
"clap",
|
||||||
|
"clojure-reader",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
"midly",
|
"midly",
|
||||||
"ratatui",
|
"ratatui",
|
||||||
|
|
|
||||||
|
|
@ -41,12 +41,12 @@ fn handle_focused (state: &mut App, e: &AppEvent) -> Usually<bool> {
|
||||||
AppFocus::Transport => state.transport.handle(e),
|
AppFocus::Transport => state.transport.handle(e),
|
||||||
AppFocus::Arranger => state.arranger.sequencer.handle(e),
|
AppFocus::Arranger => state.arranger.sequencer.handle(e),
|
||||||
AppFocus::Sequencer => 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_device(state, e)? ||
|
||||||
handle_keymap(state, e, crate::control::KEYMAP_CHAIN)?
|
handle_keymap(state, e, crate::control::KEYMAP_CHAIN)?
|
||||||
} else {
|
} else {
|
||||||
handle_keymap(state, e, crate::control::KEYMAP_CHAIN)? || handle_device(state, e)?
|
handle_keymap(state, e, crate::control::KEYMAP_CHAIN)? || handle_device(state, e)?
|
||||||
})
|
})*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,10 +69,10 @@ impl App {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(Edn::Symbol("scene")) => {
|
Some(Edn::Symbol("scene")) => {
|
||||||
Scene::load_edn(self, &items[1..])?;
|
tek_sequencer::Scene::load_edn(self, &items[1..])?;
|
||||||
},
|
},
|
||||||
Some(Edn::Symbol("track")) => {
|
Some(Edn::Symbol("track")) => {
|
||||||
Track::load_edn(self, &items[1..])?;
|
tek_mixer::Track::load_edn(self, &items[1..])?;
|
||||||
},
|
},
|
||||||
Some(Edn::Symbol("midi-in")) => {
|
Some(Edn::Symbol("midi-in")) => {
|
||||||
self.midi_ins = items[1..].iter().map(|x|match x {
|
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 {
|
impl Phrase {
|
||||||
fn load_edn <'e> (ppq: usize, args: &[Edn<'e>]) -> Usually<Self> {
|
fn load_edn <'e> (ppq: usize, args: &[Edn<'e>]) -> Usually<Self> {
|
||||||
|
|
|
||||||
|
|
@ -11,3 +11,4 @@ toml = "0.8.12"
|
||||||
better-panic = "0.3.0"
|
better-panic = "0.3.0"
|
||||||
midly = "0.5"
|
midly = "0.5"
|
||||||
clap = { version = "4.5.4", features = [ "derive" ] }
|
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 crossterm::event::{Event, KeyEvent, KeyCode, KeyModifiers};
|
||||||
pub use ratatui::prelude::{Rect, Style, Color, Buffer};
|
pub use ratatui::prelude::{Rect, Style, Color, Buffer};
|
||||||
pub use ratatui::style::Stylize;
|
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::error::Error;
|
||||||
pub(crate) use std::io::{stdout};
|
pub(crate) use std::io::{stdout};
|
||||||
|
|
@ -42,6 +43,18 @@ submod! {
|
||||||
exit render handle
|
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.
|
/// Standard result type.
|
||||||
pub type Usually<T> = Result<T, Box<dyn Error>>;
|
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 crate::*;
|
||||||
|
use tek_core::edn;
|
||||||
|
|
||||||
/// TODO: A track in the mixer. (Integrate with [crate::model::Track]?)
|
/// TODO: A track in the mixer. (Integrate with [crate::model::Track]?)
|
||||||
pub struct MixerTrack {
|
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 {
|
//impl<W: Write> Input<TUI<W>, bool> for Mixer {
|
||||||
//fn handle (&mut self, engine: &mut TUI<W>) -> Result<Option<bool>> {
|
//fn handle (&mut self, engine: &mut TUI<W>) -> Result<Option<bool>> {
|
||||||
//Ok(None)
|
//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::*;
|
use crate::*;
|
||||||
|
|
||||||
impl Scene {
|
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 name = None;
|
||||||
let mut clips = vec![];
|
let mut clips = vec![];
|
||||||
edn!(edn in args {
|
edn!(edn in args {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue