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