mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +01:00
wip: multi-crate refactor
This commit is contained in:
parent
911c47fc7c
commit
e08a79b507
25 changed files with 311 additions and 265 deletions
19
Cargo.lock
generated
19
Cargo.lock
generated
|
|
@ -1,6 +1,6 @@
|
||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "addr2line"
|
name = "addr2line"
|
||||||
|
|
@ -1268,7 +1268,6 @@ dependencies = [
|
||||||
"atomic_float",
|
"atomic_float",
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"better-panic",
|
"better-panic",
|
||||||
"clap",
|
|
||||||
"clojure-reader",
|
"clojure-reader",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
"jack",
|
"jack",
|
||||||
|
|
@ -1285,6 +1284,22 @@ dependencies = [
|
||||||
"wavers",
|
"wavers",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tek_cli"
|
||||||
|
version = "0.2.0"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
"tek",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tek_edn"
|
||||||
|
version = "0.2.0"
|
||||||
|
dependencies = [
|
||||||
|
"clojure-reader",
|
||||||
|
"tek",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.69"
|
version = "1.0.69"
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,8 @@
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
members = [
|
members = [
|
||||||
"crates/tek",
|
"crates/tek",
|
||||||
#"crates/tek_core",
|
"crates/cli",
|
||||||
#"crates/tek_api",
|
"crates/edn",
|
||||||
#"crates/tek_tui",
|
|
||||||
#"crates/tek_cli",
|
|
||||||
#"crates/tek_layout"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
|
|
|
||||||
40
crates/cli/Cargo.toml
Normal file
40
crates/cli/Cargo.toml
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
[package]
|
||||||
|
name = "tek_cli"
|
||||||
|
edition = "2021"
|
||||||
|
version = "0.2.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tek = { path = "../tek" }
|
||||||
|
clap = { version = "4.5.4", features = [ "derive" ] }
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "tek_arranger"
|
||||||
|
path = "src/cli_arranger.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "tek_sequencer"
|
||||||
|
path = "src/cli_sequencer.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "tek_groovebox"
|
||||||
|
path = "src/cli_groovebox.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "tek_transport"
|
||||||
|
path = "src/cli_transport.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "tek_sampler"
|
||||||
|
path = "src/cli_sampler.rs"
|
||||||
|
|
||||||
|
#[[bin]]
|
||||||
|
#name = "tek_mixer"
|
||||||
|
#path = "src/cli_mixer.rs"
|
||||||
|
|
||||||
|
#[[bin]]
|
||||||
|
#name = "tek_track"
|
||||||
|
#path = "src/cli_track.rs"
|
||||||
|
|
||||||
|
#[[bin]]
|
||||||
|
#name = "tek_plugin"
|
||||||
|
#path = "src/cli_plugin.rs"
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
#![allow(unused)]
|
include!("./lib.rs");
|
||||||
#![allow(clippy::unit_arg)]
|
use tek::tui::ArrangerTui;
|
||||||
include!("../lib.rs");
|
|
||||||
|
|
||||||
pub fn main () -> Usually<()> {
|
pub fn main () -> Usually<()> {
|
||||||
ArrangerCli::parse().run()
|
ArrangerCli::parse().run()
|
||||||
22
crates/cli/src/cli_groovebox.rs
Normal file
22
crates/cli/src/cli_groovebox.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
include!("./lib.rs");
|
||||||
|
pub fn main () -> Usually<()> { GrooveboxCli::parse().run() }
|
||||||
|
#[derive(Debug, Parser)]
|
||||||
|
#[command(version, about, long_about = None)]
|
||||||
|
pub struct GrooveboxCli;
|
||||||
|
impl GrooveboxCli {
|
||||||
|
fn run (&self) -> Usually<()> {
|
||||||
|
Tui::run(JackClient::new("tek_groovebox")?.activate_with(|jack|{
|
||||||
|
let app = tek::tui::GrooveboxTui::try_from(jack)?;
|
||||||
|
let jack = jack.read().unwrap();
|
||||||
|
let midi_out = jack.register_port("out", MidiOut::default())?;
|
||||||
|
let midi_in_1 = jack.register_port("in1", MidiIn::default())?;
|
||||||
|
let midi_in_2 = jack.register_port("in2", MidiIn::default())?;
|
||||||
|
let audio_in_1 = jack.register_port("inL", AudioIn::default())?;
|
||||||
|
let audio_in_2 = jack.register_port("inR", AudioIn::default())?;
|
||||||
|
let audio_out_1 = jack.register_port("out1", AudioOut::default())?;
|
||||||
|
let audio_out_2 = jack.register_port("out2", AudioOut::default())?;
|
||||||
|
Ok(app)
|
||||||
|
})?)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,21 +1,15 @@
|
||||||
#![allow(unused)]
|
include!("./lib.rs");
|
||||||
#![allow(clippy::unit_arg)]
|
pub fn main () -> Usually<()> { SamplerCli::parse().run() }
|
||||||
include!("../lib.rs");
|
|
||||||
pub fn main () -> Usually<()> {
|
|
||||||
SamplerCli::parse().run()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Parser)] #[command(version, about, long_about = None)] pub struct SamplerCli {
|
#[derive(Debug, Parser)] #[command(version, about, long_about = None)] pub struct SamplerCli {
|
||||||
/// Name of JACK client
|
/// Name of JACK client
|
||||||
#[arg(short, long)] name: Option<String>,
|
#[arg(short, long)] name: Option<String>,
|
||||||
/// Path to plugin
|
/// Path to plugin
|
||||||
#[arg(short, long)] path: Option<String>,
|
#[arg(short, long)] path: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SamplerCli {
|
impl SamplerCli {
|
||||||
fn run (&self) -> Usually<()> {
|
fn run (&self) -> Usually<()> {
|
||||||
Tui::run(JackClient::new("tek_sampler")?.activate_with(|x|{
|
Tui::run(JackClient::new("tek_sampler")?.activate_with(|x|{
|
||||||
let sampler = SamplerTui::try_from(x)?;
|
let sampler = tek::tui::SamplerTui::try_from(x)?;
|
||||||
Ok(sampler)
|
Ok(sampler)
|
||||||
})?)?;
|
})?)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
#![allow(unused)]
|
include!("./lib.rs");
|
||||||
#![allow(clippy::unit_arg)]
|
|
||||||
include!("../lib.rs");
|
|
||||||
pub fn main () -> Usually<()> {
|
pub fn main () -> Usually<()> {
|
||||||
SequencerCli::parse().run()
|
SequencerCli::parse().run()
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
#![allow(unused)]
|
include!("./lib.rs");
|
||||||
#![allow(clippy::unit_arg)]
|
|
||||||
include!("../lib.rs");
|
|
||||||
/// Application entrypoint.
|
/// Application entrypoint.
|
||||||
pub fn main () -> Usually<()> {
|
pub fn main () -> Usually<()> {
|
||||||
Tui::run(JackClient::new("tek_transport")?.activate_with(|jack|{
|
Tui::run(JackClient::new("tek_transport")?.activate_with(|jack|{
|
||||||
3
crates/cli/src/lib.rs
Normal file
3
crates/cli/src/lib.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
use clap::{self, Parser};
|
||||||
|
use tek::{*, jack::*};
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::*;
|
include!("./lib.rs");
|
||||||
|
|
||||||
pub fn main () -> Usually<()> {
|
pub fn main () -> Usually<()> {
|
||||||
MixerCli::parse().run()
|
MixerCli::parse().run()
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::*;
|
include!("./lib.rs");
|
||||||
|
|
||||||
pub fn main () -> Usually<()> {
|
pub fn main () -> Usually<()> {
|
||||||
PluginCli::parse().run()
|
PluginCli::parse().run()
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::*;
|
include!("./lib.rs");
|
||||||
|
|
||||||
pub fn main () -> Usually<()> {
|
pub fn main () -> Usually<()> {
|
||||||
SamplerCli::parse().run()
|
SamplerCli::parse().run()
|
||||||
8
crates/edn/Cargo.toml
Normal file
8
crates/edn/Cargo.toml
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
name = "tek_edn"
|
||||||
|
edition = "2021"
|
||||||
|
version = "0.2.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tek = { path = "../tek" }
|
||||||
|
clojure-reader = "0.1.0"
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#![allow(unused)]
|
use tek::{*, jack::*};
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use crate::*;
|
|
||||||
pub use clojure_reader::edn::Edn;
|
pub use clojure_reader::edn::Edn;
|
||||||
//pub use clojure_reader::{edn::{read, Edn}, error::Error as EdnError};
|
//pub use clojure_reader::{edn::{read, Edn}, error::Error as EdnError};
|
||||||
|
|
||||||
|
|
@ -107,6 +108,81 @@ from_edn!(|(jack, dir) = (&Arc<RwLock<JackClient>>, &str), "sample", args| -> Mi
|
||||||
}))))
|
}))))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
impl LV2Plugin {
|
||||||
|
pub fn from_edn <'e> (jack: &Arc<RwLock<JackClient>>, args: &[Edn<'e>]) -> Usually<Plugin> {
|
||||||
|
let mut name = String::new();
|
||||||
|
let mut path = String::new();
|
||||||
|
edn!(edn in args {
|
||||||
|
Edn::Map(map) => {
|
||||||
|
if let Some(Edn::Str(n)) = map.get(&Edn::Key(":name")) {
|
||||||
|
name = String::from(*n);
|
||||||
|
}
|
||||||
|
if let Some(Edn::Str(p)) = map.get(&Edn::Key(":path")) {
|
||||||
|
path = String::from(*p);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => panic!("unexpected in lv2 '{name}'"),
|
||||||
|
});
|
||||||
|
Plugin::new_lv2(jack, &name, &path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MixerTrack {
|
||||||
|
const SYM_NAME: &'static str = ":name";
|
||||||
|
const SYM_GAIN: &'static str = ":gain";
|
||||||
|
const SYM_SAMPLER: &'static str = "sampler";
|
||||||
|
const SYM_LV2: &'static str = "lv2";
|
||||||
|
pub fn from_edn <'a, 'e> (jack: &Arc<RwLock<JackClient>>, args: &[Edn<'e>]) -> Usually<Self> {
|
||||||
|
let mut _gain = 0.0f64;
|
||||||
|
let mut track = MixerTrack {
|
||||||
|
name: String::new(),
|
||||||
|
audio_ins: vec![],
|
||||||
|
audio_outs: vec![],
|
||||||
|
devices: vec![],
|
||||||
|
};
|
||||||
|
edn!(edn in args {
|
||||||
|
Edn::Map(map) => {
|
||||||
|
if let Some(Edn::Str(n)) = map.get(&Edn::Key(Self::SYM_NAME)) {
|
||||||
|
track.name = n.to_string();
|
||||||
|
}
|
||||||
|
if let Some(Edn::Double(g)) = map.get(&Edn::Key(Self::SYM_GAIN)) {
|
||||||
|
_gain = f64::from(*g);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Edn::List(args) => match args.get(0) {
|
||||||
|
// Add a sampler device to the track
|
||||||
|
Some(Edn::Symbol(Self::SYM_SAMPLER)) => {
|
||||||
|
track.devices.push(
|
||||||
|
Box::new(Sampler::from_edn(jack, &args[1..])?) as Box<dyn MixerTrackDevice>
|
||||||
|
);
|
||||||
|
panic!(
|
||||||
|
"unsupported in track {}: {:?}; tek_mixer not compiled with feature \"sampler\"",
|
||||||
|
&track.name,
|
||||||
|
args.get(0).unwrap()
|
||||||
|
)
|
||||||
|
},
|
||||||
|
// Add a LV2 plugin to the track.
|
||||||
|
Some(Edn::Symbol(Self::SYM_LV2)) => {
|
||||||
|
track.devices.push(
|
||||||
|
Box::new(LV2Plugin::from_edn(jack, &args[1..])?) as Box<dyn MixerTrackDevice>
|
||||||
|
);
|
||||||
|
panic!(
|
||||||
|
"unsupported in track {}: {:?}; tek_mixer not compiled with feature \"plugin\"",
|
||||||
|
&track.name,
|
||||||
|
args.get(0).unwrap()
|
||||||
|
)
|
||||||
|
},
|
||||||
|
None =>
|
||||||
|
panic!("empty list track {}", &track.name),
|
||||||
|
_ =>
|
||||||
|
panic!("unexpected in track {}: {:?}", &track.name, args.get(0).unwrap())
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
});
|
||||||
|
Ok(track)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//impl ArrangerScene {
|
//impl ArrangerScene {
|
||||||
|
|
||||||
////TODO
|
////TODO
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
[package]
|
[package]
|
||||||
name = "suil-rs"
|
name = "tek_suil"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
gtk = "0.18.1"
|
gtk = "0.18.1"
|
||||||
livi = "0.7.4"
|
livi = "0.7.4"
|
||||||
|
#winit = { version = "0.30.4", features = [ "x11" ] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
bindgen = "0.69.4"
|
bindgen = "0.69.4"
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ version = "0.2.0"
|
||||||
atomic_float = "1.0.0"
|
atomic_float = "1.0.0"
|
||||||
backtrace = "0.3.72"
|
backtrace = "0.3.72"
|
||||||
better-panic = "0.3.0"
|
better-panic = "0.3.0"
|
||||||
clap = { version = "4.5.4", features = [ "derive" ] }
|
|
||||||
clojure-reader = "0.1.0"
|
clojure-reader = "0.1.0"
|
||||||
crossterm = "0.27"
|
crossterm = "0.27"
|
||||||
jack = "0.13"
|
jack = "0.13"
|
||||||
|
|
@ -29,37 +28,4 @@ wavers = "1.4.3"
|
||||||
#winit = { version = "0.30.4", features = [ "x11" ] }
|
#winit = { version = "0.30.4", features = [ "x11" ] }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "tek_lib"
|
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "tek_arranger"
|
|
||||||
path = "src/cli/cli_arranger.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "tek_sequencer"
|
|
||||||
path = "src/cli/cli_sequencer.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "tek_groovebox"
|
|
||||||
path = "src/cli/cli_groovebox.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "tek_transport"
|
|
||||||
path = "src/cli/cli_transport.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "tek_sampler"
|
|
||||||
path = "src/cli/cli_sampler.rs"
|
|
||||||
|
|
||||||
#[[bin]]
|
|
||||||
#name = "tek_mixer"
|
|
||||||
#path = "src/cli_mixer.rs"
|
|
||||||
|
|
||||||
#[[bin]]
|
|
||||||
#name = "tek_track"
|
|
||||||
#path = "src/cli_track.rs"
|
|
||||||
|
|
||||||
#[[bin]]
|
|
||||||
#name = "tek_plugin"
|
|
||||||
#path = "src/cli_plugin.rs"
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
pub(crate) mod audio_in;
|
use crate::*;
|
||||||
pub(crate) mod audio_out;
|
|
||||||
pub(crate) mod sampler; pub(crate) use sampler::*;
|
mod audio_in;
|
||||||
|
|
||||||
|
mod audio_out;
|
||||||
|
|
||||||
|
mod sampler;
|
||||||
|
pub(crate) use sampler::*;
|
||||||
|
pub use self::sampler::{Sampler, Sample, Voice};
|
||||||
|
|
|
||||||
|
|
@ -16,62 +16,6 @@ pub struct MixerTrack {
|
||||||
|
|
||||||
//impl MixerTrackDevice for LV2Plugin {}
|
//impl MixerTrackDevice for LV2Plugin {}
|
||||||
|
|
||||||
impl MixerTrack {
|
|
||||||
const SYM_NAME: &'static str = ":name";
|
|
||||||
const SYM_GAIN: &'static str = ":gain";
|
|
||||||
const SYM_SAMPLER: &'static str = "sampler";
|
|
||||||
const SYM_LV2: &'static str = "lv2";
|
|
||||||
pub fn from_edn <'a, 'e> (jack: &Arc<RwLock<JackClient>>, args: &[Edn<'e>]) -> Usually<Self> {
|
|
||||||
let mut _gain = 0.0f64;
|
|
||||||
let mut track = MixerTrack {
|
|
||||||
name: String::new(),
|
|
||||||
audio_ins: vec![],
|
|
||||||
audio_outs: vec![],
|
|
||||||
devices: vec![],
|
|
||||||
};
|
|
||||||
edn!(edn in args {
|
|
||||||
Edn::Map(map) => {
|
|
||||||
if let Some(Edn::Str(n)) = map.get(&Edn::Key(Self::SYM_NAME)) {
|
|
||||||
track.name = n.to_string();
|
|
||||||
}
|
|
||||||
if let Some(Edn::Double(g)) = map.get(&Edn::Key(Self::SYM_GAIN)) {
|
|
||||||
_gain = f64::from(*g);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Edn::List(args) => match args.get(0) {
|
|
||||||
// Add a sampler device to the track
|
|
||||||
Some(Edn::Symbol(Self::SYM_SAMPLER)) => {
|
|
||||||
track.devices.push(
|
|
||||||
Box::new(Sampler::from_edn(jack, &args[1..])?) as Box<dyn MixerTrackDevice>
|
|
||||||
);
|
|
||||||
panic!(
|
|
||||||
"unsupported in track {}: {:?}; tek_mixer not compiled with feature \"sampler\"",
|
|
||||||
&track.name,
|
|
||||||
args.get(0).unwrap()
|
|
||||||
)
|
|
||||||
},
|
|
||||||
// Add a LV2 plugin to the track.
|
|
||||||
Some(Edn::Symbol(Self::SYM_LV2)) => {
|
|
||||||
track.devices.push(
|
|
||||||
Box::new(LV2Plugin::from_edn(jack, &args[1..])?) as Box<dyn MixerTrackDevice>
|
|
||||||
);
|
|
||||||
panic!(
|
|
||||||
"unsupported in track {}: {:?}; tek_mixer not compiled with feature \"plugin\"",
|
|
||||||
&track.name,
|
|
||||||
args.get(0).unwrap()
|
|
||||||
)
|
|
||||||
},
|
|
||||||
None =>
|
|
||||||
panic!("empty list track {}", &track.name),
|
|
||||||
_ =>
|
|
||||||
panic!("unexpected in track {}: {:?}", &track.name, args.get(0).unwrap())
|
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
});
|
|
||||||
Ok(track)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait MixerTrackDevice: Debug + Send + Sync {
|
pub trait MixerTrackDevice: Debug + Send + Sync {
|
||||||
fn boxed (self) -> Box<dyn MixerTrackDevice> where Self: Sized + 'static {
|
fn boxed (self) -> Box<dyn MixerTrackDevice> where Self: Sized + 'static {
|
||||||
Box::new(self)
|
Box::new(self)
|
||||||
|
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
#![allow(unused)]
|
|
||||||
#![allow(clippy::unit_arg)]
|
|
||||||
include!("../lib.rs");
|
|
||||||
pub fn main () -> Usually<()> {
|
|
||||||
GrooveboxCli::parse().run()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
|
||||||
#[command(version, about, long_about = None)]
|
|
||||||
pub struct GrooveboxCli;
|
|
||||||
|
|
||||||
impl GrooveboxCli {
|
|
||||||
fn run (&self) -> Usually<()> {
|
|
||||||
Tui::run(JackClient::new("tek_groovebox")?.activate_with(|jack|{
|
|
||||||
let app = GrooveboxTui::try_from(jack)?;
|
|
||||||
let midi_out = jack.read().unwrap().register_port("out", MidiOut::default())?;
|
|
||||||
let midi_in_1 = jack.read().unwrap().register_port("in1", MidiIn::default())?;
|
|
||||||
let midi_in_2 = jack.read().unwrap().register_port("in2", MidiIn::default())?;
|
|
||||||
let audio_in_1 = jack.read().unwrap().register_port("inL", AudioIn::default())?;
|
|
||||||
let audio_in_2 = jack.read().unwrap().register_port("inR", AudioIn::default())?;
|
|
||||||
let audio_out_1 = jack.read().unwrap().register_port("out1", AudioOut::default())?;
|
|
||||||
let audio_out_2 = jack.read().unwrap().register_port("out2", AudioOut::default())?;
|
|
||||||
Ok(app)
|
|
||||||
})?)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
pub use ::jack as libjack;
|
pub use ::jack as libjack;
|
||||||
pub(crate) mod activate; #[allow(unused)] pub(crate) use self::activate::*;
|
pub use ::jack::{
|
||||||
pub(crate) mod audio; pub(crate) use self::audio::*;
|
|
||||||
pub(crate) mod client; pub(crate) use self::client::*;
|
|
||||||
pub(crate) mod jack_event; pub(crate) use self::jack_event::*;
|
|
||||||
pub(crate) mod ports; pub(crate) use self::ports::*;
|
|
||||||
pub(crate) use ::jack::{
|
|
||||||
contrib::ClosureProcessHandler, NotificationHandler,
|
contrib::ClosureProcessHandler, NotificationHandler,
|
||||||
Client, AsyncClient, ClientOptions, ClientStatus,
|
Client, AsyncClient, ClientOptions, ClientStatus,
|
||||||
ProcessScope, Control, CycleTimes, Frames,
|
ProcessScope, Control, CycleTimes, Frames,
|
||||||
|
|
@ -12,6 +9,20 @@ pub(crate) use ::jack::{
|
||||||
Transport, TransportState, MidiIter, MidiWriter, RawMidi,
|
Transport, TransportState, MidiIter, MidiWriter, RawMidi,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub mod activate;
|
||||||
|
pub(crate) use self::activate::*;
|
||||||
|
pub use self::activate::JackActivate;
|
||||||
|
|
||||||
|
pub mod client;
|
||||||
|
pub(crate) use self::client::*;
|
||||||
|
pub use self::client::JackClient;
|
||||||
|
|
||||||
|
pub mod jack_event;
|
||||||
|
pub(crate) use self::jack_event::*;
|
||||||
|
|
||||||
|
pub mod ports;
|
||||||
|
pub(crate) use self::ports::*;
|
||||||
|
|
||||||
/// Implement [TryFrom<&Arc<RwLock<JackClient>>>]: create app state from wrapped JACK handle.
|
/// Implement [TryFrom<&Arc<RwLock<JackClient>>>]: create app state from wrapped JACK handle.
|
||||||
#[macro_export] macro_rules! from_jack {
|
#[macro_export] macro_rules! from_jack {
|
||||||
(|$jack:ident|$Struct:ident$(<$($L:lifetime),*$($T:ident$(:$U:path)?),*>)? $cb:expr) => {
|
(|$jack:ident|$Struct:ident$(<$($L:lifetime),*$($T:ident$(:$U:path)?),*>)? $cb:expr) => {
|
||||||
|
|
@ -24,6 +35,83 @@ pub(crate) use ::jack::{
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Implement [Audio]: provide JACK callbacks.
|
||||||
|
#[macro_export] macro_rules! audio {
|
||||||
|
(|$self:ident:$Struct:ident$(<$($L:lifetime),*$($T:ident$(:$U:path)?),*>)?,$c:ident,$s:ident|$cb:expr) => {
|
||||||
|
impl $(<$($L),*$($T $(: $U)?),*>)? Audio for $Struct $(<$($L),*$($T),*>)? {
|
||||||
|
#[inline] fn process (&mut $self, $c: &Client, $s: &ProcessScope) -> Control { $cb }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trait for thing that has a JACK process callback.
|
||||||
|
pub trait Audio: Send + Sync {
|
||||||
|
fn process (&mut self, _: &Client, _: &ProcessScope) -> Control {
|
||||||
|
Control::Continue
|
||||||
|
}
|
||||||
|
fn callback (
|
||||||
|
state: &Arc<RwLock<Self>>, client: &Client, scope: &ProcessScope
|
||||||
|
) -> Control where Self: Sized {
|
||||||
|
if let Ok(mut state) = state.write() {
|
||||||
|
state.process(client, scope)
|
||||||
|
} else {
|
||||||
|
Control::Quit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Trait for things that wrap a JACK client.
|
||||||
|
pub trait AudioEngine {
|
||||||
|
|
||||||
|
fn transport (&self) -> Transport {
|
||||||
|
self.client().transport()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn port_by_name (&self, name: &str) -> Option<Port<Unowned>> {
|
||||||
|
self.client().port_by_name(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn register_port <PS: PortSpec> (&self, name: &str, spec: PS) -> Usually<Port<PS>> {
|
||||||
|
Ok(self.client().register_port(name, spec)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn client (&self) -> &Client;
|
||||||
|
|
||||||
|
fn activate (
|
||||||
|
self,
|
||||||
|
process: impl FnMut(&Arc<RwLock<Self>>, &Client, &ProcessScope) -> Control + Send + 'static
|
||||||
|
) -> Usually<Arc<RwLock<Self>>> where Self: Send + Sync + 'static;
|
||||||
|
|
||||||
|
fn thread_init (&self, _: &Client) {}
|
||||||
|
|
||||||
|
unsafe fn shutdown (&mut self, _status: ClientStatus, _reason: &str) {}
|
||||||
|
|
||||||
|
fn freewheel (&mut self, _: &Client, _enabled: bool) {}
|
||||||
|
|
||||||
|
fn client_registration (&mut self, _: &Client, _name: &str, _reg: bool) {}
|
||||||
|
|
||||||
|
fn port_registration (&mut self, _: &Client, _id: PortId, _reg: bool) {}
|
||||||
|
|
||||||
|
fn ports_connected (&mut self, _: &Client, _a: PortId, _b: PortId, _are: bool) {}
|
||||||
|
|
||||||
|
fn sample_rate (&mut self, _: &Client, _frames: Frames) -> Control {
|
||||||
|
Control::Continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fn port_rename (&mut self, _: &Client, _id: PortId, _old: &str, _new: &str) -> Control {
|
||||||
|
Control::Continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fn graph_reorder (&mut self, _: &Client) -> Control {
|
||||||
|
Control::Continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fn xrun (&mut self, _: &Client) -> Control {
|
||||||
|
Control::Continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
///// A [AudioComponent] bound to a JACK client and a set of ports.
|
///// A [AudioComponent] bound to a JACK client and a set of ports.
|
||||||
|
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
/// Implement [Audio]: provide JACK callbacks.
|
|
||||||
#[macro_export] macro_rules! audio {
|
|
||||||
(|$self:ident:$Struct:ident$(<$($L:lifetime),*$($T:ident$(:$U:path)?),*>)?,$c:ident,$s:ident|$cb:expr) => {
|
|
||||||
impl $(<$($L),*$($T $(: $U)?),*>)? Audio for $Struct $(<$($L),*$($T),*>)? {
|
|
||||||
#[inline] fn process (&mut $self, $c: &Client, $s: &ProcessScope) -> Control { $cb }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait for thing that has a JACK process callback.
|
|
||||||
pub trait Audio: Send + Sync {
|
|
||||||
fn process (&mut self, _: &Client, _: &ProcessScope) -> Control {
|
|
||||||
Control::Continue
|
|
||||||
}
|
|
||||||
fn callback (
|
|
||||||
state: &Arc<RwLock<Self>>, client: &Client, scope: &ProcessScope
|
|
||||||
) -> Control where Self: Sized {
|
|
||||||
if let Ok(mut state) = state.write() {
|
|
||||||
state.process(client, scope)
|
|
||||||
} else {
|
|
||||||
Control::Quit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Trait for things that wrap a JACK client.
|
|
||||||
pub trait AudioEngine {
|
|
||||||
|
|
||||||
fn transport (&self) -> Transport {
|
|
||||||
self.client().transport()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn port_by_name (&self, name: &str) -> Option<Port<Unowned>> {
|
|
||||||
self.client().port_by_name(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn register_port <PS: PortSpec> (&self, name: &str, spec: PS) -> Usually<Port<PS>> {
|
|
||||||
Ok(self.client().register_port(name, spec)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn client (&self) -> &Client;
|
|
||||||
|
|
||||||
fn activate (
|
|
||||||
self,
|
|
||||||
process: impl FnMut(&Arc<RwLock<Self>>, &Client, &ProcessScope) -> Control + Send + 'static
|
|
||||||
) -> Usually<Arc<RwLock<Self>>> where Self: Send + Sync + 'static;
|
|
||||||
|
|
||||||
fn thread_init (&self, _: &Client) {}
|
|
||||||
|
|
||||||
unsafe fn shutdown (&mut self, _status: ClientStatus, _reason: &str) {}
|
|
||||||
|
|
||||||
fn freewheel (&mut self, _: &Client, _enabled: bool) {}
|
|
||||||
|
|
||||||
fn client_registration (&mut self, _: &Client, _name: &str, _reg: bool) {}
|
|
||||||
|
|
||||||
fn port_registration (&mut self, _: &Client, _id: PortId, _reg: bool) {}
|
|
||||||
|
|
||||||
fn ports_connected (&mut self, _: &Client, _a: PortId, _b: PortId, _are: bool) {}
|
|
||||||
|
|
||||||
fn sample_rate (&mut self, _: &Client, _frames: Frames) -> Control {
|
|
||||||
Control::Continue
|
|
||||||
}
|
|
||||||
|
|
||||||
fn port_rename (&mut self, _: &Client, _id: PortId, _old: &str, _new: &str) -> Control {
|
|
||||||
Control::Continue
|
|
||||||
}
|
|
||||||
|
|
||||||
fn graph_reorder (&mut self, _: &Client) -> Control {
|
|
||||||
Control::Continue
|
|
||||||
}
|
|
||||||
|
|
||||||
fn xrun (&mut self, _: &Client) -> Control {
|
|
||||||
Control::Continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +1,22 @@
|
||||||
const FOO: () = ();
|
#![allow(unused)]
|
||||||
|
#![allow(clippy::unit_arg)]
|
||||||
|
|
||||||
pub mod core; pub use self::core::*;
|
pub mod core; pub use self::core::*;
|
||||||
pub mod time; pub(crate) use self::time::*;
|
pub mod time; pub(crate) use self::time::*;
|
||||||
pub mod space; pub(crate) use self::space::*;
|
pub mod space; pub(crate) use self::space::*;
|
||||||
pub mod tui; pub(crate) use self::tui::*;
|
|
||||||
pub mod edn;
|
|
||||||
pub mod jack; pub(crate) use self::jack::*;
|
|
||||||
pub mod midi; pub(crate) use self::midi::*;
|
|
||||||
pub mod audio; pub(crate) use self::audio::*;
|
|
||||||
//pub mod plugin; pub(crate) use self::plugin::*;
|
|
||||||
|
|
||||||
pub(crate) use clap::{self, Parser};
|
pub mod tui; pub(crate) use self::tui::*;
|
||||||
|
pub use tui::{Tui, TransportTui, SequencerTui, SamplerTui, GrooveboxTui, ArrangerTui};
|
||||||
|
|
||||||
|
pub mod jack; pub(crate) use self::jack::*;
|
||||||
|
pub use jack::JackClient;
|
||||||
|
|
||||||
|
pub mod midi; pub(crate) use self::midi::*;
|
||||||
|
|
||||||
|
pub mod audio; pub(crate) use self::audio::*;
|
||||||
|
pub use audio::{Sampler, Sample, Voice};
|
||||||
|
|
||||||
|
//pub mod plugin; pub(crate) use self::plugin::*;
|
||||||
|
|
||||||
pub use ::better_panic;
|
pub use ::better_panic;
|
||||||
pub(crate) use better_panic::{Settings, Verbosity};
|
pub(crate) use better_panic::{Settings, Verbosity};
|
||||||
|
|
@ -44,13 +50,12 @@ pub(crate) use ratatui::{
|
||||||
backend::{Backend, CrosstermBackend, ClearType}
|
backend::{Backend, CrosstermBackend, ClearType}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use ::midly;
|
pub use ::midly::{self, num::u7};
|
||||||
pub(crate) use ::midly::{
|
pub(crate) use ::midly::{
|
||||||
Smf,
|
Smf,
|
||||||
MidiMessage,
|
MidiMessage,
|
||||||
TrackEventKind,
|
TrackEventKind,
|
||||||
live::LiveEvent,
|
live::LiveEvent,
|
||||||
num::u7
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use ::palette;
|
pub use ::palette;
|
||||||
|
|
|
||||||
|
|
@ -40,22 +40,3 @@ impl LV2Plugin {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LV2Plugin {
|
|
||||||
pub fn from_edn <'e> (jack: &Arc<RwLock<JackClient>>, args: &[Edn<'e>]) -> Usually<Plugin> {
|
|
||||||
let mut name = String::new();
|
|
||||||
let mut path = String::new();
|
|
||||||
edn!(edn in args {
|
|
||||||
Edn::Map(map) => {
|
|
||||||
if let Some(Edn::Str(n)) = map.get(&Edn::Key(":name")) {
|
|
||||||
name = String::from(*n);
|
|
||||||
}
|
|
||||||
if let Some(Edn::Str(p)) = map.get(&Edn::Key(":path")) {
|
|
||||||
path = String::from(*p);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => panic!("unexpected in lv2 '{name}'"),
|
|
||||||
});
|
|
||||||
Plugin::new_lv2(jack, &name, &path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,19 @@ mod tui_border; pub(crate) use self::tui_border::*;
|
||||||
////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////
|
||||||
|
|
||||||
mod app_transport; #[allow(unused)] pub(crate) use self::app_transport::*;
|
mod app_transport; #[allow(unused)] pub(crate) use self::app_transport::*;
|
||||||
|
pub use self::app_transport::TransportTui;
|
||||||
|
|
||||||
mod app_sequencer; #[allow(unused)] pub(crate) use self::app_sequencer::*;
|
mod app_sequencer; #[allow(unused)] pub(crate) use self::app_sequencer::*;
|
||||||
|
pub use self::app_sequencer::SequencerTui;
|
||||||
|
|
||||||
mod app_sampler; #[allow(unused)] pub(crate) use self::app_sampler::*;
|
mod app_sampler; #[allow(unused)] pub(crate) use self::app_sampler::*;
|
||||||
|
pub use self::app_sampler::SamplerTui;
|
||||||
|
|
||||||
mod app_groovebox; #[allow(unused)] pub(crate) use self::app_groovebox::*;
|
mod app_groovebox; #[allow(unused)] pub(crate) use self::app_groovebox::*;
|
||||||
|
pub use self::app_groovebox::GrooveboxTui;
|
||||||
|
|
||||||
mod app_arranger; #[allow(unused)] pub(crate) use self::app_arranger::*;
|
mod app_arranger; #[allow(unused)] pub(crate) use self::app_arranger::*;
|
||||||
|
pub use self::app_arranger::ArrangerTui;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ use symphonia::{
|
||||||
},
|
},
|
||||||
default::get_codecs,
|
default::get_codecs,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct SamplerTui {
|
pub struct SamplerTui {
|
||||||
pub state: Sampler,
|
pub state: Sampler,
|
||||||
pub cursor: (usize, usize),
|
pub cursor: (usize, usize),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue