1use std::f32;
6
7use dom_struct::dom_struct;
8use js::context::JSContext;
9use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
10use servo_media::audio::node::AudioNodeType;
11use servo_media::audio::param::{ParamDir, ParamType};
12
13use crate::dom::audio::audioparam::AudioParam;
14use crate::dom::audio::baseaudiocontext::BaseAudioContext;
15use crate::dom::bindings::codegen::Bindings::AudioListenerBinding::AudioListenerMethods;
16use crate::dom::bindings::codegen::Bindings::AudioParamBinding::{
17 AudioParamMethods, AutomationRate,
18};
19use crate::dom::bindings::error::Fallible;
20use crate::dom::bindings::num::Finite;
21use crate::dom::bindings::root::{Dom, DomRoot};
22use crate::dom::window::Window;
23
24#[dom_struct]
25pub(crate) struct AudioListener {
26 reflector_: Reflector,
27 position_x: Dom<AudioParam>,
28 position_y: Dom<AudioParam>,
29 position_z: Dom<AudioParam>,
30 forward_x: Dom<AudioParam>,
31 forward_y: Dom<AudioParam>,
32 forward_z: Dom<AudioParam>,
33 up_x: Dom<AudioParam>,
34 up_y: Dom<AudioParam>,
35 up_z: Dom<AudioParam>,
36}
37
38impl AudioListener {
39 fn new_inherited(
40 cx: &mut JSContext,
41 window: &Window,
42 context: &BaseAudioContext,
43 ) -> AudioListener {
44 let node = context.listener();
45
46 let position_x = AudioParam::new(
47 cx,
48 window,
49 context,
50 Some(node),
51 AudioNodeType::AudioListenerNode,
52 ParamType::Position(ParamDir::X),
53 AutomationRate::A_rate,
54 0., f32::MIN, f32::MAX, );
58 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(
71 cx,
72 window,
73 context,
74 Some(node),
75 AudioNodeType::AudioListenerNode,
76 ParamType::Position(ParamDir::Z),
77 AutomationRate::A_rate,
78 0., f32::MIN, f32::MAX, );
82 let forward_x = AudioParam::new(
83 cx,
84 window,
85 context,
86 Some(node),
87 AudioNodeType::AudioListenerNode,
88 ParamType::Forward(ParamDir::X),
89 AutomationRate::A_rate,
90 0., f32::MIN, f32::MAX, );
94 let forward_y = AudioParam::new(
95 cx,
96 window,
97 context,
98 Some(node),
99 AudioNodeType::AudioListenerNode,
100 ParamType::Forward(ParamDir::Y),
101 AutomationRate::A_rate,
102 0., f32::MIN, f32::MAX, );
106 let forward_z = AudioParam::new(
107 cx,
108 window,
109 context,
110 Some(node),
111 AudioNodeType::AudioListenerNode,
112 ParamType::Forward(ParamDir::Z),
113 AutomationRate::A_rate,
114 -1., f32::MIN, f32::MAX, );
118 let up_x = AudioParam::new(
119 cx,
120 window,
121 context,
122 Some(node),
123 AudioNodeType::AudioListenerNode,
124 ParamType::Up(ParamDir::X),
125 AutomationRate::A_rate,
126 0., f32::MIN, f32::MAX, );
130 let up_y = AudioParam::new(
131 cx,
132 window,
133 context,
134 Some(node),
135 AudioNodeType::AudioListenerNode,
136 ParamType::Up(ParamDir::Y),
137 AutomationRate::A_rate,
138 1., f32::MIN, f32::MAX, );
142 let up_z = AudioParam::new(
143 cx,
144 window,
145 context,
146 Some(node),
147 AudioNodeType::AudioListenerNode,
148 ParamType::Up(ParamDir::Z),
149 AutomationRate::A_rate,
150 0., f32::MIN, f32::MAX, );
154
155 AudioListener {
156 reflector_: Reflector::new(),
157 position_x: Dom::from_ref(&position_x),
158 position_y: Dom::from_ref(&position_y),
159 position_z: Dom::from_ref(&position_z),
160 forward_x: Dom::from_ref(&forward_x),
161 forward_y: Dom::from_ref(&forward_y),
162 forward_z: Dom::from_ref(&forward_z),
163 up_x: Dom::from_ref(&up_x),
164 up_y: Dom::from_ref(&up_y),
165 up_z: Dom::from_ref(&up_z),
166 }
167 }
168
169 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
170 pub(crate) fn new(
171 cx: &mut JSContext,
172 window: &Window,
173 context: &BaseAudioContext,
174 ) -> DomRoot<AudioListener> {
175 let node = AudioListener::new_inherited(cx, window, context);
176 reflect_dom_object_with_cx(Box::new(node), window, cx)
177 }
178}
179
180#[expect(non_snake_case)]
181impl AudioListenerMethods<crate::DomTypeHolder> for AudioListener {
182 fn PositionX(&self) -> DomRoot<AudioParam> {
184 DomRoot::from_ref(&self.position_x)
185 }
186 fn PositionY(&self) -> DomRoot<AudioParam> {
188 DomRoot::from_ref(&self.position_y)
189 }
190 fn PositionZ(&self) -> DomRoot<AudioParam> {
192 DomRoot::from_ref(&self.position_z)
193 }
194
195 fn ForwardX(&self) -> DomRoot<AudioParam> {
197 DomRoot::from_ref(&self.forward_x)
198 }
199 fn ForwardY(&self) -> DomRoot<AudioParam> {
201 DomRoot::from_ref(&self.forward_y)
202 }
203 fn ForwardZ(&self) -> DomRoot<AudioParam> {
205 DomRoot::from_ref(&self.forward_z)
206 }
207
208 fn UpX(&self) -> DomRoot<AudioParam> {
210 DomRoot::from_ref(&self.up_x)
211 }
212 fn UpY(&self) -> DomRoot<AudioParam> {
214 DomRoot::from_ref(&self.up_y)
215 }
216 fn UpZ(&self) -> DomRoot<AudioParam> {
218 DomRoot::from_ref(&self.up_z)
219 }
220
221 fn SetOrientation(
223 &self,
224 x: Finite<f32>,
225 y: Finite<f32>,
226 z: Finite<f32>,
227 xUp: Finite<f32>,
228 yUp: Finite<f32>,
229 zUp: Finite<f32>,
230 ) -> Fallible<DomRoot<AudioListener>> {
231 self.forward_x.SetValue(x);
232 self.forward_y.SetValue(y);
233 self.forward_z.SetValue(z);
234 self.up_x.SetValue(xUp);
235 self.up_y.SetValue(yUp);
236 self.up_z.SetValue(zUp);
237 Ok(DomRoot::from_ref(self))
238 }
239
240 fn SetPosition(
242 &self,
243 x: Finite<f32>,
244 y: Finite<f32>,
245 z: Finite<f32>,
246 ) -> Fallible<DomRoot<AudioListener>> {
247 self.position_x.SetValue(x);
248 self.position_y.SetValue(y);
249 self.position_z.SetValue(z);
250 Ok(DomRoot::from_ref(self))
251 }
252}