script/dom/audio/
stereopannernode.rs1use dom_struct::dom_struct;
6use js::rust::HandleObject;
7use servo_media::audio::node::{AudioNodeInit, AudioNodeType};
8use servo_media::audio::param::ParamType;
9use servo_media::audio::stereo_panner::StereoPannerOptions as ServoMediaStereoPannerOptions;
10
11use crate::conversions::Convert;
12use crate::dom::audio::audionode::AudioNodeOptionsHelper;
13use crate::dom::audio::audioparam::AudioParam;
14use crate::dom::audio::audioscheduledsourcenode::AudioScheduledSourceNode;
15use crate::dom::audio::baseaudiocontext::BaseAudioContext;
16use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{
17 ChannelCountMode, ChannelInterpretation,
18};
19use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;
20use crate::dom::bindings::codegen::Bindings::StereoPannerNodeBinding::{
21 StereoPannerNodeMethods, StereoPannerOptions,
22};
23use crate::dom::bindings::error::{Error, Fallible};
24use crate::dom::bindings::reflector::reflect_dom_object_with_proto;
25use crate::dom::bindings::root::{Dom, DomRoot};
26use crate::dom::window::Window;
27use crate::script_runtime::CanGc;
28
29#[dom_struct]
30pub(crate) struct StereoPannerNode {
31 source_node: AudioScheduledSourceNode,
32 pan: Dom<AudioParam>,
33}
34
35impl StereoPannerNode {
36 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
37 pub(crate) fn new_inherited(
38 window: &Window,
39 context: &BaseAudioContext,
40 options: &StereoPannerOptions,
41 can_gc: CanGc,
42 ) -> Fallible<StereoPannerNode> {
43 let node_options = options.parent.unwrap_or(
44 2,
45 ChannelCountMode::Clamped_max,
46 ChannelInterpretation::Speakers,
47 );
48 if node_options.mode == ChannelCountMode::Max {
49 return Err(Error::NotSupported);
50 }
51 if node_options.count > 2 || node_options.count == 0 {
52 return Err(Error::NotSupported);
53 }
54 let pan = *options.pan;
55 let source_node = AudioScheduledSourceNode::new_inherited(
56 AudioNodeInit::StereoPannerNode(options.convert()),
57 context,
58 node_options,
59 1, 1, )?;
62 let node_id = source_node.node().node_id();
63 let pan = AudioParam::new(
64 window,
65 context,
66 node_id,
67 AudioNodeType::StereoPannerNode,
68 ParamType::Pan,
69 AutomationRate::A_rate,
70 pan,
71 -1.,
72 1.,
73 can_gc,
74 );
75
76 Ok(StereoPannerNode {
77 source_node,
78 pan: Dom::from_ref(&pan),
79 })
80 }
81
82 pub(crate) fn new(
83 window: &Window,
84 context: &BaseAudioContext,
85 options: &StereoPannerOptions,
86 can_gc: CanGc,
87 ) -> Fallible<DomRoot<StereoPannerNode>> {
88 Self::new_with_proto(window, None, context, options, can_gc)
89 }
90
91 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
92 fn new_with_proto(
93 window: &Window,
94 proto: Option<HandleObject>,
95 context: &BaseAudioContext,
96 options: &StereoPannerOptions,
97 can_gc: CanGc,
98 ) -> Fallible<DomRoot<StereoPannerNode>> {
99 let node = StereoPannerNode::new_inherited(window, context, options, can_gc)?;
100 Ok(reflect_dom_object_with_proto(
101 Box::new(node),
102 window,
103 proto,
104 can_gc,
105 ))
106 }
107}
108
109impl StereoPannerNodeMethods<crate::DomTypeHolder> for StereoPannerNode {
110 fn Constructor(
112 window: &Window,
113 proto: Option<HandleObject>,
114 can_gc: CanGc,
115 context: &BaseAudioContext,
116 options: &StereoPannerOptions,
117 ) -> Fallible<DomRoot<StereoPannerNode>> {
118 StereoPannerNode::new_with_proto(window, proto, context, options, can_gc)
119 }
120
121 fn Pan(&self) -> DomRoot<AudioParam> {
123 DomRoot::from_ref(&self.pan)
124 }
125}
126
127impl Convert<ServoMediaStereoPannerOptions> for StereoPannerOptions {
128 fn convert(self) -> ServoMediaStereoPannerOptions {
129 ServoMediaStereoPannerOptions { pan: *self.pan }
130 }
131}