Skip to main content

script/dom/audio/
stereopannernode.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, AudioNodeType};
10use servo_media::audio::graph::NodeId;
11use servo_media::audio::param::ParamType;
12use servo_media::audio::stereo_panner::StereoPannerOptions as ServoMediaStereoPannerOptions;
13
14use crate::conversions::Convert;
15use crate::dom::audio::audionode::{AudioNode, AudioNodeOptionsHelper};
16use crate::dom::audio::audioparam::AudioParam;
17use crate::dom::audio::audioscheduledsourcenode::AudioScheduledSourceNode;
18use crate::dom::audio::baseaudiocontext::BaseAudioContext;
19use crate::dom::audionode::UnwrappedAudioNodeOptions;
20use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{
21    ChannelCountMode, ChannelInterpretation,
22};
23use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;
24use crate::dom::bindings::codegen::Bindings::StereoPannerNodeBinding::{
25    StereoPannerNodeMethods, StereoPannerOptions,
26};
27use crate::dom::bindings::error::{Error, Fallible};
28use crate::dom::bindings::root::{Dom, DomRoot};
29use crate::dom::window::Window;
30
31#[dom_struct]
32pub(crate) struct StereoPannerNode {
33    source_node: AudioScheduledSourceNode,
34    pan: Dom<AudioParam>,
35}
36
37impl StereoPannerNode {
38    fn new_inherited(
39        node_id: Option<NodeId>,
40        context: &BaseAudioContext,
41        node_options: UnwrappedAudioNodeOptions,
42        pan: &AudioParam,
43    ) -> Self {
44        StereoPannerNode {
45            source_node: AudioScheduledSourceNode::new_inherited(
46                node_id,
47                context,
48                node_options,
49                1, /* inputs */
50                1, /* outputs */
51            ),
52            pan: Dom::from_ref(pan),
53        }
54    }
55}
56
57impl StereoPannerNodeMethods<crate::DomTypeHolder> for StereoPannerNode {
58    /// <https://webaudio.github.io/web-audio-api/#dom-stereopannernode-stereopannernode>
59    fn Constructor(
60        cx: &mut JSContext,
61        window: &Window,
62        proto: Option<HandleObject>,
63        context: &BaseAudioContext,
64        options: &StereoPannerOptions,
65    ) -> Fallible<DomRoot<StereoPannerNode>> {
66        let node_options = options.parent.unwrap_or(
67            2,
68            ChannelCountMode::Clamped_max,
69            ChannelInterpretation::Speakers,
70        );
71        if AudioNode::channel_count_check(node_options.count) {
72            return Err(Error::NotSupported(Some(String::from(
73                "Channel count not supported",
74            ))));
75        }
76        if node_options.mode == ChannelCountMode::Max {
77            return Err(Error::NotSupported(Some(
78                "Channel count mode cannot be \"max\"".into(),
79            )));
80        }
81        if node_options.count > 2 || node_options.count == 0 {
82            return Err(Error::NotSupported(Some(
83                "Channel count must be 1 or 2".into(),
84            )));
85        }
86        let pan = *options.pan;
87        let audio_node_init = AudioNodeInit::StereoPannerNode(options.convert());
88        let node_id =
89            AudioNode::generate_audio_node_id(cx, &node_options, audio_node_init, context);
90        // <https://webaudio.github.io/web-audio-api/#dom-stereopannernode-pan>
91        let pan = AudioParam::new(
92            cx,
93            window,
94            context,
95            node_id,
96            AudioNodeType::StereoPannerNode,
97            ParamType::Pan,
98            AutomationRate::A_rate,
99            pan,
100            -1.,
101            1.,
102        );
103        Ok(reflect_dom_object_with_proto(
104            cx,
105            Box::new(StereoPannerNode::new_inherited(
106                node_id,
107                context,
108                node_options,
109                &pan,
110            )),
111            window,
112            proto,
113        ))
114    }
115
116    /// <https://webaudio.github.io/web-audio-api/#dom-stereopannernode-pan>
117    fn Pan(&self) -> DomRoot<AudioParam> {
118        DomRoot::from_ref(&self.pan)
119    }
120}
121
122impl Convert<ServoMediaStereoPannerOptions> for StereoPannerOptions {
123    fn convert(self) -> ServoMediaStereoPannerOptions {
124        ServoMediaStereoPannerOptions { pan: *self.pan }
125    }
126}