Skip to main content

script/dom/audio/
gainnode.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::gain_node::GainNodeOptions;
11use servo_media::audio::param::ParamType;
12
13use crate::conversions::Convert;
14use crate::dom::audio::audionode::{AudioNode, AudioNodeOptionsHelper};
15use crate::dom::audio::audioparam::AudioParam;
16use crate::dom::audio::baseaudiocontext::BaseAudioContext;
17use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{
18    ChannelCountMode, ChannelInterpretation,
19};
20use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;
21use crate::dom::bindings::codegen::Bindings::GainNodeBinding::{GainNodeMethods, GainOptions};
22use crate::dom::bindings::error::Fallible;
23use crate::dom::bindings::root::{Dom, DomRoot};
24use crate::dom::window::Window;
25
26#[dom_struct]
27pub(crate) struct GainNode {
28    node: AudioNode,
29    gain: Dom<AudioParam>,
30}
31
32impl GainNode {
33    #[cfg_attr(crown, expect(crown::unrooted_must_root))]
34    pub(crate) fn new_inherited(
35        cx: &mut JSContext,
36        window: &Window,
37        context: &BaseAudioContext,
38        options: &GainOptions,
39    ) -> Fallible<GainNode> {
40        let node_options =
41            options
42                .parent
43                .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);
44        let gain = *options.gain;
45        let node = AudioNode::new_inherited(
46            cx,
47            AudioNodeInit::GainNode(options.convert()),
48            context,
49            node_options,
50            1, // inputs
51            1, // outputs
52        )?;
53        // <https://webaudio.github.io/web-audio-api/#dom-gainnode-gain>
54        let gain = AudioParam::new(
55            cx,
56            window,
57            context,
58            node.node_id(),
59            AudioNodeType::GainNode,
60            ParamType::Gain,
61            AutomationRate::A_rate,
62            gain,     // default value
63            f32::MIN, // min value
64            f32::MAX, // max value
65        );
66        Ok(GainNode {
67            node,
68            gain: Dom::from_ref(&gain),
69        })
70    }
71
72    pub(crate) fn new(
73        cx: &mut JSContext,
74        window: &Window,
75        context: &BaseAudioContext,
76        options: &GainOptions,
77    ) -> Fallible<DomRoot<GainNode>> {
78        Self::new_with_proto(cx, window, None, context, options)
79    }
80
81    #[cfg_attr(crown, expect(crown::unrooted_must_root))]
82    fn new_with_proto(
83        cx: &mut JSContext,
84        window: &Window,
85        proto: Option<HandleObject>,
86        context: &BaseAudioContext,
87        options: &GainOptions,
88    ) -> Fallible<DomRoot<GainNode>> {
89        let node = GainNode::new_inherited(cx, window, context, options)?;
90        Ok(reflect_dom_object_with_proto(
91            cx,
92            Box::new(node),
93            window,
94            proto,
95        ))
96    }
97}
98
99impl GainNodeMethods<crate::DomTypeHolder> for GainNode {
100    /// <https://webaudio.github.io/web-audio-api/#dom-gainnode-gainnode>
101    fn Constructor(
102        cx: &mut JSContext,
103        window: &Window,
104        proto: Option<HandleObject>,
105        context: &BaseAudioContext,
106        options: &GainOptions,
107    ) -> Fallible<DomRoot<GainNode>> {
108        GainNode::new_with_proto(cx, window, proto, context, options)
109    }
110
111    /// <https://webaudio.github.io/web-audio-api/#dom-gainnode-gain>
112    fn Gain(&self) -> DomRoot<AudioParam> {
113        DomRoot::from_ref(&self.gain)
114    }
115}
116
117impl Convert<GainNodeOptions> for GainOptions {
118    fn convert(self) -> GainNodeOptions {
119        GainNodeOptions { gain: *self.gain }
120    }
121}