Bug 836076 - Part 3: Make AudioParams call back into their owning node when they're modified; r=roc
☠☠ backed out by 7f08319059b3 ☠ ☠
authorEhsan Akhgari <ehsan@mozilla.com>
Mon, 28 Jan 2013 18:59:29 -0500
changeset 130719 d567b1bb34ad000c101beb7b4d8f84ff5ed0fe4c
parent 130718 51f7c9e31f9a812bf16fe1b4e0381417f7eebd40
child 130720 7f08319059b3da1a0892e7a66bfd6daead7d155f
push id2323
push userbbajaj@mozilla.com
push dateMon, 01 Apr 2013 19:47:02 +0000
treeherdermozilla-beta@7712be144d91 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs836076
milestone21.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 836076 - Part 3: Make AudioParams call back into their owning node when they're modified; r=roc We need this in order to update the MediaStreamGraph thread when an AudioParam changes. This enables each AudioParam to be registered with a callback from its owner node, so that the owner node can have custom processing code for each AudioParam's mutation.
content/media/webaudio/AudioNode.h
content/media/webaudio/AudioParam.cpp
content/media/webaudio/AudioParam.h
content/media/webaudio/BiquadFilterNode.cpp
content/media/webaudio/DelayNode.cpp
content/media/webaudio/DynamicsCompressorNode.cpp
content/media/webaudio/GainNode.cpp
--- a/content/media/webaudio/AudioNode.h
+++ b/content/media/webaudio/AudioNode.h
@@ -127,16 +127,19 @@ public:
   void SetProduceOwnOutput(bool aCanProduceOwnOutput)
   {
     mCanProduceOwnOutput = aCanProduceOwnOutput;
     if (!aCanProduceOwnOutput) {
       UpdateOutputEnded();
     }
   }
 
+protected:
+  static void Callback(AudioNode* aNode) { /* not implemented */ }
+
 private:
   nsRefPtr<AudioContext> mContext;
 
 protected:
   // Must be set in the constructor. Must not be null.
   // If MaxNumberOfInputs() is > 0, then mStream must be a ProcessedMediaStream.
   nsRefPtr<MediaStream> mStream;
 
--- a/content/media/webaudio/AudioParam.cpp
+++ b/content/media/webaudio/AudioParam.cpp
@@ -8,27 +8,29 @@
 #include "nsContentUtils.h"
 #include "nsIDOMWindow.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/AudioParamBinding.h"
 
 namespace mozilla {
 namespace dom {
 
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(AudioParam, mContext)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(AudioParam, mNode)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AudioParam, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AudioParam, Release)
 
-AudioParam::AudioParam(AudioContext* aContext,
+AudioParam::AudioParam(AudioNode* aNode,
+                       AudioParam::CallbackType aCallback,
                        float aDefaultValue,
                        float aMinValue,
                        float aMaxValue)
   : AudioParamTimeline(aDefaultValue)
-  , mContext(aContext)
+  , mNode(aNode)
+  , mCallback(aCallback)
   , mDefaultValue(aDefaultValue)
   , mMinValue(aMinValue)
   , mMaxValue(aMaxValue)
 {
   MOZ_ASSERT(aDefaultValue >= aMinValue);
   MOZ_ASSERT(aDefaultValue <= aMaxValue);
   MOZ_ASSERT(aMinValue < aMaxValue);
   SetIsDOMBinding();
--- a/content/media/webaudio/AudioParam.h
+++ b/content/media/webaudio/AudioParam.h
@@ -8,17 +8,17 @@
 #define AudioParam_h_
 
 #include "AudioEventTimeline.h"
 #include "nsWrapperCache.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsCOMPtr.h"
 #include "EnableWebAudioCheck.h"
 #include "nsAutoPtr.h"
-#include "AudioContext.h"
+#include "AudioNode.h"
 #include "mozilla/dom/TypedArray.h"
 #include "mozilla/Util.h"
 #include "mozilla/ErrorResult.h"
 
 struct JSContext;
 class nsIDOMWindow;
 
 namespace mozilla {
@@ -27,39 +27,76 @@ namespace dom {
 
 typedef AudioEventTimeline<ErrorResult> AudioParamTimeline;
 
 class AudioParam MOZ_FINAL : public nsWrapperCache,
                              public EnableWebAudioCheck,
                              public AudioParamTimeline
 {
 public:
-  AudioParam(AudioContext* aContext,
+  typedef void (*CallbackType)(AudioNode*);
+
+  AudioParam(AudioNode* aNode,
+             CallbackType aCallback,
              float aDefaultValue,
              float aMinValue,
              float aMaxValue);
   virtual ~AudioParam();
 
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AudioParam)
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(AudioParam)
 
   AudioContext* GetParentObject() const
   {
-    return mContext;
+    return mNode->Context();
   }
 
   virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope,
                                bool* aTriedToWrap);
 
   // We override SetValueCurveAtTime to convert the Float32Array to the wrapper
   // object.
   void SetValueCurveAtTime(JSContext* cx, const Float32Array& aValues, double aStartTime, double aDuration, ErrorResult& aRv)
   {
     AudioParamTimeline::SetValueCurveAtTime(aValues.Data(), aValues.Length(),
                                             aStartTime, aDuration, aRv);
+    mCallback(mNode);
+  }
+
+  // We override the rest of the mutating AudioParamTimeline methods in order to make
+  // sure that the callback is called every time that this object gets mutated.
+  void SetValue(float aValue)
+  {
+    AudioParamTimeline::SetValue(aValue);
+    mCallback(mNode);
+  }
+  void SetValueAtTime(float aValue, double aStartTime, ErrorResult& aRv)
+  {
+    AudioParamTimeline::SetValueAtTime(aValue, aStartTime, aRv);
+    mCallback(mNode);
+  }
+  void LinearRampToValueAtTime(float aValue, double aEndTime, ErrorResult& aRv)
+  {
+    AudioParamTimeline::LinearRampToValueAtTime(aValue, aEndTime, aRv);
+    mCallback(mNode);
+  }
+  void ExponentialRampToValueAtTime(float aValue, double aEndTime, ErrorResult& aRv)
+  {
+    AudioParamTimeline::ExponentialRampToValueAtTime(aValue, aEndTime, aRv);
+    mCallback(mNode);
+  }
+  void SetTargetAtTime(float aTarget, double aStartTime, double aTimeConstant, ErrorResult& aRv)
+  {
+    AudioParamTimeline::SetTargetAtTime(aTarget, aStartTime, aTimeConstant, aRv);
+    mCallback(mNode);
+  }
+  void CancelScheduledValues(double aStartTime)
+  {
+    AudioParamTimeline::CancelScheduledValues(aStartTime);
+    mCallback(mNode);
   }
 
   float MinValue() const
   {
     return mMinValue;
   }
 
   float MaxValue() const
@@ -68,17 +105,18 @@ public:
   }
 
   float DefaultValue() const
   {
     return mDefaultValue;
   }
 
 private:
-  nsRefPtr<AudioContext> mContext;
+  nsRefPtr<AudioNode> mNode;
+  CallbackType mCallback;
   const float mDefaultValue;
   const float mMinValue;
   const float mMaxValue;
 };
 
 }
 }
 
--- a/content/media/webaudio/BiquadFilterNode.cpp
+++ b/content/media/webaudio/BiquadFilterNode.cpp
@@ -23,19 +23,19 @@ static float
 Nyquist(AudioContext* aContext)
 {
   return 0.5f * aContext->SampleRate();
 }
 
 BiquadFilterNode::BiquadFilterNode(AudioContext* aContext)
   : AudioNode(aContext)
   , mType(BiquadTypeEnum::LOWPASS)
-  , mFrequency(new AudioParam(aContext, 350.f, 10.f, Nyquist(aContext)))
-  , mQ(new AudioParam(aContext, 1.f, 0.0001f, 1000.f))
-  , mGain(new AudioParam(aContext, 0.f, -40.f, 40.f))
+  , mFrequency(new AudioParam(this, Callback, 350.f, 10.f, Nyquist(aContext)))
+  , mQ(new AudioParam(this, Callback, 1.f, 0.0001f, 1000.f))
+  , mGain(new AudioParam(this, Callback, 0.f, -40.f, 40.f))
 {
 }
 
 JSObject*
 BiquadFilterNode::WrapObject(JSContext* aCx, JSObject* aScope)
 {
   return BiquadFilterNodeBinding::Wrap(aCx, aScope, this);
 }
--- a/content/media/webaudio/DelayNode.cpp
+++ b/content/media/webaudio/DelayNode.cpp
@@ -16,17 +16,17 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED_1(Del
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DelayNode)
 NS_INTERFACE_MAP_END_INHERITING(AudioNode)
 
 NS_IMPL_ADDREF_INHERITED(DelayNode, AudioNode)
 NS_IMPL_RELEASE_INHERITED(DelayNode, AudioNode)
 
 DelayNode::DelayNode(AudioContext* aContext, double aMaxDelay)
   : AudioNode(aContext)
-  , mDelay(new AudioParam(aContext, 0.0f, 0.0f, float(aMaxDelay)))
+  , mDelay(new AudioParam(this, Callback, 0.0f, 0.0f, float(aMaxDelay)))
 {
 }
 
 JSObject*
 DelayNode::WrapObject(JSContext* aCx, JSObject* aScope)
 {
   return DelayNodeBinding::Wrap(aCx, aScope, this);
 }
--- a/content/media/webaudio/DynamicsCompressorNode.cpp
+++ b/content/media/webaudio/DynamicsCompressorNode.cpp
@@ -21,22 +21,22 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED_6(Dyn
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DynamicsCompressorNode)
 NS_INTERFACE_MAP_END_INHERITING(AudioNode)
 
 NS_IMPL_ADDREF_INHERITED(DynamicsCompressorNode, AudioNode)
 NS_IMPL_RELEASE_INHERITED(DynamicsCompressorNode, AudioNode)
 
 DynamicsCompressorNode::DynamicsCompressorNode(AudioContext* aContext)
   : AudioNode(aContext)
-  , mThreshold(new AudioParam(aContext, -24.f, -100.f, 0.f))
-  , mKnee(new AudioParam(aContext, 30.f, 0.f, 40.f))
-  , mRatio(new AudioParam(aContext, 12.f, 1.f, 20.f))
-  , mReduction(new AudioParam(aContext, 0.f, -20.f, 0.f))
-  , mAttack(new AudioParam(aContext, 0.003f, 0.f, 1.f))
-  , mRelease(new AudioParam(aContext, 0.25f, 0.f, 1.f))
+  , mThreshold(new AudioParam(this, Callback, -24.f, -100.f, 0.f))
+  , mKnee(new AudioParam(this, Callback, 30.f, 0.f, 40.f))
+  , mRatio(new AudioParam(this, Callback, 12.f, 1.f, 20.f))
+  , mReduction(new AudioParam(this, Callback, 0.f, -20.f, 0.f))
+  , mAttack(new AudioParam(this, Callback, 0.003f, 0.f, 1.f))
+  , mRelease(new AudioParam(this, Callback, 0.25f, 0.f, 1.f))
 {
 }
 
 JSObject*
 DynamicsCompressorNode::WrapObject(JSContext* aCx, JSObject* aScope)
 {
   return DynamicsCompressorNodeBinding::Wrap(aCx, aScope, this);
 }
--- a/content/media/webaudio/GainNode.cpp
+++ b/content/media/webaudio/GainNode.cpp
@@ -16,17 +16,17 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED_1(Gai
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(GainNode)
 NS_INTERFACE_MAP_END_INHERITING(AudioNode)
 
 NS_IMPL_ADDREF_INHERITED(GainNode, AudioNode)
 NS_IMPL_RELEASE_INHERITED(GainNode, AudioNode)
 
 GainNode::GainNode(AudioContext* aContext)
   : AudioNode(aContext)
-  , mGain(new AudioParam(aContext, 1.0f, 0.0f, 1.0f))
+  , mGain(new AudioParam(this, Callback, 1.0f, 0.0f, 1.0f))
 {
 }
 
 JSObject*
 GainNode::WrapObject(JSContext* aCx, JSObject* aScope)
 {
   return GainNodeBinding::Wrap(aCx, aScope, this);
 }