use clap::{CommandFactory, FromArgMatches};
use nice_plug_core::plugin::Plugin;
use self::backend::Backend;
use self::config::WrapperConfig;
use self::wrapper::{Wrapper, WrapperError};
use super::util::setup_logger;
mod backend;
mod config;
mod context;
mod wrapper;
pub fn nice_export_standalone<P: Plugin>() -> bool {
nice_export_standalone_with_args::<P, _>(std::env::args())
}
pub fn nice_export_standalone_with_args<P: Plugin, Args: IntoIterator<Item = String>>(
args: Args,
) -> bool {
setup_logger();
let config = WrapperConfig::from_arg_matches(
&WrapperConfig::command()
.name(P::NAME)
.author(P::VENDOR)
.get_matches_from(args),
)
.unwrap_or_else(|err| err.exit());
match config.backend {
config::BackendType::Auto => {
let result = backend::Jack::new::<P>(config.clone()).map(|backend| {
crate::nice_log!("Using the JACK backend");
run_wrapper::<P, _>(backend, config.clone())
});
#[cfg(all(target_family = "unix", not(target_os = "macos")))]
let result = result.or_else(|_| {
match backend::CpalMidir::new::<P>(config.clone(), cpal::HostId::Alsa) {
Ok(backend) => {
crate::nice_log!("Using the ALSA backend");
Ok(run_wrapper::<P, _>(backend, config.clone()))
}
Err(err) => {
use nice_plug_core::nice_error;
nice_error!(
"Could not initialize either the JACK or the ALSA backends, falling \
back to the dummy audio backend: {err:#}"
);
Err(())
}
}
});
#[cfg(target_os = "macos")]
let result = result.or_else(|_| {
match backend::CpalMidir::new::<P>(config.clone(), cpal::HostId::CoreAudio) {
Ok(backend) => {
crate::nice_log!("Using the CoreAudio backend");
Ok(run_wrapper::<P, _>(backend, config.clone()))
}
Err(err) => {
crate::nice_error!(
"Could not initialize either the JACK or the CoreAudio backends, \
falling back to the dummy audio backend: {err:#}"
);
Err(())
}
}
});
#[cfg(target_os = "windows")]
let result = result.or_else(|_| {
match backend::CpalMidir::new::<P>(config.clone(), cpal::HostId::Wasapi) {
Ok(backend) => {
crate::nice_log!("Using the WASAPI backend");
Ok(run_wrapper::<P, _>(backend, config.clone()))
}
Err(err) => {
crate::nice_error!(
"Could not initialize either the JACK or the WASAPI backends, falling \
back to the dummy audio backend: {err:#}"
);
Err(())
}
}
});
result.unwrap_or_else(|_| {
crate::nice_error!(
"Falling back to the dummy audio backend, audio and MIDI will not work"
);
run_wrapper::<P, _>(backend::Dummy::new::<P>(config.clone()), config)
})
}
config::BackendType::Jack => match backend::Jack::new::<P>(config.clone()) {
Ok(backend) => run_wrapper::<P, _>(backend, config),
Err(err) => {
crate::nice_error!("Could not initialize the JACK backend: {:#}", err);
false
}
},
#[cfg(all(target_family = "unix", not(target_os = "macos")))]
config::BackendType::Alsa => {
match backend::CpalMidir::new::<P>(config.clone(), cpal::HostId::Alsa) {
Ok(backend) => run_wrapper::<P, _>(backend, config),
Err(err) => {
crate::nice_error!("Could not initialize the ALSA backend: {:#}", err);
false
}
}
}
#[cfg(target_os = "macos")]
config::BackendType::CoreAudio => {
match backend::CpalMidir::new::<P>(config.clone(), cpal::HostId::CoreAudio) {
Ok(backend) => run_wrapper::<P, _>(backend, config),
Err(err) => {
crate::nice_error!("Could not initialize the CoreAudio backend: {:#}", err);
false
}
}
}
#[cfg(target_os = "windows")]
config::BackendType::Wasapi => {
match backend::CpalMidir::new::<P>(config.clone(), cpal::HostId::Wasapi) {
Ok(backend) => run_wrapper::<P, _>(backend, config),
Err(err) => {
crate::nice_error!("Could not initialize the WASAPI backend: {:#}", err);
false
}
}
}
config::BackendType::Dummy => {
run_wrapper::<P, _>(backend::Dummy::new::<P>(config.clone()), config)
}
}
}
fn run_wrapper<P: Plugin, B: Backend<P>>(backend: B, config: WrapperConfig) -> bool {
let wrapper = match Wrapper::<P, _>::new(backend, config) {
Ok(wrapper) => wrapper,
Err(err) => {
print_error(err);
return false;
}
};
match wrapper.run() {
Ok(()) => true,
Err(err) => {
print_error(err);
false
}
}
}
fn print_error(error: WrapperError) {
match error {
WrapperError::InitializationFailed => {
crate::nice_error!("The plugin failed to initialize");
}
}
}