From 278b3caad3ea919f02573ed762873fe29f0aafb9 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sun, 11 Aug 2024 09:48:45 +0300 Subject: [PATCH] merge tek_jack into tek_core --- Cargo.lock | 12 +- crates/tek/Cargo.toml | 1 - crates/tek/example.edn | 139 +++++++++++++++++ crates/tek/src/control.rs | 23 +-- crates/tek/src/main.rs | 6 +- crates/tek_core/Cargo.toml | 11 +- .../src/lib.rs => tek_core/src/jack_core.rs} | 143 +++++++++++++----- .../device.rs => tek_core/src/jack_device.rs} | 6 +- .../event.rs => tek_core/src/jack_event.rs} | 4 +- .../ports.rs => tek_core/src/jack_ports.rs} | 4 +- crates/tek_core/src/lib.rs | 8 +- crates/tek_core/src/render.rs | 2 +- crates/tek_core/src/time_tick.rs | 60 -------- crates/tek_jack/Cargo.toml | 8 - crates/tek_jack/README.md | 3 - crates/tek_jack/src/factory.rs | 108 ------------- crates/tek_mixer/Cargo.toml | 3 +- crates/tek_mixer/src/lib.rs | 2 +- crates/tek_sequencer/Cargo.toml | 1 - crates/tek_sequencer/src/arranger_cli.rs | 4 +- crates/tek_sequencer/src/lib.rs | 2 +- demos/project.edn | 139 ----------------- demos/scratch.edn | 52 ------- 23 files changed, 285 insertions(+), 456 deletions(-) create mode 100644 crates/tek/example.edn rename crates/{tek_jack/src/lib.rs => tek_core/src/jack_core.rs} (50%) rename crates/{tek_jack/src/device.rs => tek_core/src/jack_device.rs} (95%) rename crates/{tek_jack/src/event.rs => tek_core/src/jack_event.rs} (98%) rename crates/{tek_jack/src/ports.rs => tek_core/src/jack_ports.rs} (98%) delete mode 100644 crates/tek_jack/Cargo.toml delete mode 100644 crates/tek_jack/README.md delete mode 100644 crates/tek_jack/src/factory.rs delete mode 100644 demos/project.edn delete mode 100644 demos/scratch.edn diff --git a/Cargo.lock b/Cargo.lock index aa487fb5..8d725cf3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2512,7 +2512,6 @@ dependencies = [ "clojure-reader", "microxdg", "tek_core", - "tek_jack", "tek_mixer", "tek_sequencer", ] @@ -2527,20 +2526,13 @@ dependencies = [ "clap", "clojure-reader", "crossterm", + "jack", "midly", "once_cell", "ratatui", "toml", ] -[[package]] -name = "tek_jack" -version = "0.1.0" -dependencies = [ - "jack", - "tek_core", -] - [[package]] name = "tek_mixer" version = "0.1.0" @@ -2549,7 +2541,6 @@ dependencies = [ "suil-rs", "symphonia", "tek_core", - "tek_jack", "vst", "wavers", "winit", @@ -2560,7 +2551,6 @@ name = "tek_sequencer" version = "0.1.0" dependencies = [ "tek_core", - "tek_jack", ] [[package]] diff --git a/crates/tek/Cargo.toml b/crates/tek/Cargo.toml index 893cec66..6964a0f9 100644 --- a/crates/tek/Cargo.toml +++ b/crates/tek/Cargo.toml @@ -8,7 +8,6 @@ clojure-reader = "0.1.0" microxdg = "0.1.2" tek_core = { path = "../tek_core" } -tek_jack = { path = "../tek_jack" } tek_sequencer = { path = "../tek_sequencer" } tek_mixer = { path = "../tek_mixer" } #jack = "0.10" diff --git a/crates/tek/example.edn b/crates/tek/example.edn new file mode 100644 index 00000000..21321dab --- /dev/null +++ b/crates/tek/example.edn @@ -0,0 +1,139 @@ +;(bpm 150) + +;(midi-in "nanoKEY Studio.*capture.*") +;(midi-in "nanoKEY Studio.*capture.*") +;(audio-out "Built-.+:playback_FL", "Built-.+:playback_FR") + +;(scene { :name "Intro" } 0 0 _ _) +;(scene { :name "Hook" } 1 1 0 _) +;(scene { :name "Verse" } 2 2 1 _) +;(scene { :name "Chorus" } 3 3 2 _) +;(scene { :name "Bridge" } _ 4 3 _) +;(scene { :name "Outro" } 4 1 4 _) + +;(track { :name "Drums" :gain +0.0 } + ;(phrase { :name "4 kicks" :beats 4 :steps 16 } + ;(:00 (36 128)) + ;(:04 (36 100)) + ;(:08 (36 100)) + ;(:12 (36 100))) + ;(phrase { :name "5 kicks" :beats 4 :steps 16 } + ;(:00 (36 128)) + ;(:04 (36 100)) + ;(:08 (36 128)) + ;(:12 (36 100)) + ;(:14 (36 110))) + ;(phrase { :name "D Beat" :beats 8 :steps 32 } + ;(:00 (44 70) (36 128) (49 110)) + ;(:02 (44 30)) + ;(:04 (44 80) (40 100)) + ;(:06 (44 50)) + ;(:08 (44 30) (36 100)) + ;(:10 (44 50) (36 100)) + ;(:12 (44 80) (40 100)) + ;(:14 (44 50)) + ;(:15 (36 50)) + ;(:16 (44 60) (36 80)) + ;(:18 (44 60) (36 80)) + ;(:20 (44 60) (40 80)) + ;(:22 (44 60)) + ;(:24 (44 60)) + ;(:26 (44 30) (36 80)) + ;(:27 (44 60)) + ;(:28 (44 60) (40 80)) + ;(:30 (44 60))) + ;(phrase { :name "Garage" :beats 4 :steps 16 } + ;(:00 (44 100) (36 100) (35 100)) + ;(:01 (44 100)) + ;(:02 (44 100) (35 100)) + ;(:03 (44 100)) + ;(:04 (44 100) (40 100)) + ;(:06 (44 100)) + ;(:07 (44 100) (34 100)) + ;(:09 (44 100)) + ;(:10 (44 100)) + ;(:11 (35 100) (36 100)) + ;(:12 (44 100) (40 100)) + ;(:14 (44 100))) + + ;(phrase { :name "Trap Pinging" :beats 8 :steps 96 } + ;(:00 (42 100) (36 100) (34 120) (49 100)) + ;(:01 (42 100)) + ;(:02 (42 100)) + ;(:06 (42 100) (35 80) (36 80) (49 100)) + ;(:07 (42 100)) + ;(:08 (42 100)) + ;(:12 (42 100)) + ;(:15 (39 100) (34 100)) + ;(:18 (42 100)) + ;(:24 (42 100) (38 50) (40 50)) + ;(:27 (42 100) (36 50)) + ;(:30 (42 100)) + ;(:33 (42 100) (36 50) (34 100)) + ;(:36 (42 90)) + ;(:39 (42 80)) + ;(:42 (42 70)) + ;(:45 (42 60)) + + ;(:48 (42 100) (36 100) (34 100)) + ;(:50 (42 100)) + ;(:52 (42 110)) + ;(:54 (46 50) (42 120)) + ;(:56 (42 90)) + ;(:58 (42 100)) + ;(:60 (42 100) (35 100)) + ;(:64 (39 100)) + ;(:66 (42 100) (34 100)) + + ;(:70 (42 100)) + ;(:71 (42 100)) + ;(:72 (42 100) (38 50) (40 50)) + ;(:75 (42 100) (36 50) (34 80)) + ;(:78 (42 100)) + ;(:81 (42 100) (36 50)) + ;(:84 (38 40) (40 50) (34 90)) + ;(:87 (42 90) (35 40)) + ;(:90 (42 70))) + + ;(sampler { :name "DrumKit1" :dir "/home/user/Lab/Music/pak" } + ;(sample { :midi 34 :name "808 D" :file "808.wav" }) + ;(sample { :midi 35 :name "Kick 1" :file "kik.wav" }) + ;(sample { :midi 36 :name "Kick 2" :file "kik2.wav" }) + ;(sample { :midi 37 :name "Rim" :file "rim.wav" }) + ;(sample { :midi 38 :name "Snare 1" :file "sna.wav" }) + ;(sample { :midi 39 :name "Shaker" :file "shk.wav" }) + ;(sample { :midi 40 :name "Snare 2" :file "sna2.wav" }) + ;(sample { :midi 42 :name "Closed HH 1" :file "chh.wav" }) + ;(sample { :midi 44 :name "Closed HH 2" :file "chh2.wav" }) + ;(sample { :midi 45 :name "Open HH 0" :file "ohh.wav" }) + ;(sample { :midi 46 :name "Open HH 1" :file "ohh1.wav" }) + ;(sample { :midi 47 :name "Open HH 2" :file "ohh2.wav" }) + ;(sample { :midi 49 :name "Crash" :file "crs.wav" }))) + +;(track { :name "Bass" :gain +0.0 } + ;(phrase { :name "Bass 1" :beats 4 }) + ;(phrase { :name "Bass 2" :beats 4 }) + ;(phrase { :name "Bass 3" :beats 4 }) + ;(phrase { :name "Bass 4" :beats 4 }) + ;(phrase { :name "Bass 5" :beats 4 }) + ;(phrase { :name "Bass 6" :beats 4 }) + ;(phrase { :name "Bass 7" :beats 4 }) + ;(phrase { :name "Bass 8" :beats 4 }) + ;(lv2 { + ;:name "Odin2" + ;:path "file:///home/user/.lv2/Odin2.lv2" + ;})) + +;(track { :name "Lead" :gain +0.0 } + ;(phrase { :name "Lead 1" :beats 4 }) + ;(phrase { :name "Lead 2" :beats 4 }) + ;(phrase { :name "Lead 3" :beats 4 }) + ;(phrase { :name "Lead 4" :beats 4 }) + ;(phrase { :name "Lead 5" :beats 4 }) + ;(phrase { :name "Lead 6" :beats 4 }) + ;(phrase { :name "Lead 7" :beats 4 }) + ;(phrase { :name "Lead 8" :beats 4 }) + ;(lv2 { + ;:name "Odin2" + ;:path "file:///home/user/.lv2/Odin2.lv2" + ;})) diff --git a/crates/tek/src/control.rs b/crates/tek/src/control.rs index 1c3c0f67..366cccdc 100644 --- a/crates/tek/src/control.rs +++ b/crates/tek/src/control.rs @@ -37,17 +37,18 @@ fn handle_modal (e: &AppEvent) -> Usually { } fn handle_focused (state: &mut App, e: &AppEvent) -> Usually { - match state.section { - AppFocus::Transport => state.transport.handle(e), - AppFocus::Arranger => state.arranger.sequencer_mut().map(|s|s.handle(e)), - AppFocus::Sequencer => state.arranger.sequencer_mut().map(|s|s.handle(e)), - 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)? - })*/ - } + unimplemented!() + //match state.section { + //AppFocus::Transport => state.transport.handle(e), + //AppFocus::Arranger => state.arranger.sequencer_mut().map(|s|s.handle(e)), + //AppFocus::Sequencer => state.arranger.sequencer_mut().map(|s|s.handle(e)), + //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)? + //})*/ + //} } fn handle_device (state: &mut App, e: &AppEvent) -> Usually { diff --git a/crates/tek/src/main.rs b/crates/tek/src/main.rs index 87a1ba91..630a10ba 100644 --- a/crates/tek/src/main.rs +++ b/crates/tek/src/main.rs @@ -7,9 +7,9 @@ #![allow(macro_expanded_macro_exports_accessed_by_absolute_paths)] #![allow(ambiguous_glob_reexports)] -pub(crate) use tek_core::*; -pub(crate) use tek_jack::{*, jack::*}; +pub(crate) use tek_core::{*, jack::*}; pub(crate) use tek_sequencer::*; +pub(crate) use tek_mixer::*; pub(crate) use microxdg::XdgApp; submod! { @@ -29,7 +29,7 @@ pub static MODAL: Lazy>>>> = /// Application entrypoint. pub fn main () -> Usually<()> { - run(App::from_edn(include_str!("../../../demos/project.edn"))? + run(App::from_edn(include_str!("../example.edn"))? .activate(Some(|app: &Arc>|Ok({ let (midi_in, mut midi_outs) = { let app = app.read().unwrap(); diff --git a/crates/tek_core/Cargo.toml b/crates/tek_core/Cargo.toml index 1d1e1666..36c5632e 100644 --- a/crates/tek_core/Cargo.toml +++ b/crates/tek_core/Cargo.toml @@ -4,13 +4,14 @@ edition = "2021" version = "0.1.0" [dependencies] -crossterm = "0.27" -ratatui = { version = "0.26.3", features = [ "unstable-widget-ref", "underline-color" ] } +atomic_float = "1.0.0" backtrace = "0.3.72" -toml = "0.8.12" better-panic = "0.3.0" -midly = "0.5" clap = { version = "4.5.4", features = [ "derive" ] } clojure-reader = "0.1.0" +crossterm = "0.27" +jack = "0.10" +midly = "0.5" once_cell = "1.19.0" -atomic_float = "1.0.0" +ratatui = { version = "0.26.3", features = [ "unstable-widget-ref", "underline-color" ] } +toml = "0.8.12" diff --git a/crates/tek_jack/src/lib.rs b/crates/tek_core/src/jack_core.rs similarity index 50% rename from crates/tek_jack/src/lib.rs rename to crates/tek_core/src/jack_core.rs index 6a067ecd..b2a51db1 100644 --- a/crates/tek_jack/src/lib.rs +++ b/crates/tek_core/src/jack_core.rs @@ -1,39 +1,4 @@ -//! Audio engine. - -pub use jack; - -use std::sync::{Arc, RwLock, LockResult, RwLockReadGuard, RwLockWriteGuard}; -use std::collections::BTreeMap; - -submod!( device event factory ports ); - -pub(crate) use tek_core::*; -pub(crate) use tek_core::ratatui::prelude::{Buffer, Rect}; -pub(crate) use ::jack::{ - AsyncClient, - AudioIn, - AudioOut, - Client, - ClientOptions, - ClientStatus, - ClosureProcessHandler, - Control, - //CycleTimes, - Frames, - MidiIn, - //MidiIter, - MidiOut, - NotificationHandler, - Port, - //PortFlags, - PortId, - PortSpec, - ProcessScope, - //RawMidi, - Transport, - //TransportState, - Unowned -}; +use crate::{*, jack::*}; /// A UI component that may be associated with a JACK client by the `Jack` factory. pub trait Device: Render + Handle + Process + Send + Sync { @@ -156,3 +121,109 @@ pub fn jack_run (name: &str, app: &Arc>) -> Usually, + pub audio_ins: Vec, + pub midi_outs: Vec, + pub audio_outs: Vec, +} +impl Jack { + pub fn new (name: &str) -> Usually { + Ok(Self { + midi_ins: vec![], + audio_ins: vec![], + midi_outs: vec![], + audio_outs: vec![], + client: Client::new( + name, + ClientOptions::NO_START_SERVER + )?.0, + }) + } + pub fn run ( + self, state: impl FnOnce(JackPorts)->Box + ) + -> Usually + { + let owned_ports = JackPorts { + audio_ins: register_ports(&self.client, self.audio_ins, AudioIn)?, + audio_outs: register_ports(&self.client, self.audio_outs, AudioOut)?, + midi_ins: register_ports(&self.client, self.midi_ins, MidiIn)?, + midi_outs: register_ports(&self.client, self.midi_outs, MidiOut)?, + }; + let midi_outs = owned_ports.midi_outs.values() + .map(|p|Ok(p.name()?)).collect::>>()?; + let midi_ins = owned_ports.midi_ins.values() + .map(|p|Ok(p.name()?)).collect::>>()?; + let audio_outs = owned_ports.audio_outs.values() + .map(|p|Ok(p.name()?)).collect::>>()?; + let audio_ins = owned_ports.audio_ins.values() + .map(|p|Ok(p.name()?)).collect::>>()?; + let state = Arc::new(RwLock::new(state(owned_ports) as Box)); + let client = self.client.activate_async( + Notifications(Box::new({ + let _state = state.clone(); + move|_event|{ + // FIXME: this deadlocks + //state.lock().unwrap().handle(&event).unwrap(); + } + }) as Box), + ClosureProcessHandler::new(Box::new({ + let state = state.clone(); + move|c: &Client, s: &ProcessScope|{ + state.write().unwrap().process(c, s) + } + }) as BoxedProcessHandler) + )?; + Ok(JackDevice { + ports: UnownedJackPorts { + audio_ins: query_ports(&client.as_client(), audio_ins), + audio_outs: query_ports(&client.as_client(), audio_outs), + midi_ins: query_ports(&client.as_client(), midi_ins), + midi_outs: query_ports(&client.as_client(), midi_outs), + }, + client, + state, + }) + } + pub fn audio_in (mut self, name: &str) -> Self { + self.audio_ins.push(name.to_string()); + self + } + pub fn audio_out (mut self, name: &str) -> Self { + self.audio_outs.push(name.to_string()); + self + } + pub fn midi_in (mut self, name: &str) -> Self { + self.midi_ins.push(name.to_string()); + self + } + pub fn midi_out (mut self, name: &str) -> Self { + self.midi_outs.push(name.to_string()); + self + } +} + +fn register_ports ( + client: &Client, names: Vec, spec: T +) -> Usually>> { + names.into_iter().try_fold(BTreeMap::new(), |mut ports, name|{ + let port = client.register_port(&name, spec)?; + ports.insert(name, port); + Ok(ports) + }) +} + +fn query_ports ( + client: &Client, names: Vec +) -> BTreeMap> { + names.into_iter().fold(BTreeMap::new(), |mut ports, name|{ + let port = client.port_by_name(&name).unwrap(); + ports.insert(name, port); + ports + }) +} + diff --git a/crates/tek_jack/src/device.rs b/crates/tek_core/src/jack_device.rs similarity index 95% rename from crates/tek_jack/src/device.rs rename to crates/tek_core/src/jack_device.rs index 80b751fe..b021ef72 100644 --- a/crates/tek_jack/src/device.rs +++ b/crates/tek_core/src/jack_device.rs @@ -1,7 +1,4 @@ -//! Wrap JACK-enabled [Device]s. - -use super::*; -use tek_core::ratatui::prelude::{Buffer, Rect}; +use crate::{*, jack::*}; /// A [Device] bound to a JACK client and a set of ports. pub struct JackDevice { @@ -52,3 +49,4 @@ impl JackDevice { Ok(self.client.as_client().connect_ports(self.audio_outs()?[index], port)?) } } + diff --git a/crates/tek_jack/src/event.rs b/crates/tek_core/src/jack_event.rs similarity index 98% rename from crates/tek_jack/src/event.rs rename to crates/tek_core/src/jack_event.rs index 3a0effc7..32a8fd8e 100644 --- a/crates/tek_jack/src/event.rs +++ b/crates/tek_core/src/jack_event.rs @@ -1,6 +1,4 @@ -//! JACK event handling. - -use super::*; +use crate::{*, jack::*}; /// Notification handler used by the [Jack] factory /// when constructing [JackDevice]s. diff --git a/crates/tek_jack/src/ports.rs b/crates/tek_core/src/jack_ports.rs similarity index 98% rename from crates/tek_jack/src/ports.rs rename to crates/tek_core/src/jack_ports.rs index 52a7583b..915354f9 100644 --- a/crates/tek_jack/src/ports.rs +++ b/crates/tek_core/src/jack_ports.rs @@ -1,5 +1,4 @@ -//! Handling JACK ports. -use super::*; +use crate::{*, jack::*}; /// Collection of JACK ports as [AudioIn]/[AudioOut]/[MidiIn]/[MidiOut]. #[derive(Default, Debug)] @@ -92,3 +91,4 @@ pub trait Ports { )?} }; } + diff --git a/crates/tek_core/src/lib.rs b/crates/tek_core/src/lib.rs index a1e45ff0..dd8d47b9 100644 --- a/crates/tek_core/src/lib.rs +++ b/crates/tek_core/src/lib.rs @@ -1,8 +1,9 @@ pub use ratatui; pub use crossterm; +pub use jack; pub use midly; pub use clap; -pub use std::sync::{Arc, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard}; +pub use std::sync::{Arc, Mutex, LockResult, RwLock, RwLockReadGuard, RwLockWriteGuard}; pub use std::collections::BTreeMap; pub use crossterm::event::{Event, KeyEvent, KeyCode, KeyModifiers}; pub use ratatui::prelude::{Rect, Style, Color, Buffer}; @@ -16,7 +17,6 @@ pub(crate) use std::io::{stdout}; pub(crate) use std::thread::{spawn, JoinHandle}; pub(crate) use std::time::Duration; pub(crate) use atomic_float::*; -//, LockResult, RwLockReadGuard, RwLockWriteGuard}; //pub(crate) use std::path::PathBuf; //pub(crate) use std::fs::read_dir; //pub(crate) use std::ffi::OsString; @@ -48,6 +48,10 @@ submod! { time_base time_note time_tick + jack_core + jack_device + jack_event + jack_ports } /// EDN parsing helper. diff --git a/crates/tek_core/src/render.rs b/crates/tek_core/src/render.rs index 98d5edd1..12e32a2c 100644 --- a/crates/tek_core/src/render.rs +++ b/crates/tek_core/src/render.rs @@ -145,7 +145,7 @@ impl Render for () { } } -impl Render for Option { +impl Render for Option<&T> { fn render (&self, b: &mut Buffer, a: Rect) -> Usually { match self { Some(widget) => widget.render(b, a), diff --git a/crates/tek_core/src/time_tick.rs b/crates/tek_core/src/time_tick.rs index 7102c8bb..15aa542f 100644 --- a/crates/tek_core/src/time_tick.rs +++ b/crates/tek_core/src/time_tick.rs @@ -46,63 +46,3 @@ mod test { } } - -/// (pulses, name) -pub const NOTE_DURATIONS: [(usize, &str);26] = [ - (1, "1/384"), - (2, "1/192"), - (3, "1/128"), - (4, "1/96"), - (6, "1/64"), - (8, "1/48"), - (12, "1/32"), - (16, "1/24"), - (24, "1/16"), - (32, "1/12"), - (48, "1/8"), - (64, "1/6"), - (96, "1/4"), - (128, "1/3"), - (192, "1/2"), - (256, "2/3"), - (384, "1/1"), - (512, "4/3"), - (576, "3/2"), - (768, "2/1"), - (1152, "3/1"), - (1536, "4/1"), - (2304, "6/1"), - (3072, "8/1"), - (3456, "9/1"), - (6144, "16/1"), -]; - -/// Returns the next shorter length -pub fn prev_note_length (ppq: usize) -> usize { - for i in 1..=16 { - let length = NOTE_DURATIONS[16-i].0; - if length < ppq { - return length - } - } - ppq -} - -/// Returns the next longer length -pub fn next_note_length (ppq: usize) -> usize { - for (length, _) in &NOTE_DURATIONS { - if *length > ppq { - return *length - } - } - ppq -} - -pub fn ppq_to_name (ppq: usize) -> &'static str { - for (length, name) in &NOTE_DURATIONS { - if *length == ppq { - return name - } - } - "" -} diff --git a/crates/tek_jack/Cargo.toml b/crates/tek_jack/Cargo.toml deleted file mode 100644 index 2059efed..00000000 --- a/crates/tek_jack/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "tek_jack" -edition = "2021" -version = "0.1.0" - -[dependencies] -tek_core = { path = "../tek_core" } -jack = "0.10" diff --git a/crates/tek_jack/README.md b/crates/tek_jack/README.md deleted file mode 100644 index ad1346be..00000000 --- a/crates/tek_jack/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `tek_jack` - -This crate interfaces with the JACK Audio Connection Kit API. diff --git a/crates/tek_jack/src/factory.rs b/crates/tek_jack/src/factory.rs deleted file mode 100644 index 329a2e41..00000000 --- a/crates/tek_jack/src/factory.rs +++ /dev/null @@ -1,108 +0,0 @@ -//! Encapsulate and run [Device]s as [JackDevice]s. -use super::*; - -/// `JackDevice` factory. Creates JACK `Client`s, performs port registration -/// and activation, and encapsulates a `Device` into a `JackDevice`. -pub struct Jack { - pub client: Client, - pub midi_ins: Vec, - pub audio_ins: Vec, - pub midi_outs: Vec, - pub audio_outs: Vec, -} -impl Jack { - pub fn new (name: &str) -> Usually { - Ok(Self { - midi_ins: vec![], - audio_ins: vec![], - midi_outs: vec![], - audio_outs: vec![], - client: Client::new( - name, - ClientOptions::NO_START_SERVER - )?.0, - }) - } - pub fn run ( - self, state: impl FnOnce(JackPorts)->Box - ) - -> Usually - { - let owned_ports = JackPorts { - audio_ins: register_ports(&self.client, self.audio_ins, AudioIn)?, - audio_outs: register_ports(&self.client, self.audio_outs, AudioOut)?, - midi_ins: register_ports(&self.client, self.midi_ins, MidiIn)?, - midi_outs: register_ports(&self.client, self.midi_outs, MidiOut)?, - }; - let midi_outs = owned_ports.midi_outs.values() - .map(|p|Ok(p.name()?)).collect::>>()?; - let midi_ins = owned_ports.midi_ins.values() - .map(|p|Ok(p.name()?)).collect::>>()?; - let audio_outs = owned_ports.audio_outs.values() - .map(|p|Ok(p.name()?)).collect::>>()?; - let audio_ins = owned_ports.audio_ins.values() - .map(|p|Ok(p.name()?)).collect::>>()?; - let state = Arc::new(RwLock::new(state(owned_ports) as Box)); - let client = self.client.activate_async( - Notifications(Box::new({ - let _state = state.clone(); - move|_event|{ - // FIXME: this deadlocks - //state.lock().unwrap().handle(&event).unwrap(); - } - }) as Box), - ClosureProcessHandler::new(Box::new({ - let state = state.clone(); - move|c: &Client, s: &ProcessScope|{ - state.write().unwrap().process(c, s) - } - }) as BoxedProcessHandler) - )?; - Ok(JackDevice { - ports: UnownedJackPorts { - audio_ins: query_ports(&client.as_client(), audio_ins), - audio_outs: query_ports(&client.as_client(), audio_outs), - midi_ins: query_ports(&client.as_client(), midi_ins), - midi_outs: query_ports(&client.as_client(), midi_outs), - }, - client, - state, - }) - } - pub fn audio_in (mut self, name: &str) -> Self { - self.audio_ins.push(name.to_string()); - self - } - pub fn audio_out (mut self, name: &str) -> Self { - self.audio_outs.push(name.to_string()); - self - } - pub fn midi_in (mut self, name: &str) -> Self { - self.midi_ins.push(name.to_string()); - self - } - pub fn midi_out (mut self, name: &str) -> Self { - self.midi_outs.push(name.to_string()); - self - } -} - -fn register_ports ( - client: &Client, names: Vec, spec: T -) -> Usually>> { - names.into_iter().try_fold(BTreeMap::new(), |mut ports, name|{ - let port = client.register_port(&name, spec)?; - ports.insert(name, port); - Ok(ports) - }) -} - -fn query_ports ( - client: &Client, names: Vec -) -> BTreeMap> { - names.into_iter().fold(BTreeMap::new(), |mut ports, name|{ - let port = client.port_by_name(&name).unwrap(); - ports.insert(name, port); - ports - }) -} diff --git a/crates/tek_mixer/Cargo.toml b/crates/tek_mixer/Cargo.toml index f0a693d3..20e48eaa 100644 --- a/crates/tek_mixer/Cargo.toml +++ b/crates/tek_mixer/Cargo.toml @@ -5,7 +5,6 @@ version = "0.1.0" [dependencies] tek_core = { path = "../tek_core" } -tek_jack = { path = "../tek_jack" } livi = "0.7.4" suil-rs = { path = "../suil" } @@ -32,4 +31,4 @@ path = "src/sampler_main.rs" [[bin]] name = "tek_plugin" -path = "src/sampler_main.rs" +path = "src/plugin_main.rs" diff --git a/crates/tek_mixer/src/lib.rs b/crates/tek_mixer/src/lib.rs index ad85d6b6..9d929731 100644 --- a/crates/tek_mixer/src/lib.rs +++ b/crates/tek_mixer/src/lib.rs @@ -2,7 +2,7 @@ pub(crate) use tek_core::*; pub(crate) use tek_core::ratatui::prelude::*; pub(crate) use tek_core::crossterm::event::{KeyCode, KeyModifiers}; pub(crate) use tek_core::midly::{num::u7, live::LiveEvent, MidiMessage}; -pub(crate) use tek_jack::{*, jack::*}; +pub(crate) use tek_core::jack::*; pub(crate) use std::collections::BTreeMap; pub(crate) use std::sync::{Arc, Mutex, RwLock}; diff --git a/crates/tek_sequencer/Cargo.toml b/crates/tek_sequencer/Cargo.toml index 44867b60..e9a6c4d9 100644 --- a/crates/tek_sequencer/Cargo.toml +++ b/crates/tek_sequencer/Cargo.toml @@ -5,7 +5,6 @@ version = "0.1.0" [dependencies] tek_core = { path = "../tek_core" } -tek_jack = { path = "../tek_jack" } [lib] path = "src/lib.rs" diff --git a/crates/tek_sequencer/src/arranger_cli.rs b/crates/tek_sequencer/src/arranger_cli.rs index 5d92de59..93d63144 100644 --- a/crates/tek_sequencer/src/arranger_cli.rs +++ b/crates/tek_sequencer/src/arranger_cli.rs @@ -27,12 +27,12 @@ impl Arranger { arr.transport = Some(Arc::new(RwLock::new(TransportToolbar::new(None)))); } if let Some(tracks) = args.tracks { - for track in 0..tracks { + for _ in 0..tracks { arr.track_add(None)?; } } if let Some(scenes) = args.scenes { - for scene in 0..scenes { + for _ in 0..scenes { arr.scene_add(None)?; } } diff --git a/crates/tek_sequencer/src/lib.rs b/crates/tek_sequencer/src/lib.rs index aaad6bca..0afd645e 100644 --- a/crates/tek_sequencer/src/lib.rs +++ b/crates/tek_sequencer/src/lib.rs @@ -4,7 +4,7 @@ pub(crate) use tek_core::*; pub(crate) use tek_core::ratatui::prelude::*; pub(crate) use tek_core::crossterm::event::{KeyCode, KeyModifiers}; pub(crate) use tek_core::midly::{num::u7, live::LiveEvent, MidiMessage}; -pub(crate) use tek_jack::{*, jack::*}; +pub(crate) use tek_core::jack::*; pub(crate) use std::sync::{Arc, RwLock}; submod! { diff --git a/demos/project.edn b/demos/project.edn deleted file mode 100644 index 867b0e70..00000000 --- a/demos/project.edn +++ /dev/null @@ -1,139 +0,0 @@ -(bpm 150) - -(midi-in "nanoKEY Studio.*capture.*") -(midi-in "nanoKEY Studio.*capture.*") -(audio-out "Built-.+:playback_FL", "Built-.+:playback_FR") - -(scene { :name "Intro" } 0 0 _ _) -(scene { :name "Hook" } 1 1 0 _) -(scene { :name "Verse" } 2 2 1 _) -(scene { :name "Chorus" } 3 3 2 _) -(scene { :name "Bridge" } _ 4 3 _) -(scene { :name "Outro" } 4 1 4 _) - -(track { :name "Drums" :gain +0.0 } - (phrase { :name "4 kicks" :beats 4 :steps 16 } - (:00 (36 128)) - (:04 (36 100)) - (:08 (36 100)) - (:12 (36 100))) - (phrase { :name "5 kicks" :beats 4 :steps 16 } - (:00 (36 128)) - (:04 (36 100)) - (:08 (36 128)) - (:12 (36 100)) - (:14 (36 110))) - (phrase { :name "D Beat" :beats 8 :steps 32 } - (:00 (44 70) (36 128) (49 110)) - (:02 (44 30)) - (:04 (44 80) (40 100)) - (:06 (44 50)) - (:08 (44 30) (36 100)) - (:10 (44 50) (36 100)) - (:12 (44 80) (40 100)) - (:14 (44 50)) - (:15 (36 50)) - (:16 (44 60) (36 80)) - (:18 (44 60) (36 80)) - (:20 (44 60) (40 80)) - (:22 (44 60)) - (:24 (44 60)) - (:26 (44 30) (36 80)) - (:27 (44 60)) - (:28 (44 60) (40 80)) - (:30 (44 60))) - (phrase { :name "Garage" :beats 4 :steps 16 } - (:00 (44 100) (36 100) (35 100)) - (:01 (44 100)) - (:02 (44 100) (35 100)) - (:03 (44 100)) - (:04 (44 100) (40 100)) - (:06 (44 100)) - (:07 (44 100) (34 100)) - (:09 (44 100)) - (:10 (44 100)) - (:11 (35 100) (36 100)) - (:12 (44 100) (40 100)) - (:14 (44 100))) - - (phrase { :name "Trap Pinging" :beats 8 :steps 96 } - (:00 (42 100) (36 100) (34 120) (49 100)) - (:01 (42 100)) - (:02 (42 100)) - (:06 (42 100) (35 80) (36 80) (49 100)) - (:07 (42 100)) - (:08 (42 100)) - (:12 (42 100)) - (:15 (39 100) (34 100)) - (:18 (42 100)) - (:24 (42 100) (38 50) (40 50)) - (:27 (42 100) (36 50)) - (:30 (42 100)) - (:33 (42 100) (36 50) (34 100)) - (:36 (42 90)) - (:39 (42 80)) - (:42 (42 70)) - (:45 (42 60)) - - (:48 (42 100) (36 100) (34 100)) - (:50 (42 100)) - (:52 (42 110)) - (:54 (46 50) (42 120)) - (:56 (42 90)) - (:58 (42 100)) - (:60 (42 100) (35 100)) - (:64 (39 100)) - (:66 (42 100) (34 100)) - - (:70 (42 100)) - (:71 (42 100)) - (:72 (42 100) (38 50) (40 50)) - (:75 (42 100) (36 50) (34 80)) - (:78 (42 100)) - (:81 (42 100) (36 50)) - (:84 (38 40) (40 50) (34 90)) - (:87 (42 90) (35 40)) - (:90 (42 70))) - - (sampler { :name "DrumKit1" :dir "/home/user/Lab/Music/pak" } - (sample { :midi 34 :name "808 D" :file "808.wav" }) - (sample { :midi 35 :name "Kick 1" :file "kik.wav" }) - (sample { :midi 36 :name "Kick 2" :file "kik2.wav" }) - (sample { :midi 37 :name "Rim" :file "rim.wav" }) - (sample { :midi 38 :name "Snare 1" :file "sna.wav" }) - (sample { :midi 39 :name "Shaker" :file "shk.wav" }) - (sample { :midi 40 :name "Snare 2" :file "sna2.wav" }) - (sample { :midi 42 :name "Closed HH 1" :file "chh.wav" }) - (sample { :midi 44 :name "Closed HH 2" :file "chh2.wav" }) - (sample { :midi 45 :name "Open HH 0" :file "ohh.wav" }) - (sample { :midi 46 :name "Open HH 1" :file "ohh1.wav" }) - (sample { :midi 47 :name "Open HH 2" :file "ohh2.wav" }) - (sample { :midi 49 :name "Crash" :file "crs.wav" }))) - -(track { :name "Bass" :gain +0.0 } - (phrase { :name "Bass 1" :beats 4 }) - (phrase { :name "Bass 2" :beats 4 }) - (phrase { :name "Bass 3" :beats 4 }) - (phrase { :name "Bass 4" :beats 4 }) - (phrase { :name "Bass 5" :beats 4 }) - (phrase { :name "Bass 6" :beats 4 }) - (phrase { :name "Bass 7" :beats 4 }) - (phrase { :name "Bass 8" :beats 4 }) - (lv2 { - :name "Odin2" - :path "file:///home/user/.lv2/Odin2.lv2" - })) - -(track { :name "Lead" :gain +0.0 } - (phrase { :name "Lead 1" :beats 4 }) - (phrase { :name "Lead 2" :beats 4 }) - (phrase { :name "Lead 3" :beats 4 }) - (phrase { :name "Lead 4" :beats 4 }) - (phrase { :name "Lead 5" :beats 4 }) - (phrase { :name "Lead 6" :beats 4 }) - (phrase { :name "Lead 7" :beats 4 }) - (phrase { :name "Lead 8" :beats 4 }) - (lv2 { - :name "Odin2" - :path "file:///home/user/.lv2/Odin2.lv2" - })) diff --git a/demos/scratch.edn b/demos/scratch.edn deleted file mode 100644 index 341bb74e..00000000 --- a/demos/scratch.edn +++ /dev/null @@ -1,52 +0,0 @@ - - - -;(:bpm 150) - -;(:track#01 "Drums") -;(:track#02 "Bass") -;(:track#03 "Lead") - -;(:scene#01 "Intro" (:01 --) (:02 :01) (:03 :01) ) -;(:scene#02 "Hook" ) -;(:scene#03 "Verse" ) -;(:scene#04 "Chorus") -;(:scene#05 "Bridge") - -;(midi-in "nanoKEY Studio.*capture.*") -;(audio-out ["Komplete.+:playback_FL", "Komplete.+:playback_FR"]) - - - ;(sampler { :name "DrumKit1" :dir "/home/user/Lab/Music/pak" } - ;(sample { :midi 34 :name "808" :file "808.wav" }) - ;(sample { :midi 35 :name "KC1" :file "kik.wav" }) - ;(sample { :midi 36 :name "KC2" :file "kik2.wav" }) - ;(sample { :midi 38 :name "SN1" :file "sna.wav" }) - ;(sample { :midi 40 :name "SN2" :file "sna2.wav" }) - ;(sample { :midi 42 :name "HH1" :file "chh.wav" }) - ;(sample { :midi 44 :name "HH2" :file "chh2.wav" })) - - ;(phrase { :name "4 kicks" :beats 4 :steps 16 } - ;(:00 (36 128)) - ;(:04 (36 128)) - ;(:08 (36 128)) - ;(:12 (36 128)))) - - ;(phrase { - ;:name "5 kicks" - ;:beats 4 - ;} (:00 (36 128)) - ;(:04 (36 128)) - ;(:08 (36 128)) - ;(:12 (36 128)) - ;(:14 (36 128))) - -;(track "Bass" - ;(lv2-plugin "Odin2") - ;(phrase { :name "Empty" :beats 4 }) - ;(phrase { :name "Empty" :beats 4 })) - -;(track "Lead" - ;(lv2-plugin "Odin2") - ;(phrase { :name "Empty" :beats 4 }) - ;(phrase { :name "Empty" :beats 4 }))