1use super::effects::{self, Change};
3use super::queue::{self, Consumer, Producer, PushError};
4use super::{Action, BLOCK, BusId, Commands, Mixer, MixerEvent, MixerHandle};
5use crate::{Error, ErrorCode, Result};
6use std::collections::VecDeque;
7use std::sync::Arc;
8use std::sync::atomic::{AtomicUsize, Ordering};
9
10pub const MAX_BUS_ROUTES: usize = 1024;
12#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
15pub enum SendPosition {
16 PreFader,
17 #[default]
18 PostFader,
19}
20#[derive(Clone, Copy, Debug, PartialEq)]
21pub struct BusSend {
22 pub destination: BusId,
23 pub gain: f32,
25 pub position: SendPosition,
26}
27#[derive(Clone, Debug, PartialEq)]
31pub struct BusRouting {
32 pub bus: BusId,
33 pub output: Option<BusId>,
35 pub sends: Vec<BusSend>,
36 pub pan: f32,
38 pub muted: bool,
40 pub solo: bool,
42}
43impl BusRouting {
44 pub fn new(bus: BusId) -> Self {
45 Self {
46 bus,
47 output: Some(BusId::MASTER),
48 sends: Vec::new(),
49 pan: 0.0,
50 muted: false,
51 solo: false,
52 }
53 }
54}
55#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
57pub struct RoutingId(pub u64);
58
59pub(super) struct Edge {
60 pub destination: usize,
61 pub gain: f64,
62 pub position: SendPosition,
63 pub enabled: bool,
64}
65pub(super) struct Node {
66 pub edges: Vec<Edge>,
67 pub pan: f64,
68 pub muted: bool,
69 pub solo: bool,
70 pub audible: bool,
71}
72pub(super) struct Graph {
73 pub nodes: Vec<Node>,
74 pub incoming: Vec<Vec<usize>>,
75 pub input: [bool; 256],
76 pub pre: Vec<f32>,
77}
78impl Graph {
79 fn new(settings: &[BusRouting], buses: usize, channels: usize) -> Result<Self> {
80 if settings.len() >= buses {
81 return Err(Error::invalid("Too many/duplicate routing bus definitions"));
82 }
83 let routes = settings
84 .iter()
85 .try_fold(buses - 1 - settings.len(), |n, s| {
86 n.checked_add(s.output.is_some() as usize)
87 .and_then(|n| n.checked_add(s.sends.len()))
88 })
89 .ok_or_else(|| Error::limit("Routing edge count overflow"))?;
90 if routes > MAX_BUS_ROUTES {
91 return Err(Error::limit("Too many bus routes"));
92 }
93 let mut graph = Self {
94 nodes: (0..buses)
95 .map(|b| Node {
96 edges: if b == 0 {
97 Vec::new()
98 } else {
99 vec![Edge {
100 destination: 0,
101 gain: 1.0,
102 position: SendPosition::PostFader,
103 enabled: true,
104 }]
105 },
106 pan: 0.0,
107 muted: false,
108 solo: false,
109 audible: true,
110 })
111 .collect(),
112 incoming: (0..buses).map(|_| Vec::new()).collect(),
113 input: [true; 256],
114 pre: vec![0.0; BLOCK * channels],
115 };
116 let mut seen = [false; 256];
117 for setting in settings {
118 let b = setting.bus.0;
119 if b == 0 || b >= buses || seen[b] {
120 return Err(Error::invalid(
121 "Routing needs distinct existing named source buses",
122 ));
123 }
124 seen[b] = true;
125 if !setting.pan.is_finite()
126 || !(-1.0..=1.0).contains(&setting.pan)
127 || (channels != 2 && setting.pan != 0.0)
128 {
129 return Err(Error::invalid(
130 "Bus pan must be -1..=1 and requires stereo when nonzero",
131 ));
132 }
133 let node = &mut graph.nodes[b];
134 node.edges.clear();
135 node.pan = setting.pan as f64;
136 node.muted = setting.muted;
137 node.solo = setting.solo;
138 let mut destinations = [false; 256];
139 for (destination, gain, position) in setting
140 .output
141 .iter()
142 .map(|d| (*d, 1.0, SendPosition::PostFader))
143 .chain(
144 setting
145 .sends
146 .iter()
147 .map(|s| (s.destination, s.gain, s.position)),
148 )
149 {
150 let to = destination.0;
151 if to >= buses || to == b || destinations[to] {
152 return Err(Error::invalid(
153 "Missing, self or duplicate audio route destination",
154 ));
155 }
156 if !gain.is_finite() || gain < 0.0 {
157 return Err(Error::invalid("Send gain must be finite and nonnegative"));
158 }
159 destinations[to] = true;
160 node.edges.push(Edge {
161 destination: to,
162 gain: gain as f64,
163 position,
164 enabled: true,
165 });
166 }
167 }
168 for (from, node) in graph.nodes.iter().enumerate() {
169 for edge in &node.edges {
170 graph.incoming[edge.destination].push(from);
171 }
172 }
173 let mut order = [0usize; 256];
175 let mut done = [false; 256];
176 for entry in &mut order[..buses - 1] {
177 let ready = (1..buses)
178 .find(|&b| !done[b] && graph.incoming[b].iter().all(|&source| done[source]))
179 .ok_or_else(|| Error::invalid("Audio routes contain a cycle"))?;
180 *entry = ready;
181 done[ready] = true;
182 }
183 if graph.nodes.iter().any(|n| n.solo) {
184 let mut up = [false; 256];
185 let mut down = [false; 256];
186 for &b in order[..buses].iter().rev() {
187 up[b] =
188 graph.nodes[b].solo || graph.nodes[b].edges.iter().any(|e| up[e.destination]);
189 }
190 for &b in &order[..buses] {
191 down[b] |= graph.nodes[b].solo;
192 for edge in &graph.nodes[b].edges {
193 down[edge.destination] |= down[b];
194 }
195 }
196 for (b, node) in graph.nodes.iter_mut().enumerate() {
197 graph.input[b] = up[b];
198 node.audible = up[b] || down[b];
199 for edge in &mut node.edges {
200 edge.enabled = down[b] || (up[b] && up[edge.destination]);
201 }
202 }
203 }
204 Ok(graph)
205 }
206}
207
208pub(super) struct Edit {
209 id: RoutingId,
210 graph: Option<Box<Graph>>,
211 event: Option<MixerEvent>,
212 credits: Arc<AtomicUsize>,
213}
214impl Drop for Edit {
215 fn drop(&mut self) {
216 self.credits.fetch_sub(1, Ordering::Release);
217 }
218}
219pub(super) struct AudioRouting {
220 pub graph: Option<Box<Graph>>,
221 returns: Producer<Box<Edit>>,
222 retired: VecDeque<Box<Edit>>,
223}
224pub(super) struct ControlRouting {
225 returns: Consumer<Box<Edit>>,
226 credits: Arc<AtomicUsize>,
227 capacity: usize,
228 next: u64,
229}
230pub(super) fn create(capacity: usize) -> (AudioRouting, ControlRouting) {
231 let (tx, rx) = queue::queue(capacity);
232 (
233 AudioRouting {
234 graph: None,
235 returns: tx,
236 retired: VecDeque::with_capacity(capacity),
237 },
238 ControlRouting {
239 returns: rx,
240 credits: Arc::new(AtomicUsize::new(0)),
241 capacity,
242 next: 0,
243 },
244 )
245}
246impl AudioRouting {
247 pub fn send_returns(&mut self) {
248 while let Some(edit) = self.retired.pop_front() {
249 match self.returns.push(edit) {
250 Ok(()) => (),
251 Err(PushError::Full(edit) | PushError::Disconnected(edit)) => {
252 self.retired.push_front(edit);
253 break;
254 }
255 }
256 }
257 }
258}
259impl ControlRouting {
260 pub fn poll(&mut self) -> Option<MixerEvent> {
261 self.returns.pop()?.event
262 }
263}
264impl MixerHandle {
265 pub fn set_routing(&mut self, settings: &[BusRouting]) -> Result<RoutingId> {
271 self.now().set_routing(settings)
272 }
273}
274impl Commands<'_> {
275 pub fn set_routing(self, settings: &[BusRouting]) -> Result<RoutingId> {
276 let control = &self.handle.routing;
277 if control.credits.load(Ordering::Acquire) >= control.capacity {
278 return Err(Error::limit(
279 "Poll routing events before sending more edits",
280 ));
281 }
282 let next = control
283 .next
284 .checked_add(1)
285 .ok_or_else(|| Error::limit("Routing ID overflow"))?;
286 let graph = if settings.is_empty() {
287 None
288 } else {
289 Some(Box::new(Graph::new(
290 settings,
291 self.handle.buses.len() + 1,
292 self.handle.channels,
293 )?))
294 };
295 let id = RoutingId(control.next);
296 control.credits.fetch_add(1, Ordering::Relaxed);
297 let edit = Box::new(Edit {
298 id,
299 graph,
300 event: None,
301 credits: control.credits.clone(),
302 });
303 self.handle.send(self.frame, Action::Routing(edit))?;
304 self.handle.routing.next = next;
305 Ok(id)
306 }
307}
308impl Mixer {
309 pub(super) fn apply_routing(&mut self, frame: u64, mut edit: Box<Edit>) {
310 if let Some(order) = effects::topology(&self.buses, Change::Current, edit.graph.as_deref())
311 {
312 self.effects.order = order;
313 std::mem::swap(&mut self.routing.graph, &mut edit.graph);
314 edit.event = Some(MixerEvent::RoutingApplied(edit.id, frame));
315 } else {
316 edit.event = Some(MixerEvent::RoutingRejected(
317 edit.id,
318 ErrorCode::InvalidArgument,
319 ));
320 }
321 self.routing.retired.push_back(edit);
322 }
323}