From e5b7cc7c9bd5605b6c0b4a718485071fcbcbe3f5 Mon Sep 17 00:00:00 2001 From: Maria Sable Date: Sat, 27 Apr 2019 10:02:14 -0400 Subject: [PATCH] StereoPannerNode DOM (need to implement backend in servo/media) --- components/script/dom/audionode.rs | 10 ++ components/script/dom/baseaudiocontext.rs | 12 ++ components/script/dom/mod.rs | 1 + components/script/dom/stereopannernode.rs | 109 ++++++++++++++++++ .../dom/webidls/BaseAudioContext.webidl | 2 +- .../dom/webidls/StereoPannerNode.webidl | 17 +++ 6 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 components/script/dom/stereopannernode.rs create mode 100644 components/script/dom/webidls/StereoPannerNode.webidl diff --git a/components/script/dom/audionode.rs b/components/script/dom/audionode.rs index 48751dabeac3..bc578a815460 100644 --- a/components/script/dom/audionode.rs +++ b/components/script/dom/audionode.rs @@ -236,6 +236,11 @@ impl AudioNodeMethods for AudioNode { return Err(Error::NotSupported); } }, + EventTargetTypeId::AudioNode(AudioNodeTypeId::StereoPannerNode) => { + if value > 2 { + return Err(Error::NotSupported); + } + }, EventTargetTypeId::AudioNode(AudioNodeTypeId::ChannelMergerNode) => { return Err(Error::InvalidState); }, @@ -280,6 +285,11 @@ impl AudioNodeMethods for AudioNode { return Err(Error::NotSupported); } }, + EventTargetTypeId::AudioNode(AudioNodeTypeId::StereoPannerNode) => { + if value == ChannelCountMode::Max { + return Err(Error::NotSupported); + } + }, EventTargetTypeId::AudioNode(AudioNodeTypeId::ChannelMergerNode) => { return Err(Error::InvalidState); }, diff --git a/components/script/dom/baseaudiocontext.rs b/components/script/dom/baseaudiocontext.rs index 1d69532c8b18..afb9ad0cfc14 100644 --- a/components/script/dom/baseaudiocontext.rs +++ b/components/script/dom/baseaudiocontext.rs @@ -22,6 +22,7 @@ use crate::dom::bindings::codegen::Bindings::BaseAudioContextBinding::BaseAudioC use crate::dom::bindings::codegen::Bindings::BaseAudioContextBinding::DecodeErrorCallback; use crate::dom::bindings::codegen::Bindings::BaseAudioContextBinding::DecodeSuccessCallback; use crate::dom::bindings::codegen::Bindings::BiquadFilterNodeBinding::BiquadFilterOptions; +use crate::dom::bindings::codegen::Bindings::StereoPannerNodeBinding::StereoPannerOptions; use crate::dom::bindings::codegen::Bindings::ChannelMergerNodeBinding::ChannelMergerOptions; use crate::dom::bindings::codegen::Bindings::ChannelSplitterNodeBinding::ChannelSplitterOptions; use crate::dom::bindings::codegen::Bindings::GainNodeBinding::GainOptions; @@ -36,6 +37,7 @@ use crate::dom::bindings::root::{DomRoot, MutNullableDom}; use crate::dom::biquadfilternode::BiquadFilterNode; use crate::dom::channelmergernode::ChannelMergerNode; use crate::dom::channelsplitternode::ChannelSplitterNode; +use crate::dom::stereopannernode::StereoPannerNode; use crate::dom::domexception::{DOMErrorName, DOMException}; use crate::dom::eventtarget::EventTarget; use crate::dom::gainnode::GainNode; @@ -361,6 +363,16 @@ impl BaseAudioContextMethods for BaseAudioContext { ) } + + /// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createstereopanner + fn CreateStereoPanner(&self) -> Fallible> { + StereoPannerNode::new( + &self.global().as_window(), + &self, + &StereoPannerOptions::empty(), + ) + } + /// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createchannelmerger fn CreateChannelMerger(&self, count: u32) -> Fallible> { let mut opts = ChannelMergerOptions::empty(); diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 776d20299c15..ff1688fb6c36 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -457,6 +457,7 @@ pub mod serviceworkerglobalscope; pub mod serviceworkerregistration; pub mod servoparser; pub mod shadowroot; +pub mod stereopannernode; pub mod storage; pub mod storageevent; pub mod stylepropertymapreadonly; diff --git a/components/script/dom/stereopannernode.rs b/components/script/dom/stereopannernode.rs new file mode 100644 index 000000000000..6966bee1a277 --- /dev/null +++ b/components/script/dom/stereopannernode.rs @@ -0,0 +1,109 @@ +/* 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 https://mozilla.org/MPL/2.0/. */ + +use crate::dom::audioparam::AudioParam; +use crate::dom::audioscheduledsourcenode::AudioScheduledSourceNode; +use crate::dom::baseaudiocontext::BaseAudioContext; +use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{ + ChannelCountMode, ChannelInterpretation, +}; +use crate::dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate; +use crate::dom::bindings::codegen::Bindings::StereoPannerNodeBinding::StereoPannerNodeMethods; +use crate::dom::bindings::codegen::Bindings::StereoPannerNodeBinding::{ + self, StereoPannerOptions, +}; +use crate::dom::bindings::error::Fallible; +use crate::dom::bindings::reflector::reflect_dom_object; +use crate::dom::bindings::root::{Dom, DomRoot}; +use crate::dom::window::Window; +use dom_struct::dom_struct; +use servo_media::audio::stereo_panner_node::StereoPannerOptions as ServoMediaStereoPannerOptions; +use servo_media::audio::node::AudioNodeInit; +use servo_media::audio::param::ParamType; +use std::f32; + +#[dom_struct] +pub struct StereoPannerNode { + source_node: AudioScheduledSourceNode, + offset: Dom, +} + +impl StereoPannerNode { + #[allow(unrooted_must_root)] + pub fn new_inherited( + window: &Window, + context: &BaseAudioContext, + options: &StereoPannerOptions, + ) -> Fallible { + let node_options = + options + .parent + .unwrap_or(2, ChannelCountMode::ClampedMax, ChannelInterpretation::Speakers); + if node_options.mode == ChannelCountMode::Max { + return Err(Error::NotSupported); + } + if node_options.count > 2 || node_options.count == 0 { + return Err(Error::NotSupported); + } + let source_node = AudioScheduledSourceNode::new_inherited( + AudioNodeInit::StereoPannerNode(options.into()), + context, + node_options, + 0, /* inputs */ + 1, /* outputs */ + )?; + let node_id = source_node.node().node_id(); + let offset = AudioParam::new( + window, + context, + node_id, + ParamType::Offset, + AutomationRate::A_rate, + 1., + f32::MIN, + f32::MAX, + ); + + Ok(StereoPannerNode { + source_node, + offset: Dom::from_ref(&offset), + }) + } + + #[allow(unrooted_must_root)] + pub fn new( + window: &Window, + context: &BaseAudioContext, + options: &StereoPannerOptions, + ) -> Fallible> { + let node = StereoPannerNode::new_inherited(window, context, options)?; + Ok(reflect_dom_object( + Box::new(node), + window, + StereoPannerNodeBinding::Wrap, + )) + } + + pub fn Constructor( + window: &Window, + context: &BaseAudioContext, + options: &StereoPannerOptions, + ) -> Fallible> { + StereoPannerNode::new(window, context, options) + } +} + +impl StereoPannerNodeMethods for StereoPannerNode { + fn Offset(&self) -> DomRoot { + DomRoot::from_ref(&self.offset) + } +} + +impl<'a> From<&'a StereoPannerOptions> for ServoMediaStereoPannerOptions { + fn from(options: &'a StereoPannerOptions) -> Self { + Self { + offset: *options.offset, + } + } +} diff --git a/components/script/dom/webidls/BaseAudioContext.webidl b/components/script/dom/webidls/BaseAudioContext.webidl index 0f645177d31e..ee2cbc7c2d3e 100644 --- a/components/script/dom/webidls/BaseAudioContext.webidl +++ b/components/script/dom/webidls/BaseAudioContext.webidl @@ -43,7 +43,7 @@ interface BaseAudioContext : EventTarget { // sequence feedback); // WaveShaperNode createWaveShaper(); [Throws] PannerNode createPanner(); - // StereoPannerNode createStereoPanner(); + [Throws] StereoPannerNode createStereoPanner(); // ConvolverNode createConvolver(); [Throws] ChannelSplitterNode createChannelSplitter(optional unsigned long numberOfOutputs = 6); [Throws] ChannelMergerNode createChannelMerger(optional unsigned long numberOfInputs = 6); diff --git a/components/script/dom/webidls/StereoPannerNode.webidl b/components/script/dom/webidls/StereoPannerNode.webidl new file mode 100644 index 000000000000..0926396ef07b --- /dev/null +++ b/components/script/dom/webidls/StereoPannerNode.webidl @@ -0,0 +1,17 @@ +/* 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 https://mozilla.org/MPL/2.0/. */ +/* + * The origin of this IDL file is + * https://webaudio.github.io/web-audio-api/#StereoPannerNode + */ + +dictionary StereoPannerOptions: AudioNodeOptions { + float pan = 0; +}; + +[Exposed=Window, + Constructor (BaseAudioContext context, optional StereoPannerOptions options)] +interface StereoPannerNode : AudioScheduledSourceNode { + readonly attribute AudioParam offset; +};