diff --git a/components/script/dom/audiolistener.rs b/components/script/dom/audiolistener.rs new file mode 100644 index 00000000000..bf6c9b20d44 --- /dev/null +++ b/components/script/dom/audiolistener.rs @@ -0,0 +1,190 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use dom::audioparam::AudioParam; +use dom::baseaudiocontext::BaseAudioContext; +use dom::bindings::codegen::Bindings::AudioListenerBinding::{self, AudioListenerMethods}; +use dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; +use dom::bindings::root::{Dom, DomRoot}; +use dom::window::Window; +use dom_struct::dom_struct; +use servo_media::audio::param::{ParamType, ParamDir}; +use std::f32; + +#[dom_struct] +pub struct AudioListener { + reflector_: Reflector, + position_x: Dom, + position_y: Dom, + position_z: Dom, + forward_x: Dom, + forward_y: Dom, + forward_z: Dom, + up_x: Dom, + up_y: Dom, + up_z: Dom, +} + +impl AudioListener { + fn new_inherited( + window: &Window, + context: &BaseAudioContext, + ) -> AudioListener { + let node = context.listener(); + + let position_x = AudioParam::new( + window, + context, + node, + ParamType::Position(ParamDir::X), + AutomationRate::A_rate, + 0., // default value + f32::MIN, // min value + f32::MAX, // max value + ); + let position_y = AudioParam::new( + window, + context, + node, + ParamType::Position(ParamDir::Y), + AutomationRate::A_rate, + 0., // default value + f32::MIN, // min value + f32::MAX, // max value + ); + let position_z = AudioParam::new( + window, + context, + node, + ParamType::Position(ParamDir::Z), + AutomationRate::A_rate, + 0., // default value + f32::MIN, // min value + f32::MAX, // max value + ); + let forward_x = AudioParam::new( + window, + context, + node, + ParamType::Forward(ParamDir::X), + AutomationRate::A_rate, + 0., // default value + f32::MIN, // min value + f32::MAX, // max value + ); + let forward_y = AudioParam::new( + window, + context, + node, + ParamType::Forward(ParamDir::Y), + AutomationRate::A_rate, + 0., // default value + f32::MIN, // min value + f32::MAX, // max value + ); + let forward_z = AudioParam::new( + window, + context, + node, + ParamType::Forward(ParamDir::Z), + AutomationRate::A_rate, + -1., // default value + f32::MIN, // min value + f32::MAX, // max value + ); + let up_x = AudioParam::new( + window, + context, + node, + ParamType::Up(ParamDir::X), + AutomationRate::A_rate, + 0., // default value + f32::MIN, // min value + f32::MAX, // max value + ); + let up_y = AudioParam::new( + window, + context, + node, + ParamType::Up(ParamDir::Y), + AutomationRate::A_rate, + 1., // default value + f32::MIN, // min value + f32::MAX, // max value + ); + let up_z = AudioParam::new( + window, + context, + node, + ParamType::Up(ParamDir::Z), + AutomationRate::A_rate, + 0., // default value + f32::MIN, // min value + f32::MAX, // max value + ); + AudioListener { + reflector_: Reflector::new(), + position_x: Dom::from_ref(&position_x), + position_y: Dom::from_ref(&position_y), + position_z: Dom::from_ref(&position_z), + forward_x: Dom::from_ref(&forward_x), + forward_y: Dom::from_ref(&forward_y), + forward_z: Dom::from_ref(&forward_z), + up_x: Dom::from_ref(&up_x), + up_y: Dom::from_ref(&up_y), + up_z: Dom::from_ref(&up_z), + } + } + + #[allow(unrooted_must_root)] + pub fn new( + window: &Window, + context: &BaseAudioContext, + ) -> DomRoot { + let node = AudioListener::new_inherited(window, context); + reflect_dom_object(Box::new(node), window, AudioListenerBinding::Wrap) + } +} + +impl AudioListenerMethods for AudioListener { + // https://webaudio.github.io/web-audio-api/#dom-audiolistener-positionx + fn PositionX(&self) -> DomRoot { + DomRoot::from_ref(&self.position_x) + } + // https://webaudio.github.io/web-audio-api/#dom-audiolistener-positiony + fn PositionY(&self) -> DomRoot { + DomRoot::from_ref(&self.position_y) + } + // https://webaudio.github.io/web-audio-api/#dom-audiolistener-positionz + fn PositionZ(&self) -> DomRoot { + DomRoot::from_ref(&self.position_z) + } + + // https://webaudio.github.io/web-audio-api/#dom-audiolistener-forwardx + fn ForwardX(&self) -> DomRoot { + DomRoot::from_ref(&self.forward_x) + } + // https://webaudio.github.io/web-audio-api/#dom-audiolistener-forwardy + fn ForwardY(&self) -> DomRoot { + DomRoot::from_ref(&self.forward_y) + } + // https://webaudio.github.io/web-audio-api/#dom-audiolistener-forwardz + fn ForwardZ(&self) -> DomRoot { + DomRoot::from_ref(&self.forward_z) + } + + // https://webaudio.github.io/web-audio-api/#dom-audiolistener-upx + fn UpX(&self) -> DomRoot { + DomRoot::from_ref(&self.up_x) + } + // https://webaudio.github.io/web-audio-api/#dom-audiolistener-upy + fn UpY(&self) -> DomRoot { + DomRoot::from_ref(&self.up_y) + } + // https://webaudio.github.io/web-audio-api/#dom-audiolistener-upz + fn UpZ(&self) -> DomRoot { + DomRoot::from_ref(&self.up_z) + } +} diff --git a/components/script/dom/baseaudiocontext.rs b/components/script/dom/baseaudiocontext.rs index 583b1690048..c32f3fdcc3d 100644 --- a/components/script/dom/baseaudiocontext.rs +++ b/components/script/dom/baseaudiocontext.rs @@ -5,6 +5,7 @@ use dom::audiobuffer::AudioBuffer; use dom::audiobuffersourcenode::AudioBufferSourceNode; use dom::audiodestinationnode::AudioDestinationNode; +use dom::audiolistener::AudioListener; use dom::audionode::MAX_CHANNEL_COUNT; use dom::bindings::callback::ExceptionHandling; use dom::bindings::cell::DomRefCell; @@ -66,6 +67,7 @@ pub struct BaseAudioContext { audio_context_impl: Rc>, /// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-destination destination: MutNullableDom, + listener: MutNullableDom, /// Resume promises which are soon to be fulfilled by a queued task. #[ignore_malloc_size_of = "promises are hard"] in_flight_resume_promises_queue: DomRefCell]>, ErrorResult)>>, @@ -101,6 +103,7 @@ impl BaseAudioContext { .create_audio_context(options.into()), ), destination: Default::default(), + listener: Default::default(), in_flight_resume_promises_queue: Default::default(), pending_resume_promises: Default::default(), decode_resolvers: Default::default(), @@ -125,6 +128,10 @@ impl BaseAudioContext { self.audio_context_impl.dest_node() } + pub fn listener(&self) -> NodeId { + self.audio_context_impl.listener() + } + // https://webaudio.github.io/web-audio-api/#allowed-to-start pub fn is_allowed_to_start(&self) -> bool { self.state.get() == AudioContextState::Suspended @@ -297,6 +304,15 @@ impl BaseAudioContextMethods for BaseAudioContext { }) } + /// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-listener + fn Listener(&self) -> DomRoot { + let global = self.global(); + let window = global.as_window(); + self.listener.or_init(|| { + AudioListener::new(&window, self) + }) + } + /// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-onstatechange event_handler!(statechange, GetOnstatechange, SetOnstatechange); diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index ba1668e9f43..efc36131e77 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -220,6 +220,7 @@ pub mod audiobuffer; pub mod audiobuffersourcenode; pub mod audiocontext; pub mod audiodestinationnode; +pub mod audiolistener; pub mod audionode; pub mod audioparam; pub mod audioscheduledsourcenode; diff --git a/components/script/dom/webidls/AudioListener.webidl b/components/script/dom/webidls/AudioListener.webidl new file mode 100644 index 00000000000..a98fecdd565 --- /dev/null +++ b/components/script/dom/webidls/AudioListener.webidl @@ -0,0 +1,22 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* + * The origin of this IDL file is + * https://webaudio.github.io/web-audio-api/#audiolistener + */ + +[Exposed=Window] +interface AudioListener { + readonly attribute AudioParam positionX; + readonly attribute AudioParam positionY; + readonly attribute AudioParam positionZ; + readonly attribute AudioParam forwardX; + readonly attribute AudioParam forwardY; + readonly attribute AudioParam forwardZ; + readonly attribute AudioParam upX; + readonly attribute AudioParam upY; + readonly attribute AudioParam upZ; + // void setPosition (float x, float y, float z); + // void setOrientation (float x, float y, float z, float xUp, float yUp, float zUp); +}; diff --git a/components/script/dom/webidls/BaseAudioContext.webidl b/components/script/dom/webidls/BaseAudioContext.webidl index 197ef3f357b..af0bc28a8be 100644 --- a/components/script/dom/webidls/BaseAudioContext.webidl +++ b/components/script/dom/webidls/BaseAudioContext.webidl @@ -20,7 +20,7 @@ interface BaseAudioContext : EventTarget { readonly attribute AudioDestinationNode destination; readonly attribute float sampleRate; readonly attribute double currentTime; - // readonly attribute AudioListener listener; + readonly attribute AudioListener listener; readonly attribute AudioContextState state; Promise resume(); attribute EventHandler onstatechange;