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 renamed to `Plugin::DEFAULT_INPUT_CHANNELS` and
`Plugin::DEFAULT_OUTPUT_CHANNELS` respectively to avoid confusion as these `Plugin::DEFAULT_OUTPUT_CHANNELS` respectively to avoid confusion as these
constants only affect the main input and output. 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] ## [2022-07-18]

View file

@ -77,7 +77,7 @@ pub fn nih_export_standalone_with_args<P: Plugin, Args: IntoIterator<Item = Stri
} }
Err(_) => { Err(_) => {
nih_log!("Could not initialize JACK, falling back to the dummy audio backend"); 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()) { 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 => { 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) { fn print_error(error: WrapperError, config: &WrapperConfig) {
match error { match error {
WrapperError::IncompatibleConfig => { WrapperError::IncompatibleConfig {
input_channels,
output_channels,
} => {
nih_error!( nih_error!(
"The plugin does not support the {} channel input and {} channel output \ "The plugin does not support the {input_channels} channel input and \
configuration", {output_channels} channel output configuration",
config.input_channels,
config.output_channels
); );
} }
WrapperError::InitializationFailed => { WrapperError::InitializationFailed => {

View file

@ -5,12 +5,14 @@ use super::Backend;
use crate::buffer::Buffer; use crate::buffer::Buffer;
use crate::context::Transport; use crate::context::Transport;
use crate::midi::NoteEvent; 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 /// 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 /// application can continue to run even when there is no audio backend available. This can be
/// useful for testing plugin GUIs. /// useful for testing plugin GUIs.
pub struct Dummy { pub struct Dummy {
config: WrapperConfig, config: WrapperConfig,
bus_config: BusConfig,
} }
impl Backend for Dummy { impl Backend for Dummy {
@ -27,7 +29,7 @@ impl Backend for Dummy {
let mut channels = vec![ let mut channels = vec![
vec![0.0f32; self.config.period_size as usize]; 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(); let mut buffer = Buffer::default();
unsafe { unsafe {
@ -71,7 +73,16 @@ impl Backend for Dummy {
} }
impl Dummy { impl Dummy {
pub fn new(config: WrapperConfig) -> Self { pub fn new<P: Plugin>(config: WrapperConfig) -> Self {
Self { config } 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(); 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)?); 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 // no. So the connections are made just after activating the client in the `run()` function
// above. // above.
let mut outputs = Vec::new(); 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)?); 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")] #[clap(value_parser, short = 'b', long, default_value = "auto")]
pub backend: BackendType, 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. /// The number of input channels.
#[clap(value_parser, short = 'i', long, default_value = "2")] #[clap(value_parser, short = 'i', long)]
pub input_channels: u32, pub input_channels: Option<u32>,
/// The number of output channels. /// The number of output channels.
#[clap(value_parser, short = 'o', long, default_value = "2")] #[clap(value_parser, short = 'o', long)]
pub output_channels: u32, pub output_channels: Option<u32>,
/// The audio backend's sample rate. /// The audio backend's sample rate.
/// ///
/// This setting is ignored when using the JACK backend. /// 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)] #[derive(Debug, Clone, Copy)]
pub enum WrapperError { pub enum WrapperError {
/// The plugin does not accept the IO configuration from the config. /// 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. /// The plugin returned `false` during initialization.
InitializationFailed, InitializationFailed,
} }
@ -174,8 +177,8 @@ impl<P: Plugin, B: Backend> Wrapper<P, B> {
editor, editor,
bus_config: BusConfig { bus_config: BusConfig {
num_input_channels: config.input_channels, num_input_channels: config.input_channels.unwrap_or(P::DEFAULT_INPUT_CHANNELS),
num_output_channels: config.output_channels, num_output_channels: config.output_channels.unwrap_or(P::DEFAULT_OUTPUT_CHANNELS),
// TODO: Expose additional sidechain IO in the JACK backend // TODO: Expose additional sidechain IO in the JACK backend
aux_input_busses: AuxiliaryIOConfig::default(), aux_input_busses: AuxiliaryIOConfig::default(),
aux_output_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(); let mut plugin = wrapper.plugin.write();
if !plugin.accepts_bus_config(&wrapper.bus_config) { 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 // Befure initializing the plugin, make sure all smoothers are set the the default values