1use crate::plugin::{BusInfo, BusLayout, BusType, Descriptor};
8use crate::types::{MAX_BUSES, MAX_CHANNELS};
9
10#[derive(Clone, Copy, Debug, Default)]
16pub struct CachedBusInfo {
17 pub channel_count: usize,
19 pub bus_type: BusType,
21}
22
23impl CachedBusInfo {
24 pub const fn new(channel_count: usize, bus_type: BusType) -> Self {
26 Self {
27 channel_count,
28 bus_type,
29 }
30 }
31
32 pub fn from_bus_info(info: &BusInfo) -> Self {
34 Self {
35 channel_count: info.channel_count as usize,
36 bus_type: info.bus_type,
37 }
38 }
39}
40
41#[derive(Clone, Debug)]
46pub struct CachedBusConfig {
47 pub input_bus_count: usize,
49 pub output_bus_count: usize,
51 pub input_buses: Vec<CachedBusInfo>,
53 pub output_buses: Vec<CachedBusInfo>,
55}
56
57impl CachedBusConfig {
58 pub fn new(input_buses: Vec<CachedBusInfo>, output_buses: Vec<CachedBusInfo>) -> Self {
64 assert!(
65 input_buses.len() <= MAX_BUSES,
66 "Input bus count {} exceeds MAX_BUSES ({})",
67 input_buses.len(),
68 MAX_BUSES
69 );
70 assert!(
71 output_buses.len() <= MAX_BUSES,
72 "Output bus count {} exceeds MAX_BUSES ({})",
73 output_buses.len(),
74 MAX_BUSES
75 );
76
77 Self {
78 input_bus_count: input_buses.len(),
79 output_bus_count: output_buses.len(),
80 input_buses,
81 output_buses,
82 }
83 }
84
85 pub fn from_plugin<P: Descriptor>(plugin: &P) -> Self {
87 let input_bus_count = plugin.input_bus_count();
88 let output_bus_count = plugin.output_bus_count();
89
90 let input_buses: Vec<CachedBusInfo> = (0..input_bus_count)
91 .filter_map(|i| plugin.input_bus_info(i).map(|b| CachedBusInfo::from_bus_info(&b)))
92 .collect();
93
94 let output_buses: Vec<CachedBusInfo> = (0..output_bus_count)
95 .filter_map(|i| plugin.output_bus_info(i).map(|b| CachedBusInfo::from_bus_info(&b)))
96 .collect();
97
98 Self {
99 input_bus_count,
100 output_bus_count,
101 input_buses,
102 output_buses,
103 }
104 }
105
106 pub fn input_bus_info(&self, bus: usize) -> Option<&CachedBusInfo> {
110 self.input_buses.get(bus)
111 }
112
113 pub fn output_bus_info(&self, bus: usize) -> Option<&CachedBusInfo> {
117 self.output_buses.get(bus)
118 }
119
120 pub fn total_input_channels(&self) -> usize {
122 self.input_buses.iter().map(|b| b.channel_count).sum()
123 }
124
125 pub fn total_output_channels(&self) -> usize {
127 self.output_buses.iter().map(|b| b.channel_count).sum()
128 }
129
130 pub fn to_bus_layout(&self) -> BusLayout {
135 BusLayout {
136 main_input_channels: self
137 .input_bus_info(0)
138 .map(|b| b.channel_count as u32)
139 .unwrap_or(0),
140 main_output_channels: self
141 .output_bus_info(0)
142 .map(|b| b.channel_count as u32)
143 .unwrap_or(0),
144 aux_input_count: self.input_bus_count.saturating_sub(1),
145 aux_output_count: self.output_bus_count.saturating_sub(1),
146 }
147 }
148
149 pub fn validate(&self) -> Result<(), String> {
157 if self.input_bus_count > MAX_BUSES {
159 return Err(format!(
160 "Plugin declares {} input buses, but MAX_BUSES is {}",
161 self.input_bus_count, MAX_BUSES
162 ));
163 }
164 if self.output_bus_count > MAX_BUSES {
165 return Err(format!(
166 "Plugin declares {} output buses, but MAX_BUSES is {}",
167 self.output_bus_count, MAX_BUSES
168 ));
169 }
170
171 for (i, bus) in self.input_buses.iter().enumerate() {
173 if bus.channel_count > MAX_CHANNELS {
174 return Err(format!(
175 "Input bus {} declares {} channels, but MAX_CHANNELS is {}",
176 i, bus.channel_count, MAX_CHANNELS
177 ));
178 }
179 }
180
181 for (i, bus) in self.output_buses.iter().enumerate() {
183 if bus.channel_count > MAX_CHANNELS {
184 return Err(format!(
185 "Output bus {} declares {} channels, but MAX_CHANNELS is {}",
186 i, bus.channel_count, MAX_CHANNELS
187 ));
188 }
189 }
190
191 Ok(())
192 }
193}
194
195impl Default for CachedBusConfig {
196 fn default() -> Self {
198 Self::new(
199 vec![CachedBusInfo::new(2, BusType::Main)],
200 vec![CachedBusInfo::new(2, BusType::Main)],
201 )
202 }
203}
204
205#[cfg(test)]
206mod tests {
207 use super::*;
208
209 #[test]
210 fn test_default_config() {
211 let config = CachedBusConfig::default();
212 assert_eq!(config.input_bus_count, 1);
213 assert_eq!(config.output_bus_count, 1);
214 assert_eq!(config.total_input_channels(), 2);
215 assert_eq!(config.total_output_channels(), 2);
216 }
217
218 #[test]
219 fn test_validate_success() {
220 let config = CachedBusConfig::default();
221 assert!(config.validate().is_ok());
222 }
223
224 #[test]
225 fn test_to_bus_layout() {
226 let config = CachedBusConfig::new(
227 vec![
228 CachedBusInfo::new(2, BusType::Main),
229 CachedBusInfo::new(2, BusType::Aux),
230 ],
231 vec![CachedBusInfo::new(2, BusType::Main)],
232 );
233 let layout = config.to_bus_layout();
234 assert_eq!(layout.main_input_channels, 2);
235 assert_eq!(layout.main_output_channels, 2);
236 assert_eq!(layout.aux_input_count, 1);
237 assert_eq!(layout.aux_output_count, 0);
238 }
239
240 #[test]
241 fn test_cached_bus_info_from_bus_info() {
242 let bus_info = BusInfo {
243 name: "Test Bus",
244 bus_type: BusType::Aux,
245 channel_count: 4,
246 is_default_active: true,
247 };
248 let cached = CachedBusInfo::from_bus_info(&bus_info);
249 assert_eq!(cached.channel_count, 4);
250 assert_eq!(cached.bus_type, BusType::Aux);
251 }
252
253 #[test]
254 fn test_empty_config() {
255 let config = CachedBusConfig::new(vec![], vec![]);
256 assert_eq!(config.input_bus_count, 0);
257 assert_eq!(config.output_bus_count, 0);
258 assert_eq!(config.total_input_channels(), 0);
259 assert_eq!(config.total_output_channels(), 0);
260 assert!(config.validate().is_ok());
261 }
262}