1
0
Fork 0

Use the plugin's default channels for standalones

This commit is contained in:
Robbert van der Helm 2022-08-19 14:52:57 +02:00
parent 1a706ea1c7
commit a5c05b22fb
6 changed files with 45 additions and 20 deletions

View file

@ -12,6 +12,8 @@ code then it will not be listed here.
renamed to `Plugin::DEFAULT_INPUT_CHANNELS` and
`Plugin::DEFAULT_OUTPUT_CHANNELS` respectively to avoid confusion as these
constants only affect the main input and output.
- Standalones now use the plugin's default input and output channel counts
instead of always defaulting to two inputs and two outputs.
## [2022-07-18]

View file

@ -77,7 +77,7 @@ pub fn nih_export_standalone_with_args<P: Plugin, Args: IntoIterator<Item = Stri
}
Err(_) => {
nih_log!("Could not initialize JACK, falling back to the dummy audio backend");
run_wrapper::<P, _>(backend::Dummy::new(config.clone()), config)
run_wrapper::<P, _>(backend::Dummy::new::<P>(config.clone()), config)
}
},
config::BackendType::Jack => match backend::Jack::new::<P>(config.clone()) {
@ -88,7 +88,7 @@ pub fn nih_export_standalone_with_args<P: Plugin, Args: IntoIterator<Item = Stri
}
},
config::BackendType::Dummy => {
run_wrapper::<P, _>(backend::Dummy::new(config.clone()), config)
run_wrapper::<P, _>(backend::Dummy::new::<P>(config.clone()), config)
}
}
}
@ -114,12 +114,13 @@ fn run_wrapper<P: Plugin, B: Backend>(backend: B, config: WrapperConfig) -> bool
fn print_error(error: WrapperError, config: &WrapperConfig) {
match error {
WrapperError::IncompatibleConfig => {
WrapperError::IncompatibleConfig {
input_channels,
output_channels,
} => {
nih_error!(
"The plugin does not support the {} channel input and {} channel output \
configuration",
config.input_channels,
config.output_channels
"The plugin does not support the {input_channels} channel input and \
{output_channels} channel output configuration",
);
}
WrapperError::InitializationFailed => {

View file

@ -5,12 +5,14 @@ use super::Backend;
use crate::buffer::Buffer;
use crate::context::Transport;
use crate::midi::NoteEvent;
use crate::plugin::{AuxiliaryIOConfig, BusConfig, Plugin};
/// This backend doesn't input or output any audio or MIDI. It only exists so the standalone
/// application can continue to run even when there is no audio backend available. This can be
/// useful for testing plugin GUIs.
pub struct Dummy {
config: WrapperConfig,
bus_config: BusConfig,
}
impl Backend for Dummy {
@ -27,7 +29,7 @@ impl Backend for Dummy {
let mut channels = vec![
vec![0.0f32; self.config.period_size as usize];
self.config.output_channels as usize
self.bus_config.num_output_channels as usize
];
let mut buffer = Buffer::default();
unsafe {
@ -71,7 +73,16 @@ impl Backend for Dummy {
}
impl Dummy {
pub fn new(config: WrapperConfig) -> Self {
Self { config }
pub fn new<P: Plugin>(config: WrapperConfig) -> Self {
Self {
bus_config: BusConfig {
num_input_channels: config.input_channels.unwrap_or(P::DEFAULT_INPUT_CHANNELS),
num_output_channels: config.output_channels.unwrap_or(P::DEFAULT_OUTPUT_CHANNELS),
// TODO: Support these in the standalone
aux_input_busses: AuxiliaryIOConfig::default(),
aux_output_busses: AuxiliaryIOConfig::default(),
},
config,
}
}
}

View file

@ -188,7 +188,8 @@ impl Jack {
}
let mut inputs = Vec::new();
for port_no in 1..config.input_channels + 1 {
let num_input_channels = config.input_channels.unwrap_or(P::DEFAULT_INPUT_CHANNELS);
for port_no in 1..num_input_channels + 1 {
inputs.push(client.register_port(&format!("input_{port_no}"), AudioIn)?);
}
@ -196,7 +197,8 @@ impl Jack {
// no. So the connections are made just after activating the client in the `run()` function
// above.
let mut outputs = Vec::new();
for port_no in 1..config.output_channels + 1 {
let num_output_channels = config.output_channels.unwrap_or(P::DEFAULT_OUTPUT_CHANNELS);
for port_no in 1..num_output_channels + 1 {
outputs.push(client.register_port(&format!("output_{port_no}"), AudioOut)?);
}

View file

@ -11,12 +11,15 @@ pub struct WrapperConfig {
#[clap(value_parser, short = 'b', long, default_value = "auto")]
pub backend: BackendType,
// These will default to the plugin's default input and output channel count. We could set the
// default value here to match those, but that would require a custom Args+FromArgMatches
// implementation and access to the `Plugin` type.
/// The number of input channels.
#[clap(value_parser, short = 'i', long, default_value = "2")]
pub input_channels: u32,
#[clap(value_parser, short = 'i', long)]
pub input_channels: Option<u32>,
/// The number of output channels.
#[clap(value_parser, short = 'o', long, default_value = "2")]
pub output_channels: u32,
#[clap(value_parser, short = 'o', long)]
pub output_channels: Option<u32>,
/// The audio backend's sample rate.
///
/// This setting is ignored when using the JACK backend.

View file

@ -75,7 +75,10 @@ pub struct Wrapper<P: Plugin, B: Backend> {
#[derive(Debug, Clone, Copy)]
pub enum WrapperError {
/// The plugin does not accept the IO configuration from the config.
IncompatibleConfig,
IncompatibleConfig {
input_channels: u32,
output_channels: u32,
},
/// The plugin returned `false` during initialization.
InitializationFailed,
}
@ -174,8 +177,8 @@ impl<P: Plugin, B: Backend> Wrapper<P, B> {
editor,
bus_config: BusConfig {
num_input_channels: config.input_channels,
num_output_channels: config.output_channels,
num_input_channels: config.input_channels.unwrap_or(P::DEFAULT_INPUT_CHANNELS),
num_output_channels: config.output_channels.unwrap_or(P::DEFAULT_OUTPUT_CHANNELS),
// TODO: Expose additional sidechain IO in the JACK backend
aux_input_busses: AuxiliaryIOConfig::default(),
aux_output_busses: AuxiliaryIOConfig::default(),
@ -199,7 +202,10 @@ impl<P: Plugin, B: Backend> Wrapper<P, B> {
{
let mut plugin = wrapper.plugin.write();
if !plugin.accepts_bus_config(&wrapper.bus_config) {
return Err(WrapperError::IncompatibleConfig);
return Err(WrapperError::IncompatibleConfig {
input_channels: wrapper.bus_config.num_input_channels,
output_channels: wrapper.bus_config.num_output_channels,
});
}
// Befure initializing the plugin, make sure all smoothers are set the the default values