Line data Source code
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,
23 : public AudioParamTimeline
24 : {
25 : virtual ~AudioParam();
26 :
27 : public:
28 : AudioParam(AudioNode* aNode,
29 : uint32_t aIndex,
30 : const char* aName,
31 : float aDefaultValue,
32 0 : float aMinValue = -std::numeric_limits<float>::infinity(),
33 0 : float aMaxValue = std::numeric_limits<float>::infinity());
34 :
35 : NS_IMETHOD_(MozExternalRefCountType) AddRef(void);
36 : NS_IMETHOD_(MozExternalRefCountType) Release(void);
37 0 : NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(AudioParam)
38 :
39 0 : AudioContext* GetParentObject() const
40 : {
41 0 : return mNode->Context();
42 : }
43 :
44 : JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
45 :
46 : // We override SetValueCurveAtTime to convert the Float32Array to the wrapper
47 : // object.
48 0 : AudioParam* SetValueCurveAtTime(const Float32Array& aValues,
49 : double aStartTime,
50 : double aDuration,
51 : ErrorResult& aRv)
52 : {
53 0 : if (!WebAudioUtils::IsTimeValid(aStartTime)) {
54 0 : aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
55 0 : return this;
56 : }
57 0 : aValues.ComputeLengthAndData();
58 :
59 0 : aStartTime = std::max(aStartTime, GetParentObject()->CurrentTime());
60 0 : EventInsertionHelper(aRv, AudioTimelineEvent::SetValueCurve,
61 0 : aStartTime, 0.0f, 0.0f, aDuration, aValues.Data(),
62 0 : aValues.Length());
63 0 : return this;
64 : }
65 :
66 0 : void SetValue(float aValue)
67 : {
68 0 : AudioTimelineEvent event(AudioTimelineEvent::SetValue, 0.0f, aValue);
69 :
70 0 : ErrorResult rv;
71 0 : if (!ValidateEvent(event, rv)) {
72 0 : MOZ_ASSERT(false, "This should not happen, "
73 : "setting the value should always work");
74 : return;
75 : }
76 :
77 0 : AudioParamTimeline::SetValue(aValue);
78 :
79 0 : SendEventToEngine(event);
80 0 : }
81 :
82 0 : AudioParam* SetValueAtTime(float aValue, double aStartTime, ErrorResult& aRv)
83 : {
84 0 : if (!WebAudioUtils::IsTimeValid(aStartTime)) {
85 0 : aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
86 0 : return this;
87 : }
88 0 : aStartTime = std::max(aStartTime, GetParentObject()->CurrentTime());
89 : EventInsertionHelper(aRv, AudioTimelineEvent::SetValueAtTime,
90 0 : aStartTime, aValue);
91 :
92 0 : return this;
93 : }
94 :
95 0 : AudioParam* LinearRampToValueAtTime(float aValue, double aEndTime,
96 : ErrorResult& aRv)
97 : {
98 0 : if (!WebAudioUtils::IsTimeValid(aEndTime)) {
99 0 : aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
100 0 : return this;
101 : }
102 0 : aEndTime = std::max(aEndTime, GetParentObject()->CurrentTime());
103 0 : EventInsertionHelper(aRv, AudioTimelineEvent::LinearRamp, aEndTime, aValue);
104 0 : return this;
105 : }
106 :
107 0 : AudioParam* ExponentialRampToValueAtTime(float aValue, double aEndTime,
108 : ErrorResult& aRv)
109 : {
110 0 : if (!WebAudioUtils::IsTimeValid(aEndTime)) {
111 0 : aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
112 0 : return this;
113 : }
114 0 : aEndTime = std::max(aEndTime, GetParentObject()->CurrentTime());
115 : EventInsertionHelper(aRv, AudioTimelineEvent::ExponentialRamp,
116 0 : aEndTime, aValue);
117 0 : return this;
118 : }
119 :
120 0 : AudioParam* SetTargetAtTime(float aTarget, double aStartTime,
121 : double aTimeConstant, ErrorResult& aRv)
122 : {
123 0 : if (!WebAudioUtils::IsTimeValid(aStartTime) ||
124 0 : !WebAudioUtils::IsTimeValid(aTimeConstant)) {
125 0 : aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
126 0 : return this;
127 : }
128 0 : aStartTime = std::max(aStartTime, GetParentObject()->CurrentTime());
129 : EventInsertionHelper(aRv, AudioTimelineEvent::SetTarget,
130 : aStartTime, aTarget,
131 0 : aTimeConstant);
132 :
133 0 : return this;
134 : }
135 :
136 0 : AudioParam* CancelScheduledValues(double aStartTime, ErrorResult& aRv)
137 : {
138 0 : if (!WebAudioUtils::IsTimeValid(aStartTime)) {
139 0 : aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
140 0 : return this;
141 : }
142 :
143 0 : aStartTime = std::max(aStartTime, GetParentObject()->CurrentTime());
144 :
145 : // Remove some events on the main thread copy.
146 0 : AudioEventTimeline::CancelScheduledValues(aStartTime);
147 :
148 0 : AudioTimelineEvent event(AudioTimelineEvent::Cancel, aStartTime, 0.0f);
149 :
150 0 : SendEventToEngine(event);
151 :
152 0 : return this;
153 : }
154 :
155 0 : uint32_t ParentNodeId()
156 : {
157 0 : return mNode->Id();
158 : }
159 :
160 0 : void GetName(nsAString& aName)
161 : {
162 0 : aName.AssignASCII(mName);
163 0 : }
164 :
165 0 : float DefaultValue() const
166 : {
167 0 : return mDefaultValue;
168 : }
169 :
170 0 : float MinValue() const
171 : {
172 0 : return mMinValue;
173 : }
174 :
175 0 : float MaxValue() const
176 : {
177 0 : return mMaxValue;
178 : }
179 :
180 0 : const nsTArray<AudioNode::InputNode>& InputNodes() const
181 : {
182 0 : return mInputNodes;
183 : }
184 :
185 0 : void RemoveInputNode(uint32_t aIndex)
186 : {
187 0 : mInputNodes.RemoveElementAt(aIndex);
188 0 : }
189 :
190 0 : AudioNode::InputNode* AppendInputNode()
191 : {
192 0 : return mInputNodes.AppendElement();
193 : }
194 :
195 : // May create the stream if it doesn't exist
196 : MediaStream* Stream();
197 :
198 0 : size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
199 : {
200 0 : size_t amount = AudioParamTimeline::SizeOfExcludingThis(aMallocSizeOf);
201 : // Not owned:
202 : // - mNode
203 :
204 : // Just count the array, actual nodes are counted in mNode.
205 0 : amount += mInputNodes.ShallowSizeOfExcludingThis(aMallocSizeOf);
206 :
207 0 : if (mNodeStreamPort) {
208 0 : amount += mNodeStreamPort->SizeOfIncludingThis(aMallocSizeOf);
209 : }
210 :
211 0 : return amount;
212 : }
213 :
214 0 : size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override
215 : {
216 0 : return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
217 : }
218 :
219 : private:
220 0 : void EventInsertionHelper(ErrorResult& aRv,
221 : AudioTimelineEvent::Type aType,
222 : double aTime, float aValue,
223 : double aTimeConstant = 0.0,
224 : float aDuration = 0.0,
225 : const float* aCurve = nullptr,
226 : uint32_t aCurveLength = 0)
227 : {
228 : AudioTimelineEvent event(aType, aTime, aValue,
229 0 : aTimeConstant, aDuration, aCurve, aCurveLength);
230 :
231 0 : if (!ValidateEvent(event, aRv)) {
232 0 : return;
233 : }
234 :
235 0 : AudioEventTimeline::InsertEvent<double>(event);
236 :
237 0 : SendEventToEngine(event);
238 :
239 0 : CleanupOldEvents();
240 : }
241 :
242 : void CleanupOldEvents();
243 :
244 : void SendEventToEngine(const AudioTimelineEvent& aEvent);
245 :
246 : void DisconnectFromGraphAndDestroyStream();
247 :
248 : nsCycleCollectingAutoRefCnt mRefCnt;
249 : NS_DECL_OWNINGTHREAD
250 : RefPtr<AudioNode> mNode;
251 : // For every InputNode, there is a corresponding entry in mOutputParams of the
252 : // InputNode's mInputNode.
253 : nsTArray<AudioNode::InputNode> mInputNodes;
254 : const char* mName;
255 : // The input port used to connect the AudioParam's stream to its node's stream
256 : RefPtr<MediaInputPort> mNodeStreamPort;
257 : const uint32_t mIndex;
258 : const float mDefaultValue;
259 : const float mMinValue;
260 : const float mMaxValue;
261 : };
262 :
263 : } // namespace dom
264 : } // namespace mozilla
265 :
266 : #endif
267 :
|