use std::num::NonZeroU32;
use crate::buffer::Buffer;
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub struct AudioIOLayout {
pub main_input_channels: Option<NonZeroU32>,
pub main_output_channels: Option<NonZeroU32>,
pub aux_input_ports: &'static [NonZeroU32],
pub aux_output_ports: &'static [NonZeroU32],
pub names: PortNames,
}
pub const fn new_nonzero_u32(n: u32) -> NonZeroU32 {
match NonZeroU32::new(n) {
Some(n) => n,
None => panic!("'new_nonzero_u32()' called with a zero value"),
}
}
pub struct AuxiliaryBuffers<'a> {
pub inputs: &'a mut [Buffer<'a>],
pub outputs: &'a mut [Buffer<'a>],
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub struct PortNames {
pub layout: Option<&'static str>,
pub main_input: Option<&'static str>,
pub main_output: Option<&'static str>,
pub aux_inputs: &'static [&'static str],
pub aux_outputs: &'static [&'static str],
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct BufferConfig {
pub sample_rate: f32,
pub min_buffer_size: Option<u32>,
pub max_buffer_size: u32,
pub process_mode: ProcessMode,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ProcessMode {
Realtime,
Buffered,
Offline,
}
impl AudioIOLayout {
pub const fn const_default() -> Self {
Self {
main_input_channels: None,
main_output_channels: None,
aux_input_ports: &[],
aux_output_ports: &[],
names: PortNames::const_default(),
}
}
pub fn name(&self) -> String {
if let Some(name) = self.names.layout {
return name.to_owned();
}
match (
self.main_input_channels
.map(NonZeroU32::get)
.unwrap_or_default(),
self.main_output_channels
.map(NonZeroU32::get)
.unwrap_or_default(),
self.aux_input_ports.len(),
self.aux_output_ports.len(),
) {
(0, 0, 0, 0) => String::from("Empty"),
(_, 1, 0, _) | (1, 0, _, _) => String::from("Mono"),
(_, 2, 0, _) | (2, 0, _, _) => String::from("Stereo"),
(_, 1, _, _) => String::from("Mono with sidechain"),
(_, 2, _, _) => String::from("Stereo with sidechain"),
(i, o, 0, 0) => format!("{i} inputs, {o} outputs"),
(i, o, _, 0) => format!("{i} inputs, {o} outputs, with sidechain"),
(i, o, 0, aux_o) => format!("{i} inputs, {o}*{} outputs", aux_o + 1),
(i, o, aux_i, aux_o) => format!("{i}*{} inputs, {o}*{} outputs", aux_i + 1, aux_o + 1),
}
}
pub fn main_input_name(&self) -> String {
self.names.main_input.unwrap_or("Input").to_owned()
}
pub fn main_output_name(&self) -> String {
self.names.main_input.unwrap_or("Output").to_owned()
}
pub fn aux_input_name(&self, idx: usize) -> Option<String> {
if idx >= self.aux_input_ports.len() {
None
} else {
match self.names.aux_inputs.get(idx) {
Some(name) => Some(String::from(*name)),
None if self.aux_input_ports.len() == 1 => Some(String::from("Sidechain Input")),
None => Some(format!("Sidechain Input {}", idx + 1)),
}
}
}
pub fn aux_output_name(&self, idx: usize) -> Option<String> {
if idx >= self.aux_output_ports.len() {
None
} else {
match self.names.aux_outputs.get(idx) {
Some(name) => Some(String::from(*name)),
None if self.aux_output_ports.len() == 1 => Some(String::from("Auxiliary Output")),
None => Some(format!("Auxiliary Output {}", idx + 1)),
}
}
}
}
impl PortNames {
pub const fn const_default() -> Self {
Self {
layout: None,
main_input: None,
main_output: None,
aux_inputs: &[],
aux_outputs: &[],
}
}
}