use crate::plugin::{BusInfo, BusLayout, BusType, Descriptor};
use crate::types::{MAX_BUSES, MAX_CHANNELS};
#[derive(Clone, Copy, Debug, Default)]
pub struct CachedBusInfo {
pub channel_count: usize,
pub bus_type: BusType,
}
impl CachedBusInfo {
pub const fn new(channel_count: usize, bus_type: BusType) -> Self {
Self {
channel_count,
bus_type,
}
}
pub fn from_bus_info(info: &BusInfo) -> Self {
Self {
channel_count: info.channel_count as usize,
bus_type: info.bus_type,
}
}
}
#[derive(Clone, Debug)]
pub struct CachedBusConfig {
pub input_bus_count: usize,
pub output_bus_count: usize,
pub input_buses: Vec<CachedBusInfo>,
pub output_buses: Vec<CachedBusInfo>,
}
impl CachedBusConfig {
pub fn new(input_buses: Vec<CachedBusInfo>, output_buses: Vec<CachedBusInfo>) -> Self {
assert!(
input_buses.len() <= MAX_BUSES,
"Input bus count {} exceeds MAX_BUSES ({})",
input_buses.len(),
MAX_BUSES
);
assert!(
output_buses.len() <= MAX_BUSES,
"Output bus count {} exceeds MAX_BUSES ({})",
output_buses.len(),
MAX_BUSES
);
Self {
input_bus_count: input_buses.len(),
output_bus_count: output_buses.len(),
input_buses,
output_buses,
}
}
pub fn from_plugin<P: Descriptor>(plugin: &P) -> Self {
let input_bus_count = plugin.input_bus_count();
let output_bus_count = plugin.output_bus_count();
let input_buses: Vec<CachedBusInfo> = (0..input_bus_count)
.filter_map(|i| plugin.input_bus_info(i).map(|b| CachedBusInfo::from_bus_info(&b)))
.collect();
let output_buses: Vec<CachedBusInfo> = (0..output_bus_count)
.filter_map(|i| plugin.output_bus_info(i).map(|b| CachedBusInfo::from_bus_info(&b)))
.collect();
Self {
input_bus_count,
output_bus_count,
input_buses,
output_buses,
}
}
pub fn input_bus_info(&self, bus: usize) -> Option<&CachedBusInfo> {
self.input_buses.get(bus)
}
pub fn output_bus_info(&self, bus: usize) -> Option<&CachedBusInfo> {
self.output_buses.get(bus)
}
pub fn total_input_channels(&self) -> usize {
self.input_buses.iter().map(|b| b.channel_count).sum()
}
pub fn total_output_channels(&self) -> usize {
self.output_buses.iter().map(|b| b.channel_count).sum()
}
pub fn to_bus_layout(&self) -> BusLayout {
BusLayout {
main_input_channels: self
.input_bus_info(0)
.map(|b| b.channel_count as u32)
.unwrap_or(0),
main_output_channels: self
.output_bus_info(0)
.map(|b| b.channel_count as u32)
.unwrap_or(0),
aux_input_count: self.input_bus_count.saturating_sub(1),
aux_output_count: self.output_bus_count.saturating_sub(1),
}
}
pub fn validate(&self) -> Result<(), String> {
if self.input_bus_count > MAX_BUSES {
return Err(format!(
"Plugin declares {} input buses, but MAX_BUSES is {}",
self.input_bus_count, MAX_BUSES
));
}
if self.output_bus_count > MAX_BUSES {
return Err(format!(
"Plugin declares {} output buses, but MAX_BUSES is {}",
self.output_bus_count, MAX_BUSES
));
}
for (i, bus) in self.input_buses.iter().enumerate() {
if bus.channel_count > MAX_CHANNELS {
return Err(format!(
"Input bus {} declares {} channels, but MAX_CHANNELS is {}",
i, bus.channel_count, MAX_CHANNELS
));
}
}
for (i, bus) in self.output_buses.iter().enumerate() {
if bus.channel_count > MAX_CHANNELS {
return Err(format!(
"Output bus {} declares {} channels, but MAX_CHANNELS is {}",
i, bus.channel_count, MAX_CHANNELS
));
}
}
Ok(())
}
}
impl Default for CachedBusConfig {
fn default() -> Self {
Self::new(
vec![CachedBusInfo::new(2, BusType::Main)],
vec![CachedBusInfo::new(2, BusType::Main)],
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = CachedBusConfig::default();
assert_eq!(config.input_bus_count, 1);
assert_eq!(config.output_bus_count, 1);
assert_eq!(config.total_input_channels(), 2);
assert_eq!(config.total_output_channels(), 2);
}
#[test]
fn test_validate_success() {
let config = CachedBusConfig::default();
assert!(config.validate().is_ok());
}
#[test]
fn test_to_bus_layout() {
let config = CachedBusConfig::new(
vec![
CachedBusInfo::new(2, BusType::Main),
CachedBusInfo::new(2, BusType::Aux),
],
vec![CachedBusInfo::new(2, BusType::Main)],
);
let layout = config.to_bus_layout();
assert_eq!(layout.main_input_channels, 2);
assert_eq!(layout.main_output_channels, 2);
assert_eq!(layout.aux_input_count, 1);
assert_eq!(layout.aux_output_count, 0);
}
#[test]
fn test_cached_bus_info_from_bus_info() {
let bus_info = BusInfo {
name: "Test Bus",
bus_type: BusType::Aux,
channel_count: 4,
is_default_active: true,
};
let cached = CachedBusInfo::from_bus_info(&bus_info);
assert_eq!(cached.channel_count, 4);
assert_eq!(cached.bus_type, BusType::Aux);
}
#[test]
fn test_empty_config() {
let config = CachedBusConfig::new(vec![], vec![]);
assert_eq!(config.input_bus_count, 0);
assert_eq!(config.output_bus_count, 0);
assert_eq!(config.total_input_channels(), 0);
assert_eq!(config.total_output_channels(), 0);
assert!(config.validate().is_ok());
}
}