1use dom_struct::dom_struct;
6use js::context::JSContext;
7use script_bindings::reflector::{Reflector, reflect_dom_object};
8use servo_media::audio::audio_node::AudioNodeType;
9use servo_media::audio::param::{ParamDir, ParamType};
10
11use crate::dom::audio::audioparam::AudioParam;
12use crate::dom::audio::baseaudiocontext::BaseAudioContext;
13use crate::dom::bindings::codegen::Bindings::AudioListenerBinding::AudioListenerMethods;
14use crate::dom::bindings::codegen::Bindings::AudioParamBinding::{
15 AudioParamMethods, AutomationRate,
16};
17use crate::dom::bindings::error::Fallible;
18use crate::dom::bindings::num::Finite;
19use crate::dom::bindings::root::{Dom, DomRoot};
20use crate::dom::window::Window;
21
22#[dom_struct]
23pub(crate) struct AudioListener {
24 reflector_: Reflector,
25 position_x: Dom<AudioParam>,
26 position_y: Dom<AudioParam>,
27 position_z: Dom<AudioParam>,
28 forward_x: Dom<AudioParam>,
29 forward_y: Dom<AudioParam>,
30 forward_z: Dom<AudioParam>,
31 up_x: Dom<AudioParam>,
32 up_y: Dom<AudioParam>,
33 up_z: Dom<AudioParam>,
34}
35
36impl AudioListener {
37 fn new_inherited(
38 cx: &mut JSContext,
39 window: &Window,
40 context: &BaseAudioContext,
41 ) -> AudioListener {
42 let node = context.listener();
43
44 let position_x = AudioParam::new(
46 cx,
47 window,
48 context,
49 Some(node),
50 AudioNodeType::AudioListenerNode,
51 ParamType::Position(ParamDir::X),
52 AutomationRate::A_rate,
53 0., f32::MIN, f32::MAX, );
57 let position_y = AudioParam::new(
59 cx,
60 window,
61 context,
62 Some(node),
63 AudioNodeType::AudioListenerNode,
64 ParamType::Position(ParamDir::Y),
65 AutomationRate::A_rate,
66 0., f32::MIN, f32::MAX, );
70 let position_z = AudioParam::new(
72 cx,
73 window,
74 context,
75 Some(node),
76 AudioNodeType::AudioListenerNode,
77 ParamType::Position(ParamDir::Z),
78 AutomationRate::A_rate,
79 0., f32::MIN, f32::MAX, );
83 let forward_x = AudioParam::new(
85 cx,
86 window,
87 context,
88 Some(node),
89 AudioNodeType::AudioListenerNode,
90 ParamType::Forward(ParamDir::X),
91 AutomationRate::A_rate,
92 0., f32::MIN, f32::MAX, );
96 let forward_y = AudioParam::new(
98 cx,
99 window,
100 context,
101 Some(node),
102 AudioNodeType::AudioListenerNode,
103 ParamType::Forward(ParamDir::Y),
104 AutomationRate::A_rate,
105 0., f32::MIN, f32::MAX, );
109 let forward_z = AudioParam::new(
111 cx,
112 window,
113 context,
114 Some(node),
115 AudioNodeType::AudioListenerNode,
116 ParamType::Forward(ParamDir::Z),
117 AutomationRate::A_rate,
118 -1., f32::MIN, f32::MAX, );
122 let up_x = AudioParam::new(
124 cx,
125 window,
126 context,
127 Some(node),
128 AudioNodeType::AudioListenerNode,
129 ParamType::Up(ParamDir::X),
130 AutomationRate::A_rate,
131 0., f32::MIN, f32::MAX, );
135 let up_y = AudioParam::new(
137 cx,
138 window,
139 context,
140 Some(node),
141 AudioNodeType::AudioListenerNode,
142 ParamType::Up(ParamDir::Y),
143 AutomationRate::A_rate,
144 1., f32::MIN, f32::MAX, );
148 let up_z = AudioParam::new(
150 cx,
151 window,
152 context,
153 Some(node),
154 AudioNodeType::AudioListenerNode,
155 ParamType::Up(ParamDir::Z),
156 AutomationRate::A_rate,
157 0., f32::MIN, f32::MAX, );
161
162 AudioListener {
163 reflector_: Reflector::new(),
164 position_x: Dom::from_ref(&position_x),
165 position_y: Dom::from_ref(&position_y),
166 position_z: Dom::from_ref(&position_z),
167 forward_x: Dom::from_ref(&forward_x),
168 forward_y: Dom::from_ref(&forward_y),
169 forward_z: Dom::from_ref(&forward_z),
170 up_x: Dom::from_ref(&up_x),
171 up_y: Dom::from_ref(&up_y),
172 up_z: Dom::from_ref(&up_z),
173 }
174 }
175
176 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
177 pub(crate) fn new(
178 cx: &mut JSContext,
179 window: &Window,
180 context: &BaseAudioContext,
181 ) -> DomRoot<AudioListener> {
182 let node = AudioListener::new_inherited(cx, window, context);
183 reflect_dom_object(cx, Box::new(node), window)
184 }
185}
186
187#[expect(non_snake_case)]
188impl AudioListenerMethods<crate::DomTypeHolder> for AudioListener {
189 fn PositionX(&self) -> DomRoot<AudioParam> {
191 DomRoot::from_ref(&self.position_x)
192 }
193 fn PositionY(&self) -> DomRoot<AudioParam> {
195 DomRoot::from_ref(&self.position_y)
196 }
197 fn PositionZ(&self) -> DomRoot<AudioParam> {
199 DomRoot::from_ref(&self.position_z)
200 }
201
202 fn ForwardX(&self) -> DomRoot<AudioParam> {
204 DomRoot::from_ref(&self.forward_x)
205 }
206 fn ForwardY(&self) -> DomRoot<AudioParam> {
208 DomRoot::from_ref(&self.forward_y)
209 }
210 fn ForwardZ(&self) -> DomRoot<AudioParam> {
212 DomRoot::from_ref(&self.forward_z)
213 }
214
215 fn UpX(&self) -> DomRoot<AudioParam> {
217 DomRoot::from_ref(&self.up_x)
218 }
219 fn UpY(&self) -> DomRoot<AudioParam> {
221 DomRoot::from_ref(&self.up_y)
222 }
223 fn UpZ(&self) -> DomRoot<AudioParam> {
225 DomRoot::from_ref(&self.up_z)
226 }
227
228 fn SetOrientation(
230 &self,
231 x: Finite<f32>,
232 y: Finite<f32>,
233 z: Finite<f32>,
234 xUp: Finite<f32>,
235 yUp: Finite<f32>,
236 zUp: Finite<f32>,
237 ) -> Fallible<DomRoot<AudioListener>> {
238 self.forward_x.SetValue(x);
239 self.forward_y.SetValue(y);
240 self.forward_z.SetValue(z);
241 self.up_x.SetValue(xUp);
242 self.up_y.SetValue(yUp);
243 self.up_z.SetValue(zUp);
244 Ok(DomRoot::from_ref(self))
245 }
246
247 fn SetPosition(
249 &self,
250 x: Finite<f32>,
251 y: Finite<f32>,
252 z: Finite<f32>,
253 ) -> Fallible<DomRoot<AudioListener>> {
254 self.position_x.SetValue(x);
255 self.position_y.SetValue(y);
256 self.position_z.SetValue(z);
257 Ok(DomRoot::from_ref(self))
258 }
259}