Skip to main content

script/dom/audio/
channelsplitternode.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use dom_struct::dom_struct;
6use js::context::JSContext;
7use js::rust::HandleObject;
8use script_bindings::reflector::reflect_dom_object_with_proto;
9use servo_media::audio::audio_node::AudioNodeInit;
10use servo_media::audio::graph::NodeId;
11
12use crate::dom::audio::audionode::{AudioNode, AudioNodeOptionsHelper, MAX_CHANNEL_COUNT};
13use crate::dom::audio::baseaudiocontext::BaseAudioContext;
14use crate::dom::audionode::UnwrappedAudioNodeOptions;
15use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{
16    ChannelCountMode, ChannelInterpretation,
17};
18use crate::dom::bindings::codegen::Bindings::ChannelSplitterNodeBinding::{
19    ChannelSplitterNodeMethods, ChannelSplitterOptions,
20};
21use crate::dom::bindings::error::{Error, Fallible};
22use crate::dom::bindings::root::DomRoot;
23use crate::dom::window::Window;
24
25#[dom_struct]
26pub(crate) struct ChannelSplitterNode {
27    node: AudioNode,
28}
29
30impl ChannelSplitterNode {
31    fn new_inherited(
32        node_id: Option<NodeId>,
33        context: &BaseAudioContext,
34        node_options: UnwrappedAudioNodeOptions,
35        number_of_outputs: u32,
36    ) -> Self {
37        ChannelSplitterNode {
38            node: AudioNode::new_inherited(
39                node_id,
40                context,
41                node_options,
42                1,                 // inputs
43                number_of_outputs, // outputs
44            ),
45        }
46    }
47}
48
49impl ChannelSplitterNodeMethods<crate::DomTypeHolder> for ChannelSplitterNode {
50    /// <https://webaudio.github.io/web-audio-api/#dom-channelsplitternode-channelsplitternode>
51    fn Constructor(
52        cx: &mut JSContext,
53        window: &Window,
54        proto: Option<HandleObject>,
55        context: &BaseAudioContext,
56        options: &ChannelSplitterOptions,
57    ) -> Fallible<DomRoot<ChannelSplitterNode>> {
58        if options.numberOfOutputs < 1 || options.numberOfOutputs > MAX_CHANNEL_COUNT {
59            return Err(Error::IndexSize(Some(
60                "numberOfOutputs is out of range".into(),
61            )));
62        }
63
64        let node_options = options.parent.unwrap_or(
65            options.numberOfOutputs,
66            ChannelCountMode::Explicit,
67            ChannelInterpretation::Discrete,
68        );
69
70        if AudioNode::channel_count_check(node_options.count) {
71            return Err(Error::NotSupported(Some(String::from(
72                "Channel count not supported",
73            ))));
74        }
75
76        if node_options.count != options.numberOfOutputs ||
77            node_options.mode != ChannelCountMode::Explicit ||
78            node_options.interpretation != ChannelInterpretation::Discrete
79        {
80            return Err(Error::InvalidState(Some(
81                "Invalid channel options for ChannelSplitterNode".into(),
82            )));
83        }
84
85        let audio_node_init = AudioNodeInit::ChannelSplitterNode;
86        let node_id =
87            AudioNode::generate_audio_node_id(cx, &node_options, audio_node_init, context);
88
89        Ok(reflect_dom_object_with_proto(
90            cx,
91            Box::new(ChannelSplitterNode::new_inherited(
92                node_id,
93                context,
94                node_options,
95                options.numberOfOutputs, // outputs
96            )),
97            window,
98            proto,
99        ))
100    }
101}