From 191d5383bd9a4fead3259f74c24233a2083e7765 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Tue, 14 Jun 2022 17:19:09 +0200 Subject: [PATCH] Add boilerplate for an actual JACK implementation --- Cargo.lock | 27 +++++++++++++++++++++++++++ Cargo.toml | 3 ++- src/wrapper/standalone.rs | 4 ++-- src/wrapper/standalone/backend.rs | 20 +++++++++++++++----- src/wrapper/standalone/config.rs | 4 ++++ 5 files changed, 50 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1b455c91..e5295a02 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1772,6 +1772,32 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +[[package]] +name = "jack" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce722655a29b13bb98ec7e8ba9dc65d670b9b37c7b1c09775c7f7516811c5a36" +dependencies = [ + "bitflags", + "jack-sys", + "lazy_static", + "libc", + "log", +] + +[[package]] +name = "jack-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d70559ff166d148ccb750ddd77702af760718f3a752c731add168c22c16a9f" +dependencies = [ + "bitflags", + "lazy_static", + "libc", + "libloading", + "pkg-config", +] + [[package]] name = "jpeg-decoder" version = "0.1.22" @@ -2106,6 +2132,7 @@ dependencies = [ "clap", "clap-sys", "crossbeam", + "jack", "lazy_static", "libc", "log", diff --git a/Cargo.toml b/Cargo.toml index baeddfb4..7fead71c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,7 @@ assert_process_allocs = ["dep:assert_no_alloc"] # Enables an export target for standalone binaries through the # `nih_export_standalone()` function. Disabled by default, as this requires # building additional dependencies for audio and MIDI handling. -standalone = ["dep:anyhow", "dep:baseview", "dep:clap"] +standalone = ["dep:anyhow", "dep:baseview", "dep:clap", "dep:jack"] # Enables the `nih_export_vst3!()` macro. Enabled by default. This feature # exists mostly for GPL-compliance reasons, since even if you don't use the VST3 # wrapper you might otherwise still include a couple (unused) symbols from the @@ -89,6 +89,7 @@ anyhow = { version = "1.0", optional = true } baseview = { git = "https://github.com/robbert-vdh/baseview.git", branch = "feature/resize", features = ["opengl"], optional = true } # All the claps! clap = { version = "3.2", features = ["derive"], optional = true } +jack = { version = "0.10.0", optional = true } # Used for the `vst3` feature vst3-sys = { git = "https://github.com/robbert-vdh/vst3-sys.git", branch = "fix/note-off-event", optional = true } diff --git a/src/wrapper/standalone.rs b/src/wrapper/standalone.rs index a888418f..29d7dcab 100644 --- a/src/wrapper/standalone.rs +++ b/src/wrapper/standalone.rs @@ -70,14 +70,14 @@ pub fn nih_export_standalone_with_args match backend::Jack::new(config.clone()) { + config::BackendType::Auto => match backend::Jack::new(P::NAME, config.clone()) { Ok(backend) => run_wrapper::(backend, config), Err(_) => { nih_log!("Could not initialize JACK, falling back to the dummy audio backend"); run_wrapper::(backend::Dummy::new(config.clone()), config) } }, - config::BackendType::Jack => match backend::Jack::new(config.clone()) { + config::BackendType::Jack => match backend::Jack::new(P::NAME, config.clone()) { Ok(backend) => run_wrapper::(backend, config), Err(err) => { nih_error!("Could not initialize the JACK backend: {:#}", err); diff --git a/src/wrapper/standalone/backend.rs b/src/wrapper/standalone/backend.rs index 8b790457..1158d32f 100644 --- a/src/wrapper/standalone/backend.rs +++ b/src/wrapper/standalone/backend.rs @@ -1,4 +1,4 @@ -use anyhow::Result; +use anyhow::{Context, Result}; use std::time::{Duration, Instant}; use crate::buffer::Buffer; @@ -19,6 +19,7 @@ pub trait Backend: 'static + Send + Sync { /// Uses JACK audio and MIDI. pub struct Jack { config: WrapperConfig, + client: jack::Client, } /// This backend doesn't input or output any audio or MIDI. It only exists so the standalone @@ -30,6 +31,7 @@ pub struct Dummy { impl Backend for Jack { fn run(&mut self, cb: impl FnMut(&mut Buffer) -> bool) { + // TODO: Create an async client and do The Thing (tm) todo!() } } @@ -75,10 +77,18 @@ impl Backend for Dummy { impl Jack { /// Initialize the JACK backend. Returns an error if this failed for whatever reason. - pub fn new(config: WrapperConfig) -> Result { - // TODO: Actually implement the JACK backend - anyhow::bail!("Not yet implemented") - // Ok(Self { config }) + pub fn new(name: &str, config: WrapperConfig) -> Result { + let (client, status) = jack::Client::new(name, jack::ClientOptions::NO_START_SERVER) + .context("Error while initializing the JACK client")?; + if !status.is_empty() { + anyhow::bail!("The JACK server returned an error: {status:?}"); + } + + // TODO: Register ports + // TODO: Connect output + // TODO: Command line argument to connect the inputs? + + Ok(Self { config, client }) } } diff --git a/src/wrapper/standalone/config.rs b/src/wrapper/standalone/config.rs index 1ce29b4e..798a3f44 100644 --- a/src/wrapper/standalone/config.rs +++ b/src/wrapper/standalone/config.rs @@ -18,9 +18,13 @@ pub struct WrapperConfig { #[clap(value_parser, short = 'o', long, default_value = "2")] pub output_channels: u32, /// The audio backend's sample rate. + /// + /// This setting is ignored when using the JACK backend. #[clap(value_parser, short = 'r', long, default_value = "44100")] pub sample_rate: f32, /// The audio backend's period size. + /// + /// This setting is ignored when using the JACK backend. #[clap(value_parser, short = 'p', long, default_value = "512")] pub period_size: u32,