Skip to content

Commit 67f2c55

Browse files
committed
AudioNode::disconnect, disconnect_dest, disconnect_output and more
All variants of https://webaudio.github.io/web-audio-api/#AudioNode disconnect methods. Changed: renamed disconnect_from -> disconnect_dest Fix: disconnect methods should not return any value
1 parent 63efe2f commit 67f2c55

File tree

3 files changed

+210
-73
lines changed

3 files changed

+210
-73
lines changed

src/context/concrete_base.rs

Lines changed: 19 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -426,24 +426,29 @@ impl ConcreteBaseAudioContext {
426426
self.inner.queued_messages.lock().unwrap().push(message);
427427
}
428428

429-
/// Disconnects all outputs of the audio node that go to a specific destination node.
430-
///
431-
/// # Panics
432-
///
433-
/// Panics if this node was not connected to the target node
434-
pub(crate) fn disconnect_from(&self, from: AudioNodeId, to: AudioNodeId) {
429+
/// Disconnects outputs of the audio node, possibly filtered by output node, input, output.
430+
pub(crate) fn disconnect(
431+
&self,
432+
from: AudioNodeId,
433+
output: Option<usize>,
434+
to: Option<AudioNodeId>,
435+
input: Option<usize>,
436+
) {
435437
// check if the node was connected, otherwise panic
436438
let mut has_disconnected = false;
437439
let mut connections = self.inner.connections.lock().unwrap();
438-
connections.retain(|&(c_from, output, c_to, input)| {
439-
let retain = c_from != from || c_to != to;
440+
connections.retain(|&(c_from, c_output, c_to, c_input)| {
441+
let retain = c_from != from
442+
|| c_output != output.unwrap_or(c_output)
443+
|| c_to != to.unwrap_or(c_to)
444+
|| c_input != input.unwrap_or(c_input);
440445
if !retain {
441446
has_disconnected = true;
442447
let message = ControlMessage::DisconnectNode {
443448
from,
444-
to,
445-
input,
446-
output,
449+
to: c_to,
450+
input: c_input,
451+
output: c_output,
447452
};
448453
self.send_control_msg(message);
449454
}
@@ -453,53 +458,11 @@ impl ConcreteBaseAudioContext {
453458
// make sure to drop the MutexGuard before the panic to avoid poisoning
454459
drop(connections);
455460

456-
if !has_disconnected {
461+
if !has_disconnected && to.is_some() {
457462
panic!("InvalidAccessError - attempting to disconnect unconnected nodes");
458463
}
459464
}
460465

461-
/// Disconnects all outgoing connections from the audio node.
462-
pub(crate) fn disconnect(&self, from: AudioNodeId) {
463-
self.inner
464-
.connections
465-
.lock()
466-
.unwrap()
467-
.retain(|&(c_from, output, to, input)| {
468-
let retain = c_from != from;
469-
if !retain {
470-
let message = ControlMessage::DisconnectNode {
471-
from,
472-
to,
473-
input,
474-
output,
475-
};
476-
self.send_control_msg(message);
477-
}
478-
retain
479-
});
480-
}
481-
482-
/// Disconnects all outgoing connections at the given output port from the audio node.
483-
pub(crate) fn disconnect_at(&self, from: AudioNodeId, output: usize) {
484-
self.inner
485-
.connections
486-
.lock()
487-
.unwrap()
488-
.retain(|&(c_from, c_output, to, input)| {
489-
let retain = c_from != from || c_output != output;
490-
if !retain {
491-
let message = ControlMessage::DisconnectNode {
492-
from,
493-
to,
494-
input,
495-
output,
496-
};
497-
self.send_control_msg(message);
498-
}
499-
retain
500-
});
501-
}
502-
503466
/// Connect the `AudioListener` to a `PannerNode`
504467
pub(crate) fn connect_listener_to_panner(&self, panner: AudioNodeId) {
505468
self.connect(LISTENER_NODE_ID, panner, 0, usize::MAX);
@@ -568,7 +531,7 @@ mod tests {
568531
node1.disconnect();
569532

570533
node1.connect(&node2);
571-
node1.disconnect_from(&node2);
534+
node1.disconnect_dest(&node2);
572535
}
573536

574537
#[test]
@@ -578,6 +541,6 @@ mod tests {
578541
let node1 = context.create_constant_source();
579542
let node2 = context.create_gain();
580543

581-
node1.disconnect_from(&node2);
544+
node1.disconnect_dest(&node2);
582545
}
583546
}

src/node/audio_node.rs

Lines changed: 95 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -288,28 +288,112 @@ pub trait AudioNode {
288288
dest
289289
}
290290

291+
/// Disconnects all outgoing connections from the AudioNode.
292+
fn disconnect(&self) {
293+
self.context()
294+
.disconnect(self.registration().id(), None, None, None);
295+
}
296+
291297
/// Disconnects all outputs of the AudioNode that go to a specific destination AudioNode.
292-
fn disconnect_from<'a>(&self, dest: &'a dyn AudioNode) -> &'a dyn AudioNode {
298+
///
299+
/// # Panics
300+
///
301+
/// This function will panic when
302+
/// - the AudioContext of the source and destination does not match
303+
/// - the source node was not connected to the destination node
304+
fn disconnect_dest(&self, dest: &dyn AudioNode) {
293305
assert!(
294306
self.context() == dest.context(),
295307
"InvalidAccessError - Attempting to disconnect nodes from different contexts"
296308
);
297309

298-
self.context()
299-
.disconnect_from(self.registration().id(), dest.registration().id());
310+
self.context().disconnect(
311+
self.registration().id(),
312+
None,
313+
Some(dest.registration().id()),
314+
None,
315+
);
316+
}
300317

301-
dest
318+
/// Disconnects all outgoing connections at the given output port from the AudioNode.
319+
///
320+
/// # Panics
321+
///
322+
/// This function will panic when
323+
/// - if the output port is out of bounds for this node
324+
fn disconnect_output(&self, output: usize) {
325+
assert!(
326+
self.number_of_outputs() > output,
327+
"IndexSizeError - output port {} is out of bounds",
328+
output
329+
);
330+
331+
self.context()
332+
.disconnect(self.registration().id(), Some(output), None, None);
302333
}
303334

304-
/// Disconnects all outgoing connections from the AudioNode.
305-
fn disconnect(&self) {
306-
self.context().disconnect(self.registration().id());
335+
/// Disconnects a specific output of the AudioNode to a specific destination AudioNode
336+
///
337+
/// # Panics
338+
///
339+
/// This function will panic when
340+
/// - the AudioContext of the source and destination does not match
341+
/// - if the output port is out of bounds for the source node
342+
/// - the source node was not connected to the destination node
343+
fn disconnect_dest_output(&self, dest: &dyn AudioNode, output: usize) {
344+
assert!(
345+
self.context() == dest.context(),
346+
"InvalidAccessError - Attempting to disconnect nodes from different contexts"
347+
);
348+
349+
assert!(
350+
self.number_of_outputs() > output,
351+
"IndexSizeError - output port {} is out of bounds",
352+
output
353+
);
354+
355+
self.context().disconnect(
356+
self.registration().id(),
357+
Some(output),
358+
Some(dest.registration().id()),
359+
None,
360+
);
307361
}
308362

309-
/// Disconnects all outgoing connections at the given output port from the AudioNode.
310-
fn disconnect_at(&self, output: usize) {
311-
self.context()
312-
.disconnect_at(self.registration().id(), output);
363+
/// Disconnects a specific output of the AudioNode to a specific input of some destination
364+
/// AudioNode
365+
///
366+
/// # Panics
367+
///
368+
/// This function will panic when
369+
/// - the AudioContext of the source and destination does not match
370+
/// - if the input port is out of bounds for the destination node
371+
/// - if the output port is out of bounds for the source node
372+
/// - the source node was not connected to the destination node
373+
fn disconnect_dest_output_input(&self, dest: &dyn AudioNode, output: usize, input: usize) {
374+
assert!(
375+
self.context() == dest.context(),
376+
"InvalidAccessError - Attempting to disconnect nodes from different contexts"
377+
);
378+
379+
assert!(
380+
self.number_of_outputs() > output,
381+
"IndexSizeError - output port {} is out of bounds",
382+
output
383+
);
384+
385+
assert!(
386+
dest.number_of_inputs() > input,
387+
"IndexSizeError - input port {} is out of bounds",
388+
input
389+
);
390+
391+
self.context().disconnect(
392+
self.registration().id(),
393+
Some(output),
394+
Some(dest.registration().id()),
395+
Some(input),
396+
);
313397
}
314398

315399
/// The number of inputs feeding into the AudioNode. For source nodes, this will be 0.

src/node/delay.rs

Lines changed: 96 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,22 +160,112 @@ impl AudioNode for DelayNode {
160160
dest
161161
}
162162

163+
/// Disconnects all outgoing connections from the AudioNode.
164+
fn disconnect(&self) {
165+
self.context()
166+
.disconnect(self.reader_registration.id(), None, None, None);
167+
}
168+
163169
/// Disconnects all outputs of the AudioNode that go to a specific destination AudioNode.
164-
fn disconnect_from<'a>(&self, dest: &'a dyn AudioNode) -> &'a dyn AudioNode {
170+
///
171+
/// # Panics
172+
///
173+
/// This function will panic when
174+
/// - the AudioContext of the source and destination does not match
175+
/// - the source node was not connected to the destination node
176+
fn disconnect_dest(&self, dest: &dyn AudioNode) {
165177
assert!(
166178
self.context() == dest.context(),
167179
"InvalidAccessError - Attempting to disconnect nodes from different contexts"
168180
);
169181

182+
self.context().disconnect(
183+
self.reader_registration.id(),
184+
None,
185+
Some(dest.registration().id()),
186+
None,
187+
);
188+
}
189+
190+
/// Disconnects all outgoing connections at the given output port from the AudioNode.
191+
///
192+
/// # Panics
193+
///
194+
/// This function will panic when
195+
/// - if the output port is out of bounds for this node
196+
fn disconnect_output(&self, output: usize) {
197+
assert!(
198+
self.number_of_outputs() > output,
199+
"IndexSizeError - output port {} is out of bounds",
200+
output
201+
);
202+
170203
self.context()
171-
.disconnect_from(self.reader_registration.id(), dest.registration().id());
204+
.disconnect(self.reader_registration.id(), Some(output), None, None);
205+
}
172206

173-
dest
207+
/// Disconnects a specific output of the AudioNode to a specific destination AudioNode
208+
///
209+
/// # Panics
210+
///
211+
/// This function will panic when
212+
/// - the AudioContext of the source and destination does not match
213+
/// - if the output port is out of bounds for the source node
214+
/// - the source node was not connected to the destination node
215+
fn disconnect_dest_output(&self, dest: &dyn AudioNode, output: usize) {
216+
assert!(
217+
self.context() == dest.context(),
218+
"InvalidAccessError - Attempting to disconnect nodes from different contexts"
219+
);
220+
221+
assert!(
222+
self.number_of_outputs() > output,
223+
"IndexSizeError - output port {} is out of bounds",
224+
output
225+
);
226+
227+
self.context().disconnect(
228+
self.reader_registration.id(),
229+
Some(output),
230+
Some(dest.registration().id()),
231+
None,
232+
);
174233
}
175234

176-
/// Disconnects all outgoing connections from the AudioNode.
177-
fn disconnect(&self) {
178-
self.context().disconnect(self.reader_registration.id());
235+
/// Disconnects a specific output of the AudioNode to a specific input of some destination
236+
/// AudioNode
237+
///
238+
/// # Panics
239+
///
240+
/// This function will panic when
241+
/// - the AudioContext of the source and destination does not match
242+
/// - if the input port is out of bounds for the destination node
243+
/// - if the output port is out of bounds for the source node
244+
/// - the source node was not connected to the destination node
245+
fn disconnect_dest_output_input(&self, dest: &dyn AudioNode, output: usize, input: usize) {
246+
assert!(
247+
self.context() == dest.context(),
248+
"InvalidAccessError - Attempting to disconnect nodes from different contexts"
249+
);
250+
251+
assert!(
252+
self.number_of_outputs() > output,
253+
"IndexSizeError - output port {} is out of bounds",
254+
output
255+
);
256+
257+
assert!(
258+
dest.number_of_inputs() > input,
259+
"IndexSizeError - input port {} is out of bounds",
260+
input
261+
);
262+
263+
self.context().disconnect(
264+
self.reader_registration.id(),
265+
Some(output),
266+
Some(dest.registration().id()),
267+
Some(input),
268+
);
179269
}
180270
}
181271

0 commit comments

Comments
 (0)