use basedrop::Handle;
use cpal::traits::HostTrait;
use crate::standalone_cpal::StandaloneStartOptions;
use crate::standalone_processor::StandaloneOptions;
use audio_processor_traits::{AudioProcessor, MidiEventHandler};
use options::{ParseOptionsParams, RenderingOptions};
#[doc(inline)]
pub use standalone_cpal::{
audio_processor_start, audio_processor_start_with_midi, standalone_start,
standalone_start_with, StandaloneHandles,
};
#[doc(inline)]
pub use standalone_processor::{
StandaloneAudioOnlyProcessor, StandaloneProcessor, StandaloneProcessorImpl,
};
pub mod options;
pub mod standalone_cpal;
pub mod standalone_processor;
#[cfg(not(target_os = "ios"))]
pub mod offline;
#[cfg(all(feature = "vst", not(target_os = "ios")))]
pub mod standalone_vst;
#[cfg(feature = "clap")]
pub mod standalone_clap;
pub fn audio_processor_main_with_midi<
Processor: AudioProcessor<SampleType = f32> + MidiEventHandler + Send + 'static,
>(
audio_processor: Processor,
handle: &Handle,
) {
let app = StandaloneProcessorImpl::new(audio_processor);
standalone_main(app, Some(handle));
}
pub fn audio_processor_main<Processor: AudioProcessor<SampleType = f32> + Send + 'static>(
audio_processor: Processor,
) {
let options = options::parse_options(ParseOptionsParams {
supports_midi: false,
});
let app = StandaloneAudioOnlyProcessor::new(
audio_processor,
StandaloneOptions {
input_device: options.rendering().input_device(),
output_device: options.rendering().output_device(),
..Default::default()
},
);
standalone_main(app, None);
}
fn standalone_main<SP: StandaloneProcessor>(mut app: SP, handle: Option<&Handle>) {
let options = options::parse_options(ParseOptionsParams {
supports_midi: app.supports_midi(),
});
if handle_list_commands(&options) {
return;
}
match options.rendering() {
RenderingOptions::Online { .. } => {
log::info!("Starting stand-alone online rendering with default IO config");
let _handles = standalone_start_with::<SP, cpal::Host>(
app,
StandaloneStartOptions {
handle: handle.cloned(),
..StandaloneStartOptions::default()
},
);
std::thread::park();
}
#[cfg(not(target_os = "ios"))]
RenderingOptions::Offline {
input_file: input_path,
output_file: output_path,
} => {
#[cfg(feature = "midi")]
let midi_input_file = options.midi().input_file.as_ref().map(|midi_input_file| {
let file_contents =
std::fs::read(midi_input_file).expect("Failed to read input MIDI file");
let (_, midi_file) =
augmented_midi::parse_midi_file::<String, Vec<u8>>(&file_contents)
.expect("Failed to parse input MIDI file");
midi_file
});
offline::run_offline_render(offline::OfflineRenderOptions {
app,
handle,
input_path,
output_path,
#[cfg(feature = "midi")]
midi_input_file,
});
}
#[cfg(target_os = "ios")]
_ => {
log::error!("Offline rendering is unsupported on iOS");
std::process::exit(1)
}
}
}
fn handle_list_commands(options: &options::Options) -> bool {
if options.list_hosts() {
for host in cpal::available_hosts() {
println!("{:?}", host.name());
}
return true;
}
if options.list_input_devices() || options.list_output_devices() {
use cpal::traits::DeviceTrait;
let host = cpal::default_host();
let devices = if options.list_input_devices() {
host.input_devices()
} else {
host.output_devices()
};
for device in devices.expect("Failed to list devices") {
println!("{:?}", device.name().expect("Failed to get device name"));
}
return true;
}
false
}