mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
wip: multi-crate refactor
This commit is contained in:
parent
911c47fc7c
commit
e08a79b507
25 changed files with 311 additions and 265 deletions
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)]
|
||||
#![allow(clippy::unit_arg)]
|
||||
include!("../lib.rs");
|
||||
include!("./lib.rs");
|
||||
use tek::tui::ArrangerTui;
|
||||
|
||||
pub fn main () -> Usually<()> {
|
||||
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)]
|
||||
#![allow(clippy::unit_arg)]
|
||||
include!("../lib.rs");
|
||||
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 {
|
||||
/// Name of JACK client
|
||||
#[arg(short, long)] name: Option<String>,
|
||||
/// Path to plugin
|
||||
#[arg(short, long)] path: Option<String>,
|
||||
}
|
||||
|
||||
impl SamplerCli {
|
||||
fn run (&self) -> Usually<()> {
|
||||
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(())
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
#![allow(unused)]
|
||||
#![allow(clippy::unit_arg)]
|
||||
include!("../lib.rs");
|
||||
include!("./lib.rs");
|
||||
|
||||
pub fn main () -> Usually<()> {
|
||||
SequencerCli::parse().run()
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
#![allow(unused)]
|
||||
#![allow(clippy::unit_arg)]
|
||||
include!("../lib.rs");
|
||||
include!("./lib.rs");
|
||||
|
||||
/// Application entrypoint.
|
||||
pub fn main () -> Usually<()> {
|
||||
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<()> {
|
||||
MixerCli::parse().run()
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::*;
|
||||
include!("./lib.rs");
|
||||
|
||||
pub fn main () -> Usually<()> {
|
||||
PluginCli::parse().run()
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::*;
|
||||
include!("./lib.rs");
|
||||
|
||||
pub fn main () -> Usually<()> {
|
||||
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::{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 {
|
||||
|
||||
////TODO
|
||||
|
|
@ -1,11 +1,12 @@
|
|||
[package]
|
||||
name = "suil-rs"
|
||||
name = "tek_suil"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
gtk = "0.18.1"
|
||||
livi = "0.7.4"
|
||||
#winit = { version = "0.30.4", features = [ "x11" ] }
|
||||
|
||||
[build-dependencies]
|
||||
bindgen = "0.69.4"
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ version = "0.2.0"
|
|||
atomic_float = "1.0.0"
|
||||
backtrace = "0.3.72"
|
||||
better-panic = "0.3.0"
|
||||
clap = { version = "4.5.4", features = [ "derive" ] }
|
||||
clojure-reader = "0.1.0"
|
||||
crossterm = "0.27"
|
||||
jack = "0.13"
|
||||
|
|
@ -29,37 +28,4 @@ wavers = "1.4.3"
|
|||
#winit = { version = "0.30.4", features = [ "x11" ] }
|
||||
|
||||
[lib]
|
||||
name = "tek_lib"
|
||||
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;
|
||||
pub(crate) mod audio_out;
|
||||
pub(crate) mod sampler; pub(crate) use sampler::*;
|
||||
use crate::*;
|
||||
|
||||
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 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 {
|
||||
fn boxed (self) -> Box<dyn MixerTrackDevice> where Self: Sized + 'static {
|
||||
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(crate) mod activate; #[allow(unused)] pub(crate) use self::activate::*;
|
||||
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::{
|
||||
pub use ::jack::{
|
||||
contrib::ClosureProcessHandler, NotificationHandler,
|
||||
Client, AsyncClient, ClientOptions, ClientStatus,
|
||||
ProcessScope, Control, CycleTimes, Frames,
|
||||
|
|
@ -12,6 +9,20 @@ pub(crate) use ::jack::{
|
|||
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.
|
||||
#[macro_export] macro_rules! from_jack {
|
||||
(|$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.
|
||||
|
|
|
|||
|
|
@ -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 time; pub(crate) use self::time::*;
|
||||
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(crate) use better_panic::{Settings, Verbosity};
|
||||
|
|
@ -44,13 +50,12 @@ pub(crate) use ratatui::{
|
|||
backend::{Backend, CrosstermBackend, ClearType}
|
||||
};
|
||||
|
||||
pub use ::midly;
|
||||
pub use ::midly::{self, num::u7};
|
||||
pub(crate) use ::midly::{
|
||||
Smf,
|
||||
MidiMessage,
|
||||
TrackEventKind,
|
||||
live::LiveEvent,
|
||||
num::u7
|
||||
};
|
||||
|
||||
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::*;
|
||||
pub use self::app_transport::TransportTui;
|
||||
|
||||
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::*;
|
||||
pub use self::app_sampler::SamplerTui;
|
||||
|
||||
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::*;
|
||||
pub use self::app_arranger::ArrangerTui;
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ use symphonia::{
|
|||
},
|
||||
default::get_codecs,
|
||||
};
|
||||
|
||||
pub struct SamplerTui {
|
||||
pub state: Sampler,
|
||||
pub cursor: (usize, usize),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue