1
0
Fork 0

Register JACK MIDI input and output ports

This commit is contained in:
Robbert van der Helm 2022-06-14 21:32:23 +02:00
parent c7f6aa15f8
commit 5cd4bb8de0
2 changed files with 31 additions and 6 deletions

View file

@ -70,7 +70,7 @@ pub fn nih_export_standalone_with_args<P: Plugin, Args: IntoIterator<Item = Stri
.unwrap_or_else(|err| err.exit());
match config.backend {
config::BackendType::Auto => match backend::Jack::new(P::NAME, config.clone()) {
config::BackendType::Auto => match backend::Jack::new::<P>(config.clone()) {
Ok(backend) => {
nih_log!("Using the JACK backend");
run_wrapper::<P, _>(backend, config)
@ -80,7 +80,7 @@ pub fn nih_export_standalone_with_args<P: Plugin, Args: IntoIterator<Item = Stri
run_wrapper::<P, _>(backend::Dummy::new(config.clone()), config)
}
},
config::BackendType::Jack => match backend::Jack::new(P::NAME, config.clone()) {
config::BackendType::Jack => match backend::Jack::new::<P>(config.clone()) {
Ok(backend) => run_wrapper::<P, _>(backend, config),
Err(err) => {
nih_error!("Could not initialize the JACK backend: {:#}", err);

View file

@ -3,11 +3,15 @@ use std::sync::Arc;
use anyhow::{Context, Result};
use atomic_refcell::AtomicRefCell;
use crossbeam::channel;
use jack::{AudioIn, AudioOut, Client, ClientOptions, ClosureProcessHandler, Control, Port};
use jack::{
AudioIn, AudioOut, Client, ClientOptions, ClosureProcessHandler, Control, MidiIn, MidiOut, Port,
};
use super::super::config::WrapperConfig;
use super::Backend;
use crate::buffer::Buffer;
use crate::midi::MidiConfig;
use crate::plugin::Plugin;
/// Uses JACK audio and MIDI.
pub struct Jack {
@ -17,6 +21,8 @@ pub struct Jack {
inputs: Arc<Vec<Port<AudioIn>>>,
outputs: Arc<AtomicRefCell<Vec<Port<AudioOut>>>>,
midi_input: Option<Arc<Port<MidiIn>>>,
midi_output: Option<Arc<AtomicRefCell<Port<MidiOut>>>>,
}
/// A simple message to tell the audio thread to shut down, since the actual processing happens in
@ -100,9 +106,11 @@ impl Backend for Jack {
}
impl Jack {
/// Initialize the JACK backend. Returns an error if this failed for whatever reason.
pub fn new(name: &str, config: WrapperConfig) -> Result<Self> {
let (client, status) = Client::new(name, ClientOptions::NO_START_SERVER)
/// Initialize the JACK backend. Returns an error if this failed for whatever reason. The plugin
/// generic argument is to get the name for the client, and to know whether or not the
/// standalone should expose JACK MIDI ports.
pub fn new<P: Plugin>(config: WrapperConfig) -> Result<Self> {
let (client, status) = Client::new(P::NAME, ClientOptions::NO_START_SERVER)
.context("Error while initializing the JACK client")?;
if !status.is_empty() {
anyhow::bail!("The JACK server returned an error: {status:?}");
@ -125,6 +133,21 @@ impl Jack {
outputs.push(port);
}
// TODO: CLI arguments to connect the MIDI input and output ports
let midi_input = if P::MIDI_INPUT >= MidiConfig::Basic {
Some(Arc::new(client.register_port("midi_input", MidiIn)?))
} else {
None
};
let midi_output = if P::MIDI_OUTPUT >= MidiConfig::Basic {
Some(Arc::new(AtomicRefCell::new(
client.register_port("midi_output", MidiOut)?,
)))
} else {
None
};
// This option can either be set to a single port all inputs should be connected to, or a
// comma separated list of ports
if let Some(port_name) = config.connect_jack_inputs {
@ -150,6 +173,8 @@ impl Jack {
inputs: Arc::new(inputs),
outputs: Arc::new(AtomicRefCell::new(outputs)),
midi_input,
midi_output,
})
}
}