Skip to main content

script/dom/audio/
channelmergernode.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::channel_node::ChannelNodeOptions;
11use servo_media::audio::graph::NodeId;
12
13use crate::conversions::Convert;
14use crate::dom::audio::audionode::{AudioNode, AudioNodeOptionsHelper, MAX_CHANNEL_COUNT};
15use crate::dom::audio::baseaudiocontext::BaseAudioContext;
16use crate::dom::audionode::UnwrappedAudioNodeOptions;
17use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{
18    ChannelCountMode, ChannelInterpretation,
19};
20use crate::dom::bindings::codegen::Bindings::ChannelMergerNodeBinding::{
21    ChannelMergerNodeMethods, ChannelMergerOptions,
22};
23use crate::dom::bindings::error::{Error, Fallible};
24use crate::dom::bindings::root::DomRoot;
25use crate::dom::window::Window;
26
27#[dom_struct]
28pub(crate) struct ChannelMergerNode {
29    node: AudioNode,
30}
31
32impl ChannelMergerNode {
33    fn new_inherited(
34        node_id: Option<NodeId>,
35        context: &BaseAudioContext,
36        node_options: UnwrappedAudioNodeOptions,
37        number_of_inputs: u32,
38    ) -> Self {
39        ChannelMergerNode {
40            node: AudioNode::new_inherited(
41                node_id,
42                context,
43                node_options,
44                number_of_inputs, // inputs
45                1,                // outputs
46            ),
47        }
48    }
49}
50
51impl ChannelMergerNodeMethods<crate::DomTypeHolder> for ChannelMergerNode {
52    /// <https://webaudio.github.io/web-audio-api/#dom-channelmergernode-channelmergernode>
53    fn Constructor(
54        cx: &mut JSContext,
55        window: &Window,
56        proto: Option<HandleObject>,
57        context: &BaseAudioContext,
58        options: &ChannelMergerOptions,
59    ) -> Fallible<DomRoot<ChannelMergerNode>> {
60        let node_options = options.parent.unwrap_or(
61            1,
62            ChannelCountMode::Explicit,
63            ChannelInterpretation::Speakers,
64        );
65
66        if AudioNode::channel_count_check(node_options.count) {
67            return Err(Error::NotSupported(Some(String::from(
68                "Channel count not supported",
69            ))));
70        }
71
72        if node_options.count != 1 || node_options.mode != ChannelCountMode::Explicit {
73            return Err(Error::InvalidState(None));
74        }
75
76        if options.numberOfInputs < 1 || options.numberOfInputs > MAX_CHANNEL_COUNT {
77            return Err(Error::IndexSize(None));
78        }
79
80        let audio_node_init = AudioNodeInit::ChannelMergerNode(options.convert());
81        let node_id =
82            AudioNode::generate_audio_node_id(cx, &node_options, audio_node_init, context);
83
84        Ok(reflect_dom_object_with_proto(
85            cx,
86            Box::new(ChannelMergerNode::new_inherited(
87                node_id,
88                context,
89                node_options,
90                options.numberOfInputs, // inputs
91            )),
92            window,
93            proto,
94        ))
95    }
96}
97
98impl Convert<ChannelNodeOptions> for ChannelMergerOptions {
99    fn convert(self) -> ChannelNodeOptions {
100        ChannelNodeOptions {
101            channels: self.numberOfInputs as u8,
102        }
103    }
104}