OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2010, Google Inc. All rights reserved. | 2 * Copyright (C) 2010, Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 { | 82 { |
83 // FIXME: It would be nice if the minimum sample-rate could be less than 44.
1KHz, | 83 // FIXME: It would be nice if the minimum sample-rate could be less than 44.
1KHz, |
84 // but that will require some fixes in HRTFPanner::fftSizeForSampleRate(), a
nd some testing there. | 84 // but that will require some fixes in HRTFPanner::fftSizeForSampleRate(), a
nd some testing there. |
85 return sampleRate >= 44100 && sampleRate <= 96000; | 85 return sampleRate >= 44100 && sampleRate <= 96000; |
86 } | 86 } |
87 | 87 |
88 // Don't allow more than this number of simultaneous AudioContexts talking to ha
rdware. | 88 // Don't allow more than this number of simultaneous AudioContexts talking to ha
rdware. |
89 const unsigned MaxHardwareContexts = 6; | 89 const unsigned MaxHardwareContexts = 6; |
90 unsigned AudioContext::s_hardwareContextCount = 0; | 90 unsigned AudioContext::s_hardwareContextCount = 0; |
91 | 91 |
92 PassRefPtrWillBeRawPtr<AudioContext> AudioContext::create(Document& document, Ex
ceptionState& exceptionState) | 92 AudioContext* AudioContext::create(Document& document, ExceptionState& exception
State) |
93 { | 93 { |
94 ASSERT(isMainThread()); | 94 ASSERT(isMainThread()); |
95 if (s_hardwareContextCount >= MaxHardwareContexts) { | 95 if (s_hardwareContextCount >= MaxHardwareContexts) { |
96 exceptionState.throwDOMException( | 96 exceptionState.throwDOMException( |
97 SyntaxError, | 97 SyntaxError, |
98 "number of hardware contexts reached maximum (" + String::number(Max
HardwareContexts) + ")."); | 98 "number of hardware contexts reached maximum (" + String::number(Max
HardwareContexts) + ")."); |
99 return nullptr; | 99 return 0; |
100 } | 100 } |
101 | 101 |
102 RefPtrWillBeRawPtr<AudioContext> audioContext(adoptRefWillBeThreadSafeRefCou
ntedGarbageCollected(new AudioContext(&document))); | 102 AudioContext* audioContext = adoptRefCountedGarbageCollected(new AudioContex
t(&document)); |
103 audioContext->suspendIfNeeded(); | 103 audioContext->suspendIfNeeded(); |
104 return audioContext.release(); | 104 return audioContext; |
105 } | 105 } |
106 | 106 |
107 // Constructor for rendering to the audio hardware. | 107 // Constructor for rendering to the audio hardware. |
108 AudioContext::AudioContext(Document* document) | 108 AudioContext::AudioContext(Document* document) |
109 : ActiveDOMObject(document) | 109 : ActiveDOMObject(document) |
110 , m_isStopScheduled(false) | 110 , m_isStopScheduled(false) |
111 , m_isCleared(false) | 111 , m_isCleared(false) |
112 , m_isInitialized(false) | 112 , m_isInitialized(false) |
113 , m_destinationNode(nullptr) | 113 , m_destinationNode(nullptr) |
114 #if !ENABLE(OILPAN) | |
115 , m_isDeletionScheduled(false) | |
116 #endif | |
117 , m_automaticPullNodesNeedUpdating(false) | 114 , m_automaticPullNodesNeedUpdating(false) |
118 , m_connectionCount(0) | 115 , m_connectionCount(0) |
119 , m_audioThread(0) | 116 , m_audioThread(0) |
120 , m_graphOwnerThread(UndefinedThreadIdentifier) | 117 , m_graphOwnerThread(UndefinedThreadIdentifier) |
121 , m_isOfflineContext(false) | 118 , m_isOfflineContext(false) |
122 { | 119 { |
123 ScriptWrappable::init(this); | 120 ScriptWrappable::init(this); |
124 | 121 |
125 m_destinationNode = DefaultAudioDestinationNode::create(this); | 122 m_destinationNode = DefaultAudioDestinationNode::create(this); |
126 | 123 |
127 initialize(); | 124 initialize(); |
128 #if DEBUG_AUDIONODE_REFERENCES | 125 #if DEBUG_AUDIONODE_REFERENCES |
129 fprintf(stderr, "%p: AudioContext::AudioContext() #%u\n", this, AudioContext
::s_hardwareContextCount); | 126 fprintf(stderr, "%p: AudioContext::AudioContext() #%u\n", this, AudioContext
::s_hardwareContextCount); |
130 #endif | 127 #endif |
131 } | 128 } |
132 | 129 |
133 // Constructor for offline (non-realtime) rendering. | 130 // Constructor for offline (non-realtime) rendering. |
134 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t
numberOfFrames, float sampleRate) | 131 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t
numberOfFrames, float sampleRate) |
135 : ActiveDOMObject(document) | 132 : ActiveDOMObject(document) |
136 , m_isStopScheduled(false) | 133 , m_isStopScheduled(false) |
137 , m_isCleared(false) | 134 , m_isCleared(false) |
138 , m_isInitialized(false) | 135 , m_isInitialized(false) |
139 , m_destinationNode(nullptr) | 136 , m_destinationNode(nullptr) |
140 #if !ENABLE(OILPAN) | |
141 , m_isDeletionScheduled(false) | |
142 #endif | |
143 , m_automaticPullNodesNeedUpdating(false) | 137 , m_automaticPullNodesNeedUpdating(false) |
144 , m_connectionCount(0) | 138 , m_connectionCount(0) |
145 , m_audioThread(0) | 139 , m_audioThread(0) |
146 , m_graphOwnerThread(UndefinedThreadIdentifier) | 140 , m_graphOwnerThread(UndefinedThreadIdentifier) |
147 , m_isOfflineContext(true) | 141 , m_isOfflineContext(true) |
148 { | 142 { |
149 ScriptWrappable::init(this); | 143 ScriptWrappable::init(this); |
150 | 144 |
151 // Create a new destination for offline rendering. | 145 // Create a new destination for offline rendering. |
152 m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampl
eRate); | 146 m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampl
eRate); |
153 if (m_renderTarget.get()) | 147 if (m_renderTarget.get()) |
154 m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTa
rget.get()); | 148 m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTa
rget.get()); |
155 | 149 |
156 initialize(); | 150 initialize(); |
157 } | 151 } |
158 | 152 |
159 AudioContext::~AudioContext() | 153 AudioContext::~AudioContext() |
160 { | 154 { |
161 #if DEBUG_AUDIONODE_REFERENCES | 155 #if DEBUG_AUDIONODE_REFERENCES |
162 fprintf(stderr, "%p: AudioContext::~AudioContext()\n", this); | 156 fprintf(stderr, "%p: AudioContext::~AudioContext()\n", this); |
163 #endif | 157 #endif |
164 // AudioNodes keep a reference to their context, so there should be no way t
o be in the destructor if there are still AudioNodes around. | 158 // AudioNodes keep a reference to their context, so there should be no way t
o be in the destructor if there are still AudioNodes around. |
165 ASSERT(!m_isInitialized); | 159 ASSERT(!m_isInitialized); |
166 #if !ENABLE(OILPAN) | |
167 ASSERT(!m_nodesToDelete.size()); | |
168 #endif | |
169 ASSERT(!m_referencedNodes.size()); | 160 ASSERT(!m_referencedNodes.size()); |
170 ASSERT(!m_finishedNodes.size()); | 161 ASSERT(!m_finishedNodes.size()); |
171 ASSERT(!m_automaticPullNodes.size()); | 162 ASSERT(!m_automaticPullNodes.size()); |
172 if (m_automaticPullNodesNeedUpdating) | 163 if (m_automaticPullNodesNeedUpdating) |
173 m_renderingAutomaticPullNodes.resize(m_automaticPullNodes.size()); | 164 m_renderingAutomaticPullNodes.resize(m_automaticPullNodes.size()); |
174 ASSERT(!m_renderingAutomaticPullNodes.size()); | 165 ASSERT(!m_renderingAutomaticPullNodes.size()); |
175 } | 166 } |
176 | 167 |
177 void AudioContext::initialize() | 168 void AudioContext::initialize() |
178 { | 169 { |
(...skipping 14 matching lines...) Expand all Loading... |
193 m_destinationNode->startRendering(); | 184 m_destinationNode->startRendering(); |
194 ++s_hardwareContextCount; | 185 ++s_hardwareContextCount; |
195 } | 186 } |
196 | 187 |
197 m_isInitialized = true; | 188 m_isInitialized = true; |
198 } | 189 } |
199 } | 190 } |
200 | 191 |
201 void AudioContext::clear() | 192 void AudioContext::clear() |
202 { | 193 { |
203 #if ENABLE(OILPAN) | |
204 // We need to run disposers before destructing m_contextGraphMutex. | 194 // We need to run disposers before destructing m_contextGraphMutex. |
205 m_liveAudioSummingJunctions.clear(); | 195 m_liveAudioSummingJunctions.clear(); |
206 m_liveNodes.clear(); | 196 m_liveNodes.clear(); |
207 #else | 197 m_destinationNode.clear(); |
208 | |
209 // We have to release our reference to the destination node before the conte
xt will ever be deleted since the destination node holds a reference to the cont
ext. | |
210 if (m_destinationNode) | |
211 m_destinationNode.clear(); | |
212 | |
213 // Audio thread is dead. Nobody will schedule node deletion action. Let's do
it ourselves. | |
214 do { | |
215 m_nodesToDelete.appendVector(m_nodesMarkedForDeletion); | |
216 m_nodesMarkedForDeletion.clear(); | |
217 deleteMarkedNodes(); | |
218 } while (m_nodesToDelete.size()); | |
219 #endif | |
220 | |
221 m_isCleared = true; | 198 m_isCleared = true; |
222 } | 199 } |
223 | 200 |
224 void AudioContext::uninitialize() | 201 void AudioContext::uninitialize() |
225 { | 202 { |
226 ASSERT(isMainThread()); | 203 ASSERT(isMainThread()); |
227 | 204 |
228 if (!isInitialized()) | 205 if (!isInitialized()) |
229 return; | 206 return; |
230 | 207 |
(...skipping 16 matching lines...) Expand all Loading... |
247 { | 224 { |
248 // Usually ExecutionContext calls stop twice. | 225 // Usually ExecutionContext calls stop twice. |
249 if (m_isStopScheduled) | 226 if (m_isStopScheduled) |
250 return; | 227 return; |
251 m_isStopScheduled = true; | 228 m_isStopScheduled = true; |
252 | 229 |
253 // Don't call uninitialize() immediately here because the ExecutionContext i
s in the middle | 230 // Don't call uninitialize() immediately here because the ExecutionContext i
s in the middle |
254 // of dealing with all of its ActiveDOMObjects at this point. uninitialize()
can de-reference other | 231 // of dealing with all of its ActiveDOMObjects at this point. uninitialize()
can de-reference other |
255 // ActiveDOMObjects so let's schedule uninitialize() to be called later. | 232 // ActiveDOMObjects so let's schedule uninitialize() to be called later. |
256 // FIXME: see if there's a more direct way to handle this issue. | 233 // FIXME: see if there's a more direct way to handle this issue. |
257 callOnMainThread(bind(&AudioContext::uninitialize, PassRefPtrWillBeRawPtr<Au
dioContext>(this))); | 234 callOnMainThread(bind(&AudioContext::uninitialize, this)); |
258 } | 235 } |
259 | 236 |
260 bool AudioContext::hasPendingActivity() const | 237 bool AudioContext::hasPendingActivity() const |
261 { | 238 { |
262 // According to spec AudioContext must die only after page navigates. | 239 // According to spec AudioContext must die only after page navigates. |
263 return !m_isCleared; | 240 return !m_isCleared; |
264 } | 241 } |
265 | 242 |
266 PassRefPtrWillBeRawPtr<AudioBuffer> AudioContext::createBuffer(unsigned numberOf
Channels, size_t numberOfFrames, float sampleRate, ExceptionState& exceptionStat
e) | 243 AudioBuffer* AudioContext::createBuffer(unsigned numberOfChannels, size_t number
OfFrames, float sampleRate, ExceptionState& exceptionState) |
267 { | 244 { |
268 RefPtrWillBeRawPtr<AudioBuffer> audioBuffer = AudioBuffer::create(numberOfCh
annels, numberOfFrames, sampleRate, exceptionState); | 245 return AudioBuffer::create(numberOfChannels, numberOfFrames, sampleRate, exc
eptionState); |
269 | |
270 return audioBuffer; | |
271 } | 246 } |
272 | 247 |
273 void AudioContext::decodeAudioData(ArrayBuffer* audioData, PassOwnPtr<AudioBuffe
rCallback> successCallback, PassOwnPtr<AudioBufferCallback> errorCallback, Excep
tionState& exceptionState) | 248 void AudioContext::decodeAudioData(ArrayBuffer* audioData, PassOwnPtr<AudioBuffe
rCallback> successCallback, PassOwnPtr<AudioBufferCallback> errorCallback, Excep
tionState& exceptionState) |
274 { | 249 { |
275 if (!audioData) { | 250 if (!audioData) { |
276 exceptionState.throwDOMException( | 251 exceptionState.throwDOMException( |
277 SyntaxError, | 252 SyntaxError, |
278 "invalid ArrayBuffer for audioData."); | 253 "invalid ArrayBuffer for audioData."); |
279 return; | 254 return; |
280 } | 255 } |
281 m_audioDecoder.decodeAsync(audioData, sampleRate(), successCallback, errorCa
llback); | 256 m_audioDecoder.decodeAsync(audioData, sampleRate(), successCallback, errorCa
llback); |
282 } | 257 } |
283 | 258 |
284 PassRefPtrWillBeRawPtr<AudioBufferSourceNode> AudioContext::createBufferSource() | 259 AudioBufferSourceNode* AudioContext::createBufferSource() |
285 { | 260 { |
286 ASSERT(isMainThread()); | 261 ASSERT(isMainThread()); |
287 RefPtrWillBeRawPtr<AudioBufferSourceNode> node = AudioBufferSourceNode::crea
te(this, m_destinationNode->sampleRate()); | 262 AudioBufferSourceNode* node = AudioBufferSourceNode::create(this, m_destinat
ionNode->sampleRate()); |
288 | 263 |
289 // Because this is an AudioScheduledSourceNode, the context keeps a referenc
e until it has finished playing. | 264 // Because this is an AudioScheduledSourceNode, the context keeps a referenc
e until it has finished playing. |
290 // When this happens, AudioScheduledSourceNode::finish() calls AudioContext:
:notifyNodeFinishedProcessing(). | 265 // When this happens, AudioScheduledSourceNode::finish() calls AudioContext:
:notifyNodeFinishedProcessing(). |
291 refNode(node.get()); | 266 refNode(node); |
292 | 267 |
293 return node; | 268 return node; |
294 } | 269 } |
295 | 270 |
296 PassRefPtrWillBeRawPtr<MediaElementAudioSourceNode> AudioContext::createMediaEle
mentSource(HTMLMediaElement* mediaElement, ExceptionState& exceptionState) | 271 MediaElementAudioSourceNode* AudioContext::createMediaElementSource(HTMLMediaEle
ment* mediaElement, ExceptionState& exceptionState) |
297 { | 272 { |
298 ASSERT(isMainThread()); | 273 ASSERT(isMainThread()); |
299 if (!mediaElement) { | 274 if (!mediaElement) { |
300 exceptionState.throwDOMException( | 275 exceptionState.throwDOMException( |
301 InvalidStateError, | 276 InvalidStateError, |
302 "invalid HTMLMedialElement."); | 277 "invalid HTMLMedialElement."); |
303 return nullptr; | 278 return 0; |
304 } | 279 } |
305 | 280 |
306 // First check if this media element already has a source node. | 281 // First check if this media element already has a source node. |
307 if (mediaElement->audioSourceNode()) { | 282 if (mediaElement->audioSourceNode()) { |
308 exceptionState.throwDOMException( | 283 exceptionState.throwDOMException( |
309 InvalidStateError, | 284 InvalidStateError, |
310 "invalid HTMLMediaElement."); | 285 "invalid HTMLMediaElement."); |
311 return nullptr; | 286 return 0; |
312 } | 287 } |
313 | 288 |
314 RefPtrWillBeRawPtr<MediaElementAudioSourceNode> node = MediaElementAudioSour
ceNode::create(this, mediaElement); | 289 MediaElementAudioSourceNode* node = MediaElementAudioSourceNode::create(this
, mediaElement); |
315 | 290 |
316 mediaElement->setAudioSourceNode(node.get()); | 291 mediaElement->setAudioSourceNode(node); |
317 | 292 |
318 refNode(node.get()); // context keeps reference until node is disconnected | 293 refNode(node); // context keeps reference until node is disconnected |
319 return node; | 294 return node; |
320 } | 295 } |
321 | 296 |
322 PassRefPtrWillBeRawPtr<MediaStreamAudioSourceNode> AudioContext::createMediaStre
amSource(MediaStream* mediaStream, ExceptionState& exceptionState) | 297 MediaStreamAudioSourceNode* AudioContext::createMediaStreamSource(MediaStream* m
ediaStream, ExceptionState& exceptionState) |
323 { | 298 { |
324 ASSERT(isMainThread()); | 299 ASSERT(isMainThread()); |
325 if (!mediaStream) { | 300 if (!mediaStream) { |
326 exceptionState.throwDOMException( | 301 exceptionState.throwDOMException( |
327 InvalidStateError, | 302 InvalidStateError, |
328 "invalid MediaStream source"); | 303 "invalid MediaStream source"); |
329 return nullptr; | 304 return 0; |
330 } | 305 } |
331 | 306 |
332 MediaStreamTrackVector audioTracks = mediaStream->getAudioTracks(); | 307 MediaStreamTrackVector audioTracks = mediaStream->getAudioTracks(); |
333 if (audioTracks.isEmpty()) { | 308 if (audioTracks.isEmpty()) { |
334 exceptionState.throwDOMException( | 309 exceptionState.throwDOMException( |
335 InvalidStateError, | 310 InvalidStateError, |
336 "MediaStream has no audio track"); | 311 "MediaStream has no audio track"); |
337 return nullptr; | 312 return 0; |
338 } | 313 } |
339 | 314 |
340 // Use the first audio track in the media stream. | 315 // Use the first audio track in the media stream. |
341 MediaStreamTrack* audioTrack = audioTracks[0]; | 316 MediaStreamTrack* audioTrack = audioTracks[0]; |
342 OwnPtr<AudioSourceProvider> provider = audioTrack->createWebAudioSource(); | 317 OwnPtr<AudioSourceProvider> provider = audioTrack->createWebAudioSource(); |
343 RefPtrWillBeRawPtr<MediaStreamAudioSourceNode> node = MediaStreamAudioSource
Node::create(this, mediaStream, audioTrack, provider.release()); | 318 MediaStreamAudioSourceNode* node = MediaStreamAudioSourceNode::create(this,
mediaStream, audioTrack, provider.release()); |
344 | 319 |
345 // FIXME: Only stereo streams are supported right now. We should be able to
accept multi-channel streams. | 320 // FIXME: Only stereo streams are supported right now. We should be able to
accept multi-channel streams. |
346 node->setFormat(2, sampleRate()); | 321 node->setFormat(2, sampleRate()); |
347 | 322 |
348 refNode(node.get()); // context keeps reference until node is disconnected | 323 refNode(node); // context keeps reference until node is disconnected |
349 return node; | 324 return node; |
350 } | 325 } |
351 | 326 |
352 PassRefPtrWillBeRawPtr<MediaStreamAudioDestinationNode> AudioContext::createMedi
aStreamDestination() | 327 MediaStreamAudioDestinationNode* AudioContext::createMediaStreamDestination() |
353 { | 328 { |
354 // Set number of output channels to stereo by default. | 329 // Set number of output channels to stereo by default. |
355 return MediaStreamAudioDestinationNode::create(this, 2); | 330 return MediaStreamAudioDestinationNode::create(this, 2); |
356 } | 331 } |
357 | 332 |
358 PassRefPtrWillBeRawPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(
ExceptionState& exceptionState) | 333 ScriptProcessorNode* AudioContext::createScriptProcessor(ExceptionState& excepti
onState) |
359 { | 334 { |
360 // Set number of input/output channels to stereo by default. | 335 // Set number of input/output channels to stereo by default. |
361 return createScriptProcessor(0, 2, 2, exceptionState); | 336 return createScriptProcessor(0, 2, 2, exceptionState); |
362 } | 337 } |
363 | 338 |
364 PassRefPtrWillBeRawPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(
size_t bufferSize, ExceptionState& exceptionState) | 339 ScriptProcessorNode* AudioContext::createScriptProcessor(size_t bufferSize, Exce
ptionState& exceptionState) |
365 { | 340 { |
366 // Set number of input/output channels to stereo by default. | 341 // Set number of input/output channels to stereo by default. |
367 return createScriptProcessor(bufferSize, 2, 2, exceptionState); | 342 return createScriptProcessor(bufferSize, 2, 2, exceptionState); |
368 } | 343 } |
369 | 344 |
370 PassRefPtrWillBeRawPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(
size_t bufferSize, size_t numberOfInputChannels, ExceptionState& exceptionState) | 345 ScriptProcessorNode* AudioContext::createScriptProcessor(size_t bufferSize, size
_t numberOfInputChannels, ExceptionState& exceptionState) |
371 { | 346 { |
372 // Set number of output channels to stereo by default. | 347 // Set number of output channels to stereo by default. |
373 return createScriptProcessor(bufferSize, numberOfInputChannels, 2, exception
State); | 348 return createScriptProcessor(bufferSize, numberOfInputChannels, 2, exception
State); |
374 } | 349 } |
375 | 350 |
376 PassRefPtrWillBeRawPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(
size_t bufferSize, size_t numberOfInputChannels, size_t numberOfOutputChannels,
ExceptionState& exceptionState) | 351 ScriptProcessorNode* AudioContext::createScriptProcessor(size_t bufferSize, size
_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionState& excepti
onState) |
377 { | 352 { |
378 ASSERT(isMainThread()); | 353 ASSERT(isMainThread()); |
379 RefPtrWillBeRawPtr<ScriptProcessorNode> node = ScriptProcessorNode::create(t
his, m_destinationNode->sampleRate(), bufferSize, numberOfInputChannels, numberO
fOutputChannels); | 354 ScriptProcessorNode* node = ScriptProcessorNode::create(this, m_destinationN
ode->sampleRate(), bufferSize, numberOfInputChannels, numberOfOutputChannels); |
380 | 355 |
381 if (!node.get()) { | 356 if (!node) { |
382 if (!numberOfInputChannels && !numberOfOutputChannels) { | 357 if (!numberOfInputChannels && !numberOfOutputChannels) { |
383 exceptionState.throwDOMException( | 358 exceptionState.throwDOMException( |
384 IndexSizeError, | 359 IndexSizeError, |
385 "number of input channels and output channels cannot both be zer
o."); | 360 "number of input channels and output channels cannot both be zer
o."); |
386 } else if (numberOfInputChannels > AudioContext::maxNumberOfChannels())
{ | 361 } else if (numberOfInputChannels > AudioContext::maxNumberOfChannels())
{ |
387 exceptionState.throwDOMException( | 362 exceptionState.throwDOMException( |
388 IndexSizeError, | 363 IndexSizeError, |
389 "number of input channels (" + String::number(numberOfInputChann
els) | 364 "number of input channels (" + String::number(numberOfInputChann
els) |
390 + ") exceeds maximum (" | 365 + ") exceeds maximum (" |
391 + String::number(AudioContext::maxNumberOfChannels()) + ")."); | 366 + String::number(AudioContext::maxNumberOfChannels()) + ")."); |
392 } else if (numberOfOutputChannels > AudioContext::maxNumberOfChannels())
{ | 367 } else if (numberOfOutputChannels > AudioContext::maxNumberOfChannels())
{ |
393 exceptionState.throwDOMException( | 368 exceptionState.throwDOMException( |
394 IndexSizeError, | 369 IndexSizeError, |
395 "number of output channels (" + String::number(numberOfInputChan
nels) | 370 "number of output channels (" + String::number(numberOfInputChan
nels) |
396 + ") exceeds maximum (" | 371 + ") exceeds maximum (" |
397 + String::number(AudioContext::maxNumberOfChannels()) + ")."); | 372 + String::number(AudioContext::maxNumberOfChannels()) + ")."); |
398 } else { | 373 } else { |
399 exceptionState.throwDOMException( | 374 exceptionState.throwDOMException( |
400 IndexSizeError, | 375 IndexSizeError, |
401 "buffer size (" + String::number(bufferSize) | 376 "buffer size (" + String::number(bufferSize) |
402 + ") must be a power of two between 256 and 16384."); | 377 + ") must be a power of two between 256 and 16384."); |
403 } | 378 } |
404 return nullptr; | 379 return 0; |
405 } | 380 } |
406 | 381 |
407 refNode(node.get()); // context keeps reference until we stop making javascr
ipt rendering callbacks | 382 refNode(node); // context keeps reference until we stop making javascript re
ndering callbacks |
408 return node; | 383 return node; |
409 } | 384 } |
410 | 385 |
411 PassRefPtrWillBeRawPtr<BiquadFilterNode> AudioContext::createBiquadFilter() | 386 BiquadFilterNode* AudioContext::createBiquadFilter() |
412 { | 387 { |
413 ASSERT(isMainThread()); | 388 ASSERT(isMainThread()); |
414 return BiquadFilterNode::create(this, m_destinationNode->sampleRate()); | 389 return BiquadFilterNode::create(this, m_destinationNode->sampleRate()); |
415 } | 390 } |
416 | 391 |
417 PassRefPtrWillBeRawPtr<WaveShaperNode> AudioContext::createWaveShaper() | 392 WaveShaperNode* AudioContext::createWaveShaper() |
418 { | 393 { |
419 ASSERT(isMainThread()); | 394 ASSERT(isMainThread()); |
420 return WaveShaperNode::create(this); | 395 return WaveShaperNode::create(this); |
421 } | 396 } |
422 | 397 |
423 PassRefPtrWillBeRawPtr<PannerNode> AudioContext::createPanner() | 398 PannerNode* AudioContext::createPanner() |
424 { | 399 { |
425 ASSERT(isMainThread()); | 400 ASSERT(isMainThread()); |
426 return PannerNode::create(this, m_destinationNode->sampleRate()); | 401 return PannerNode::create(this, m_destinationNode->sampleRate()); |
427 } | 402 } |
428 | 403 |
429 PassRefPtrWillBeRawPtr<ConvolverNode> AudioContext::createConvolver() | 404 ConvolverNode* AudioContext::createConvolver() |
430 { | 405 { |
431 ASSERT(isMainThread()); | 406 ASSERT(isMainThread()); |
432 return ConvolverNode::create(this, m_destinationNode->sampleRate()); | 407 return ConvolverNode::create(this, m_destinationNode->sampleRate()); |
433 } | 408 } |
434 | 409 |
435 PassRefPtrWillBeRawPtr<DynamicsCompressorNode> AudioContext::createDynamicsCompr
essor() | 410 DynamicsCompressorNode* AudioContext::createDynamicsCompressor() |
436 { | 411 { |
437 ASSERT(isMainThread()); | 412 ASSERT(isMainThread()); |
438 return DynamicsCompressorNode::create(this, m_destinationNode->sampleRate())
; | 413 return DynamicsCompressorNode::create(this, m_destinationNode->sampleRate())
; |
439 } | 414 } |
440 | 415 |
441 PassRefPtrWillBeRawPtr<AnalyserNode> AudioContext::createAnalyser() | 416 AnalyserNode* AudioContext::createAnalyser() |
442 { | 417 { |
443 ASSERT(isMainThread()); | 418 ASSERT(isMainThread()); |
444 return AnalyserNode::create(this, m_destinationNode->sampleRate()); | 419 return AnalyserNode::create(this, m_destinationNode->sampleRate()); |
445 } | 420 } |
446 | 421 |
447 PassRefPtrWillBeRawPtr<GainNode> AudioContext::createGain() | 422 GainNode* AudioContext::createGain() |
448 { | 423 { |
449 ASSERT(isMainThread()); | 424 ASSERT(isMainThread()); |
450 return GainNode::create(this, m_destinationNode->sampleRate()); | 425 return GainNode::create(this, m_destinationNode->sampleRate()); |
451 } | 426 } |
452 | 427 |
453 PassRefPtrWillBeRawPtr<DelayNode> AudioContext::createDelay(ExceptionState& exce
ptionState) | 428 DelayNode* AudioContext::createDelay(ExceptionState& exceptionState) |
454 { | 429 { |
455 const double defaultMaxDelayTime = 1; | 430 const double defaultMaxDelayTime = 1; |
456 return createDelay(defaultMaxDelayTime, exceptionState); | 431 return createDelay(defaultMaxDelayTime, exceptionState); |
457 } | 432 } |
458 | 433 |
459 PassRefPtrWillBeRawPtr<DelayNode> AudioContext::createDelay(double maxDelayTime,
ExceptionState& exceptionState) | 434 DelayNode* AudioContext::createDelay(double maxDelayTime, ExceptionState& except
ionState) |
460 { | 435 { |
461 ASSERT(isMainThread()); | 436 ASSERT(isMainThread()); |
462 RefPtrWillBeRawPtr<DelayNode> node = DelayNode::create(this, m_destinationNo
de->sampleRate(), maxDelayTime, exceptionState); | 437 DelayNode* node = DelayNode::create(this, m_destinationNode->sampleRate(), m
axDelayTime, exceptionState); |
463 if (exceptionState.hadException()) | 438 if (exceptionState.hadException()) |
464 return nullptr; | 439 return 0; |
465 return node; | 440 return node; |
466 } | 441 } |
467 | 442 |
468 PassRefPtrWillBeRawPtr<ChannelSplitterNode> AudioContext::createChannelSplitter(
ExceptionState& exceptionState) | 443 ChannelSplitterNode* AudioContext::createChannelSplitter(ExceptionState& excepti
onState) |
469 { | 444 { |
470 const unsigned ChannelSplitterDefaultNumberOfOutputs = 6; | 445 const unsigned ChannelSplitterDefaultNumberOfOutputs = 6; |
471 return createChannelSplitter(ChannelSplitterDefaultNumberOfOutputs, exceptio
nState); | 446 return createChannelSplitter(ChannelSplitterDefaultNumberOfOutputs, exceptio
nState); |
472 } | 447 } |
473 | 448 |
474 PassRefPtrWillBeRawPtr<ChannelSplitterNode> AudioContext::createChannelSplitter(
size_t numberOfOutputs, ExceptionState& exceptionState) | 449 ChannelSplitterNode* AudioContext::createChannelSplitter(size_t numberOfOutputs,
ExceptionState& exceptionState) |
475 { | 450 { |
476 ASSERT(isMainThread()); | 451 ASSERT(isMainThread()); |
477 | 452 |
478 RefPtrWillBeRawPtr<ChannelSplitterNode> node = ChannelSplitterNode::create(t
his, m_destinationNode->sampleRate(), numberOfOutputs); | 453 ChannelSplitterNode* node = ChannelSplitterNode::create(this, m_destinationN
ode->sampleRate(), numberOfOutputs); |
479 | 454 |
480 if (!node.get()) { | 455 if (!node) { |
481 exceptionState.throwDOMException( | 456 exceptionState.throwDOMException( |
482 IndexSizeError, | 457 IndexSizeError, |
483 "number of outputs (" + String::number(numberOfOutputs) | 458 "number of outputs (" + String::number(numberOfOutputs) |
484 + ") must be between 1 and " | 459 + ") must be between 1 and " |
485 + String::number(AudioContext::maxNumberOfChannels()) + "."); | 460 + String::number(AudioContext::maxNumberOfChannels()) + "."); |
486 return nullptr; | 461 return 0; |
487 } | 462 } |
488 | 463 |
489 return node; | 464 return node; |
490 } | 465 } |
491 | 466 |
492 PassRefPtrWillBeRawPtr<ChannelMergerNode> AudioContext::createChannelMerger(Exce
ptionState& exceptionState) | 467 ChannelMergerNode* AudioContext::createChannelMerger(ExceptionState& exceptionSt
ate) |
493 { | 468 { |
494 const unsigned ChannelMergerDefaultNumberOfInputs = 6; | 469 const unsigned ChannelMergerDefaultNumberOfInputs = 6; |
495 return createChannelMerger(ChannelMergerDefaultNumberOfInputs, exceptionStat
e); | 470 return createChannelMerger(ChannelMergerDefaultNumberOfInputs, exceptionStat
e); |
496 } | 471 } |
497 | 472 |
498 PassRefPtrWillBeRawPtr<ChannelMergerNode> AudioContext::createChannelMerger(size
_t numberOfInputs, ExceptionState& exceptionState) | 473 ChannelMergerNode* AudioContext::createChannelMerger(size_t numberOfInputs, Exce
ptionState& exceptionState) |
499 { | 474 { |
500 ASSERT(isMainThread()); | 475 ASSERT(isMainThread()); |
501 | 476 |
502 RefPtrWillBeRawPtr<ChannelMergerNode> node = ChannelMergerNode::create(this,
m_destinationNode->sampleRate(), numberOfInputs); | 477 ChannelMergerNode* node = ChannelMergerNode::create(this, m_destinationNode-
>sampleRate(), numberOfInputs); |
503 | 478 |
504 if (!node.get()) { | 479 if (!node) { |
505 exceptionState.throwDOMException( | 480 exceptionState.throwDOMException( |
506 IndexSizeError, | 481 IndexSizeError, |
507 "number of inputs (" + String::number(numberOfInputs) | 482 "number of inputs (" + String::number(numberOfInputs) |
508 + ") must be between 1 and " | 483 + ") must be between 1 and " |
509 + String::number(AudioContext::maxNumberOfChannels()) + "."); | 484 + String::number(AudioContext::maxNumberOfChannels()) + "."); |
510 return nullptr; | 485 return 0; |
511 } | 486 } |
512 | 487 |
513 return node; | 488 return node; |
514 } | 489 } |
515 | 490 |
516 PassRefPtrWillBeRawPtr<OscillatorNode> AudioContext::createOscillator() | 491 OscillatorNode* AudioContext::createOscillator() |
517 { | 492 { |
518 ASSERT(isMainThread()); | 493 ASSERT(isMainThread()); |
519 | 494 |
520 RefPtrWillBeRawPtr<OscillatorNode> node = OscillatorNode::create(this, m_des
tinationNode->sampleRate()); | 495 OscillatorNode* node = OscillatorNode::create(this, m_destinationNode->sampl
eRate()); |
521 | 496 |
522 // Because this is an AudioScheduledSourceNode, the context keeps a referenc
e until it has finished playing. | 497 // Because this is an AudioScheduledSourceNode, the context keeps a referenc
e until it has finished playing. |
523 // When this happens, AudioScheduledSourceNode::finish() calls AudioContext:
:notifyNodeFinishedProcessing(). | 498 // When this happens, AudioScheduledSourceNode::finish() calls AudioContext:
:notifyNodeFinishedProcessing(). |
524 refNode(node.get()); | 499 refNode(node); |
525 | 500 |
526 return node; | 501 return node; |
527 } | 502 } |
528 | 503 |
529 PassRefPtrWillBeRawPtr<PeriodicWave> AudioContext::createPeriodicWave(Float32Arr
ay* real, Float32Array* imag, ExceptionState& exceptionState) | 504 PeriodicWave* AudioContext::createPeriodicWave(Float32Array* real, Float32Array*
imag, ExceptionState& exceptionState) |
530 { | 505 { |
531 ASSERT(isMainThread()); | 506 ASSERT(isMainThread()); |
532 | 507 |
533 if (!real) { | 508 if (!real) { |
534 exceptionState.throwDOMException( | 509 exceptionState.throwDOMException( |
535 SyntaxError, | 510 SyntaxError, |
536 "invalid real array"); | 511 "invalid real array"); |
537 return nullptr; | 512 return 0; |
538 } | 513 } |
539 | 514 |
540 if (!imag) { | 515 if (!imag) { |
541 exceptionState.throwDOMException( | 516 exceptionState.throwDOMException( |
542 SyntaxError, | 517 SyntaxError, |
543 "invalid imaginary array"); | 518 "invalid imaginary array"); |
544 return nullptr; | 519 return 0; |
545 } | 520 } |
546 | 521 |
547 if (real->length() != imag->length()) { | 522 if (real->length() != imag->length()) { |
548 exceptionState.throwDOMException( | 523 exceptionState.throwDOMException( |
549 IndexSizeError, | 524 IndexSizeError, |
550 "length of real array (" + String::number(real->length()) | 525 "length of real array (" + String::number(real->length()) |
551 + ") and length of imaginary array (" + String::number(imag->length
()) | 526 + ") and length of imaginary array (" + String::number(imag->length
()) |
552 + ") must match."); | 527 + ") must match."); |
553 return nullptr; | 528 return 0; |
554 } | 529 } |
555 | 530 |
556 if (real->length() > 4096) { | 531 if (real->length() > 4096) { |
557 exceptionState.throwDOMException( | 532 exceptionState.throwDOMException( |
558 IndexSizeError, | 533 IndexSizeError, |
559 "length of real array (" + String::number(real->length()) | 534 "length of real array (" + String::number(real->length()) |
560 + ") exceeds allowed maximum of 4096"); | 535 + ") exceeds allowed maximum of 4096"); |
561 return nullptr; | 536 return 0; |
562 } | 537 } |
563 | 538 |
564 if (imag->length() > 4096) { | 539 if (imag->length() > 4096) { |
565 exceptionState.throwDOMException( | 540 exceptionState.throwDOMException( |
566 IndexSizeError, | 541 IndexSizeError, |
567 "length of imaginary array (" + String::number(imag->length()) | 542 "length of imaginary array (" + String::number(imag->length()) |
568 + ") exceeds allowed maximum of 4096"); | 543 + ") exceeds allowed maximum of 4096"); |
569 return nullptr; | 544 return 0; |
570 } | 545 } |
571 | 546 |
572 return PeriodicWave::create(sampleRate(), real, imag); | 547 return PeriodicWave::create(sampleRate(), real, imag); |
573 } | 548 } |
574 | 549 |
575 void AudioContext::notifyNodeFinishedProcessing(AudioNode* node) | 550 void AudioContext::notifyNodeFinishedProcessing(AudioNode* node) |
576 { | 551 { |
577 ASSERT(isAudioThread()); | 552 ASSERT(isAudioThread()); |
578 m_finishedNodes.append(node); | 553 m_finishedNodes.append(node); |
579 } | 554 } |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 { | 662 { |
688 return currentThread() == m_graphOwnerThread; | 663 return currentThread() == m_graphOwnerThread; |
689 } | 664 } |
690 | 665 |
691 void AudioContext::addDeferredBreakConnection(AudioNode& node) | 666 void AudioContext::addDeferredBreakConnection(AudioNode& node) |
692 { | 667 { |
693 ASSERT(isAudioThread()); | 668 ASSERT(isAudioThread()); |
694 m_deferredBreakConnectionList.append(&node); | 669 m_deferredBreakConnectionList.append(&node); |
695 } | 670 } |
696 | 671 |
697 #if !ENABLE(OILPAN) | |
698 void AudioContext::addDeferredFinishDeref(AudioNode* node) | |
699 { | |
700 ASSERT(isAudioThread()); | |
701 m_deferredFinishDerefList.append(node); | |
702 } | |
703 #endif | |
704 | |
705 void AudioContext::handlePreRenderTasks() | 672 void AudioContext::handlePreRenderTasks() |
706 { | 673 { |
707 ASSERT(isAudioThread()); | 674 ASSERT(isAudioThread()); |
708 | 675 |
709 // At the beginning of every render quantum, try to update the internal rend
ering graph state (from main thread changes). | 676 // At the beginning of every render quantum, try to update the internal rend
ering graph state (from main thread changes). |
710 // It's OK if the tryLock() fails, we'll just take slightly longer to pick u
p the changes. | 677 // It's OK if the tryLock() fails, we'll just take slightly longer to pick u
p the changes. |
711 bool mustReleaseLock; | 678 bool mustReleaseLock; |
712 if (tryLock(mustReleaseLock)) { | 679 if (tryLock(mustReleaseLock)) { |
713 // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutpu
ts. | 680 // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutpu
ts. |
714 handleDirtyAudioSummingJunctions(); | 681 handleDirtyAudioSummingJunctions(); |
(...skipping 14 matching lines...) Expand all Loading... |
729 // The worst that can happen is that there will be some nodes which will tak
e slightly longer than usual to be deleted or removed | 696 // The worst that can happen is that there will be some nodes which will tak
e slightly longer than usual to be deleted or removed |
730 // from the render graph (in which case they'll render silence). | 697 // from the render graph (in which case they'll render silence). |
731 bool mustReleaseLock; | 698 bool mustReleaseLock; |
732 if (tryLock(mustReleaseLock)) { | 699 if (tryLock(mustReleaseLock)) { |
733 // Take care of AudioNode tasks where the tryLock() failed previously. | 700 // Take care of AudioNode tasks where the tryLock() failed previously. |
734 handleDeferredAudioNodeTasks(); | 701 handleDeferredAudioNodeTasks(); |
735 | 702 |
736 // Dynamically clean up nodes which are no longer needed. | 703 // Dynamically clean up nodes which are no longer needed. |
737 derefFinishedSourceNodes(); | 704 derefFinishedSourceNodes(); |
738 | 705 |
739 #if !ENABLE(OILPAN) | |
740 // Don't delete in the real-time thread. Let the main thread do it. | |
741 // Ref-counted objects held by certain AudioNodes may not be thread-safe
. | |
742 scheduleNodeDeletion(); | |
743 #endif | |
744 | |
745 // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutpu
ts. | 706 // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutpu
ts. |
746 handleDirtyAudioSummingJunctions(); | 707 handleDirtyAudioSummingJunctions(); |
747 handleDirtyAudioNodeOutputs(); | 708 handleDirtyAudioNodeOutputs(); |
748 | 709 |
749 updateAutomaticPullNodes(); | 710 updateAutomaticPullNodes(); |
750 | 711 |
751 if (mustReleaseLock) | 712 if (mustReleaseLock) |
752 unlock(); | 713 unlock(); |
753 } | 714 } |
754 } | 715 } |
755 | 716 |
756 void AudioContext::handleDeferredAudioNodeTasks() | 717 void AudioContext::handleDeferredAudioNodeTasks() |
757 { | 718 { |
758 ASSERT(isAudioThread() && isGraphOwner()); | 719 ASSERT(isAudioThread() && isGraphOwner()); |
759 | 720 |
760 for (unsigned i = 0; i < m_deferredBreakConnectionList.size(); ++i) | 721 for (unsigned i = 0; i < m_deferredBreakConnectionList.size(); ++i) |
761 m_deferredBreakConnectionList[i]->breakConnectionWithLock(); | 722 m_deferredBreakConnectionList[i]->breakConnectionWithLock(); |
762 m_deferredBreakConnectionList.clear(); | 723 m_deferredBreakConnectionList.clear(); |
763 | |
764 #if !ENABLE(OILPAN) | |
765 for (unsigned i = 0; i < m_deferredFinishDerefList.size(); ++i) | |
766 m_deferredFinishDerefList[i]->finishDeref(); | |
767 m_deferredFinishDerefList.clear(); | |
768 #endif | |
769 } | 724 } |
770 | 725 |
771 #if ENABLE(OILPAN) | |
772 void AudioContext::registerLiveNode(AudioNode& node) | 726 void AudioContext::registerLiveNode(AudioNode& node) |
773 { | 727 { |
774 ASSERT(isMainThread()); | 728 ASSERT(isMainThread()); |
775 m_liveNodes.add(&node, adoptPtr(new AudioNodeDisposer(node))); | 729 m_liveNodes.add(&node, adoptPtr(new AudioNodeDisposer(node))); |
776 } | 730 } |
777 | 731 |
778 AudioContext::AudioNodeDisposer::~AudioNodeDisposer() | 732 AudioContext::AudioNodeDisposer::~AudioNodeDisposer() |
779 { | 733 { |
780 ASSERT(isMainThread()); | 734 ASSERT(isMainThread()); |
781 AudioContext::AutoLocker locker(m_node.context()); | 735 AudioContext::AutoLocker locker(m_node.context()); |
782 m_node.dispose(); | 736 m_node.dispose(); |
783 } | 737 } |
784 | 738 |
785 void AudioContext::registerLiveAudioSummingJunction(AudioSummingJunction& juncti
on) | 739 void AudioContext::registerLiveAudioSummingJunction(AudioSummingJunction& juncti
on) |
786 { | 740 { |
787 ASSERT(isMainThread()); | 741 ASSERT(isMainThread()); |
788 m_liveAudioSummingJunctions.add(&junction, adoptPtr(new AudioSummingJunction
Disposer(junction))); | 742 m_liveAudioSummingJunctions.add(&junction, adoptPtr(new AudioSummingJunction
Disposer(junction))); |
789 } | 743 } |
790 | 744 |
791 AudioContext::AudioSummingJunctionDisposer::~AudioSummingJunctionDisposer() | 745 AudioContext::AudioSummingJunctionDisposer::~AudioSummingJunctionDisposer() |
792 { | 746 { |
793 ASSERT(isMainThread()); | 747 ASSERT(isMainThread()); |
794 m_junction.context()->removeMarkedSummingJunction(&m_junction); | 748 m_junction.context()->removeMarkedSummingJunction(&m_junction); |
795 } | 749 } |
796 #else | |
797 | |
798 void AudioContext::markForDeletion(AudioNode* node) | |
799 { | |
800 ASSERT(isGraphOwner()); | |
801 | |
802 if (!isInitialized()) | |
803 m_nodesToDelete.append(node); | |
804 else | |
805 m_nodesMarkedForDeletion.append(node); | |
806 } | |
807 | |
808 void AudioContext::scheduleNodeDeletion() | |
809 { | |
810 bool isGood = isInitialized() && isGraphOwner(); | |
811 ASSERT(isGood); | |
812 if (!isGood) | |
813 return; | |
814 | |
815 // Make sure to call deleteMarkedNodes() on main thread. | |
816 if (m_nodesMarkedForDeletion.size() && !m_isDeletionScheduled) { | |
817 m_nodesToDelete.appendVector(m_nodesMarkedForDeletion); | |
818 m_nodesMarkedForDeletion.clear(); | |
819 | |
820 m_isDeletionScheduled = true; | |
821 | |
822 // Don't let ourself get deleted before the callback. | |
823 // See matching deref() in deleteMarkedNodesDispatch(). | |
824 ref(); | |
825 callOnMainThread(deleteMarkedNodesDispatch, this); | |
826 } | |
827 } | |
828 | |
829 void AudioContext::deleteMarkedNodesDispatch(void* userData) | |
830 { | |
831 AudioContext* context = reinterpret_cast<AudioContext*>(userData); | |
832 ASSERT(context); | |
833 if (!context) | |
834 return; | |
835 | |
836 context->deleteMarkedNodes(); | |
837 context->deref(); | |
838 } | |
839 | |
840 void AudioContext::deleteMarkedNodes() | |
841 { | |
842 ASSERT(isMainThread()); | |
843 | |
844 // Protect this object from being deleted before we release the mutex locked
by AutoLocker. | |
845 RefPtrWillBeRawPtr<AudioContext> protect(this); | |
846 { | |
847 AutoLocker locker(this); | |
848 | |
849 while (size_t n = m_nodesToDelete.size()) { | |
850 AudioNode* node = m_nodesToDelete[n - 1]; | |
851 m_nodesToDelete.removeLast(); | |
852 | |
853 node->dispose(); | |
854 | |
855 // Finally, delete it. | |
856 delete node; | |
857 } | |
858 m_isDeletionScheduled = false; | |
859 } | |
860 } | |
861 #endif | |
862 | 750 |
863 void AudioContext::unmarkDirtyNode(AudioNode& node) | 751 void AudioContext::unmarkDirtyNode(AudioNode& node) |
864 { | 752 { |
865 ASSERT(isGraphOwner()); | 753 ASSERT(isGraphOwner()); |
866 #if !ENABLE(OILPAN) | |
867 // Before deleting the node, clear out any AudioNodeInputs from | |
868 // m_dirtySummingJunctions. | |
869 unsigned numberOfInputs = node.numberOfInputs(); | |
870 for (unsigned i = 0; i < numberOfInputs; ++i) | |
871 m_dirtySummingJunctions.remove(node.input(i)); | |
872 #endif | |
873 | 754 |
874 // Before deleting the node, clear out any AudioNodeOutputs from | 755 // Before deleting the node, clear out any AudioNodeOutputs from |
875 // m_dirtyAudioNodeOutputs. | 756 // m_dirtyAudioNodeOutputs. |
876 unsigned numberOfOutputs = node.numberOfOutputs(); | 757 unsigned numberOfOutputs = node.numberOfOutputs(); |
877 for (unsigned i = 0; i < numberOfOutputs; ++i) | 758 for (unsigned i = 0; i < numberOfOutputs; ++i) |
878 m_dirtyAudioNodeOutputs.remove(node.output(i)); | 759 m_dirtyAudioNodeOutputs.remove(node.output(i)); |
879 } | 760 } |
880 | 761 |
881 void AudioContext::markSummingJunctionDirty(AudioSummingJunction* summingJunctio
n) | 762 void AudioContext::markSummingJunctionDirty(AudioSummingJunction* summingJunctio
n) |
882 { | 763 { |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
996 // Call the offline rendering completion event listener. | 877 // Call the offline rendering completion event listener. |
997 dispatchEvent(OfflineAudioCompletionEvent::create(renderedBuffer)); | 878 dispatchEvent(OfflineAudioCompletionEvent::create(renderedBuffer)); |
998 } | 879 } |
999 } | 880 } |
1000 | 881 |
1001 void AudioContext::trace(Visitor* visitor) | 882 void AudioContext::trace(Visitor* visitor) |
1002 { | 883 { |
1003 visitor->trace(m_renderTarget); | 884 visitor->trace(m_renderTarget); |
1004 visitor->trace(m_destinationNode); | 885 visitor->trace(m_destinationNode); |
1005 visitor->trace(m_listener); | 886 visitor->trace(m_listener); |
1006 #if ENABLE(OILPAN) | |
1007 visitor->trace(m_referencedNodes); | 887 visitor->trace(m_referencedNodes); |
1008 visitor->trace(m_liveNodes); | 888 visitor->trace(m_liveNodes); |
1009 visitor->trace(m_liveAudioSummingJunctions); | 889 visitor->trace(m_liveAudioSummingJunctions); |
1010 #endif | |
1011 EventTargetWithInlineData::trace(visitor); | 890 EventTargetWithInlineData::trace(visitor); |
1012 } | 891 } |
1013 | 892 |
1014 } // namespace blink | 893 } // namespace blink |
1015 | 894 |
1016 #endif // ENABLE(WEB_AUDIO) | 895 #endif // ENABLE(WEB_AUDIO) |
OLD | NEW |