1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef AudioParam_h_ 8 #define AudioParam_h_ 9 10 #include "AudioParamTimeline.h" 11 #include "nsWrapperCache.h" 12 #include "nsCycleCollectionParticipant.h" 13 #include "AudioNode.h" 14 #include "mozilla/dom/TypedArray.h" 15 #include "WebAudioUtils.h" 16 #include "js/TypeDecls.h" 17 18 namespace mozilla { 19 20 namespace dom { 21 22 class AudioParam final : public nsWrapperCache, public AudioParamTimeline { 23 virtual ~AudioParam(); 24 25 public: 26 AudioParam(AudioNode* aNode, uint32_t aIndex, const char16_t* aName, 27 float aDefaultValue, 28 float aMinValue = std::numeric_limits<float>::lowest(), 29 float aMaxValue = std::numeric_limits<float>::max()); 30 31 NS_IMETHOD_(MozExternalRefCountType) AddRef(void); 32 NS_IMETHOD_(MozExternalRefCountType) Release(void); NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(AudioParam)33 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(AudioParam) 34 35 AudioContext* GetParentObject() const { return mNode->Context(); } 36 37 JSObject* WrapObject(JSContext* aCx, 38 JS::Handle<JSObject*> aGivenProto) override; 39 Value()40 float Value() { 41 return AudioParamTimeline::GetValueAtTime<double>( 42 GetParentObject()->CurrentTime()); 43 } 44 45 // We override SetValueCurveAtTime to convert the Float32Array to the wrapper 46 // object. SetValueCurveAtTime(const nsTArray<float> & aValues,double aStartTime,double aDuration,ErrorResult & aRv)47 AudioParam* SetValueCurveAtTime(const nsTArray<float>& aValues, 48 double aStartTime, double aDuration, 49 ErrorResult& aRv) { 50 if (!WebAudioUtils::IsTimeValid(aStartTime)) { 51 aRv.ThrowRangeError<MSG_INVALID_AUDIOPARAM_METHOD_START_TIME_ERROR>(); 52 return this; 53 } 54 aStartTime = std::max(aStartTime, GetParentObject()->CurrentTime()); 55 EventInsertionHelper(aRv, AudioTimelineEvent::SetValueCurve, aStartTime, 56 0.0f, 0.0f, aDuration, aValues.Elements(), 57 aValues.Length()); 58 59 return this; 60 } 61 SetValue(float aValue)62 void SetValue(float aValue) { 63 AudioTimelineEvent event(AudioTimelineEvent::SetValue, 0.0f, aValue); 64 65 ErrorResult rv; 66 if (!ValidateEvent(event, rv)) { 67 MOZ_ASSERT(false, 68 "This should not happen, " 69 "setting the value should always work"); 70 return; 71 } 72 73 AudioParamTimeline::SetValue(aValue); 74 75 SendEventToEngine(event); 76 } 77 SetValueAtTime(float aValue,double aStartTime,ErrorResult & aRv)78 AudioParam* SetValueAtTime(float aValue, double aStartTime, 79 ErrorResult& aRv) { 80 if (!WebAudioUtils::IsTimeValid(aStartTime)) { 81 aRv.ThrowRangeError<MSG_INVALID_AUDIOPARAM_METHOD_START_TIME_ERROR>(); 82 return this; 83 } 84 aStartTime = std::max(aStartTime, GetParentObject()->CurrentTime()); 85 EventInsertionHelper(aRv, AudioTimelineEvent::SetValueAtTime, aStartTime, 86 aValue); 87 88 return this; 89 } 90 LinearRampToValueAtTime(float aValue,double aEndTime,ErrorResult & aRv)91 AudioParam* LinearRampToValueAtTime(float aValue, double aEndTime, 92 ErrorResult& aRv) { 93 if (!WebAudioUtils::IsTimeValid(aEndTime)) { 94 aRv.ThrowRangeError<MSG_INVALID_AUDIOPARAM_METHOD_END_TIME_ERROR>(); 95 return this; 96 } 97 aEndTime = std::max(aEndTime, GetParentObject()->CurrentTime()); 98 EventInsertionHelper(aRv, AudioTimelineEvent::LinearRamp, aEndTime, aValue); 99 return this; 100 } 101 ExponentialRampToValueAtTime(float aValue,double aEndTime,ErrorResult & aRv)102 AudioParam* ExponentialRampToValueAtTime(float aValue, double aEndTime, 103 ErrorResult& aRv) { 104 if (!WebAudioUtils::IsTimeValid(aEndTime)) { 105 aRv.ThrowRangeError<MSG_INVALID_AUDIOPARAM_METHOD_END_TIME_ERROR>(); 106 return this; 107 } 108 aEndTime = std::max(aEndTime, GetParentObject()->CurrentTime()); 109 EventInsertionHelper(aRv, AudioTimelineEvent::ExponentialRamp, aEndTime, 110 aValue); 111 return this; 112 } 113 SetTargetAtTime(float aTarget,double aStartTime,double aTimeConstant,ErrorResult & aRv)114 AudioParam* SetTargetAtTime(float aTarget, double aStartTime, 115 double aTimeConstant, ErrorResult& aRv) { 116 if (!WebAudioUtils::IsTimeValid(aStartTime) || 117 !WebAudioUtils::IsTimeValid(aTimeConstant)) { 118 aRv.ThrowRangeError<MSG_INVALID_AUDIOPARAM_METHOD_START_TIME_ERROR>(); 119 return this; 120 } 121 aStartTime = std::max(aStartTime, GetParentObject()->CurrentTime()); 122 EventInsertionHelper(aRv, AudioTimelineEvent::SetTarget, aStartTime, 123 aTarget, aTimeConstant); 124 125 return this; 126 } 127 CancelScheduledValues(double aStartTime,ErrorResult & aRv)128 AudioParam* CancelScheduledValues(double aStartTime, ErrorResult& aRv) { 129 if (!WebAudioUtils::IsTimeValid(aStartTime)) { 130 aRv.ThrowRangeError<MSG_INVALID_AUDIOPARAM_METHOD_START_TIME_ERROR>(); 131 return this; 132 } 133 134 aStartTime = std::max(aStartTime, GetParentObject()->CurrentTime()); 135 136 // Remove some events on the main thread copy. 137 AudioEventTimeline::CancelScheduledValues(aStartTime); 138 139 AudioTimelineEvent event(AudioTimelineEvent::Cancel, aStartTime, 0.0f); 140 141 SendEventToEngine(event); 142 143 return this; 144 } 145 ParentNodeId()146 uint32_t ParentNodeId() { return mNode->Id(); } 147 GetName(nsAString & aName)148 void GetName(nsAString& aName) { aName.Assign(mName); } 149 DefaultValue()150 float DefaultValue() const { return mDefaultValue; } 151 MinValue()152 float MinValue() const { return mMinValue; } 153 MaxValue()154 float MaxValue() const { return mMaxValue; } 155 IsTrackSuspended()156 bool IsTrackSuspended() const { 157 return mTrack ? mTrack->IsSuspended() : false; 158 } 159 InputNodes()160 const nsTArray<AudioNode::InputNode>& InputNodes() const { 161 return mInputNodes; 162 } 163 RemoveInputNode(uint32_t aIndex)164 void RemoveInputNode(uint32_t aIndex) { mInputNodes.RemoveElementAt(aIndex); } 165 AppendInputNode()166 AudioNode::InputNode* AppendInputNode() { 167 return mInputNodes.AppendElement(); 168 } 169 170 // May create the track if it doesn't exist 171 mozilla::MediaTrack* Track(); 172 173 // Return nullptr if track doesn't exist. 174 mozilla::MediaTrack* GetTrack() const; 175 SizeOfExcludingThis(MallocSizeOf aMallocSizeOf)176 size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override { 177 size_t amount = AudioParamTimeline::SizeOfExcludingThis(aMallocSizeOf); 178 // Not owned: 179 // - mNode 180 181 // Just count the array, actual nodes are counted in mNode. 182 amount += mInputNodes.ShallowSizeOfExcludingThis(aMallocSizeOf); 183 184 if (mNodeTrackPort) { 185 amount += mNodeTrackPort->SizeOfIncludingThis(aMallocSizeOf); 186 } 187 188 return amount; 189 } 190 SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)191 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override { 192 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); 193 } 194 195 private: 196 void EventInsertionHelper(ErrorResult& aRv, AudioTimelineEvent::Type aType, 197 double aTime, float aValue, 198 double aTimeConstant = 0.0, double aDuration = 0.0, 199 const float* aCurve = nullptr, 200 uint32_t aCurveLength = 0) { 201 AudioTimelineEvent event(aType, aTime, aValue, aTimeConstant, aDuration, 202 aCurve, aCurveLength); 203 204 if (!ValidateEvent(event, aRv)) { 205 return; 206 } 207 208 AudioEventTimeline::InsertEvent<double>(event); 209 210 SendEventToEngine(event); 211 212 CleanupOldEvents(); 213 } 214 215 void CleanupOldEvents(); 216 217 void SendEventToEngine(const AudioTimelineEvent& aEvent); 218 219 void DisconnectFromGraphAndDestroyTrack(); 220 221 nsCycleCollectingAutoRefCnt mRefCnt; 222 NS_DECL_OWNINGTHREAD 223 RefPtr<AudioNode> mNode; 224 // For every InputNode, there is a corresponding entry in mOutputParams of the 225 // InputNode's mInputNode. 226 nsTArray<AudioNode::InputNode> mInputNodes; 227 const char16_t* mName; 228 // The input port used to connect the AudioParam's track to its node's track 229 RefPtr<MediaInputPort> mNodeTrackPort; 230 const uint32_t mIndex; 231 const float mDefaultValue; 232 const float mMinValue; 233 const float mMaxValue; 234 }; 235 236 } // namespace dom 237 } // namespace mozilla 238 239 #endif 240