Add AudioSummingJunction class to handle fan-in (abstracted from AudioNodeInput)
[WebKit-https.git] / Source / WebCore / Modules / webaudio / AudioContext.cpp
1 /*
2  * Copyright (C) 2010, Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26
27 #if ENABLE(WEB_AUDIO)
28
29 #include "AudioContext.h"
30
31 #include "AsyncAudioDecoder.h"
32 #include "AudioBuffer.h"
33 #include "AudioBufferCallback.h"
34 #include "AudioBufferSourceNode.h"
35 #include "AudioChannelMerger.h"
36 #include "AudioChannelSplitter.h"
37 #include "AudioGainNode.h"
38 #include "AudioListener.h"
39 #include "AudioNodeInput.h"
40 #include "AudioNodeOutput.h"
41 #include "AudioPannerNode.h"
42 #include "BiquadFilterNode.h"
43 #include "ConvolverNode.h"
44 #include "DefaultAudioDestinationNode.h"
45 #include "DelayNode.h"
46 #include "Document.h"
47 #include "DynamicsCompressorNode.h"
48 #include "ExceptionCode.h"
49 #include "FFTFrame.h"
50 #include "HRTFDatabaseLoader.h"
51 #include "HRTFPanner.h"
52 #include "JavaScriptAudioNode.h"
53 #include "OfflineAudioCompletionEvent.h"
54 #include "OfflineAudioDestinationNode.h"
55 #include "Oscillator.h"
56 #include "PlatformString.h"
57 #include "RealtimeAnalyserNode.h"
58 #include "ScriptCallStack.h"
59 #include "WaveShaperNode.h"
60 #include "WaveTable.h"
61
62 #if ENABLE(VIDEO)
63 #include "HTMLMediaElement.h"
64 #include "MediaElementAudioSourceNode.h"
65 #endif
66
67 #if DEBUG_AUDIONODE_REFERENCES
68 #include <stdio.h>
69 #endif
70
71 #if USE(GSTREAMER)
72 #include "GStreamerUtilities.h"
73 #endif
74
75 #include <wtf/ArrayBuffer.h>
76 #include <wtf/Atomics.h>
77 #include <wtf/MainThread.h>
78 #include <wtf/OwnPtr.h>
79 #include <wtf/PassOwnPtr.h>
80 #include <wtf/RefCounted.h>
81
82 // FIXME: check the proper way to reference an undefined thread ID
83 const int UndefinedThreadIdentifier = 0xffffffff;
84
85 const unsigned MaxNodesToDeletePerQuantum = 10;
86
87 namespace WebCore {
88     
89 namespace {
90     
91 bool isSampleRateRangeGood(float sampleRate)
92 {
93     // FIXME: It would be nice if the minimum sample-rate could be less than 44.1KHz,
94     // but that will require some fixes in HRTFPanner::fftSizeForSampleRate(), and some testing there.
95     return sampleRate >= 44100 && sampleRate <= 96000;
96 }
97
98 }
99
100 // Don't allow more than this number of simultaneous AudioContexts talking to hardware.
101 const unsigned MaxHardwareContexts = 4;
102 unsigned AudioContext::s_hardwareContextCount = 0;
103     
104 PassRefPtr<AudioContext> AudioContext::create(Document* document, ExceptionCode& ec)
105 {
106     UNUSED_PARAM(ec);
107
108     ASSERT(document);
109     ASSERT(isMainThread());
110     if (s_hardwareContextCount >= MaxHardwareContexts)
111         return 0;
112
113     RefPtr<AudioContext> audioContext(adoptRef(new AudioContext(document)));
114     audioContext->suspendIfNeeded();
115     return audioContext.release();
116 }
117
118 PassRefPtr<AudioContext> AudioContext::createOfflineContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionCode& ec)
119 {
120     ASSERT(document);
121
122     // FIXME: offline contexts have limitations on supported sample-rates.
123     // Currently all AudioContexts must have the same sample-rate.
124     HRTFDatabaseLoader* loader = HRTFDatabaseLoader::loader();
125     if (numberOfChannels > 10 || !isSampleRateRangeGood(sampleRate) || (loader && loader->databaseSampleRate() != sampleRate)) {
126         ec = SYNTAX_ERR;
127         return 0;
128     }
129
130     RefPtr<AudioContext> audioContext(new AudioContext(document, numberOfChannels, numberOfFrames, sampleRate));
131     audioContext->suspendIfNeeded();
132     return audioContext.release();
133 }
134
135 // Constructor for rendering to the audio hardware.
136 AudioContext::AudioContext(Document* document)
137     : ActiveDOMObject(document, this)
138     , m_isInitialized(false)
139     , m_isAudioThreadFinished(false)
140     , m_document(document)
141     , m_destinationNode(0)
142     , m_isDeletionScheduled(false)
143     , m_automaticPullNodesNeedUpdating(false)
144     , m_connectionCount(0)
145     , m_audioThread(0)
146     , m_graphOwnerThread(UndefinedThreadIdentifier)
147     , m_isOfflineContext(false)
148     , m_activeSourceCount(0)
149 {
150     constructCommon();
151
152     m_destinationNode = DefaultAudioDestinationNode::create(this);
153
154     // This sets in motion an asynchronous loading mechanism on another thread.
155     // We can check m_hrtfDatabaseLoader->isLoaded() to find out whether or not it has been fully loaded.
156     // It's not that useful to have a callback function for this since the audio thread automatically starts rendering on the graph
157     // when this has finished (see AudioDestinationNode).
158     m_hrtfDatabaseLoader = HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(sampleRate());
159 }
160
161 // Constructor for offline (non-realtime) rendering.
162 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate)
163     : ActiveDOMObject(document, this)
164     , m_isInitialized(false)
165     , m_isAudioThreadFinished(false)
166     , m_document(document)
167     , m_destinationNode(0)
168     , m_automaticPullNodesNeedUpdating(false)
169     , m_connectionCount(0)
170     , m_audioThread(0)
171     , m_graphOwnerThread(UndefinedThreadIdentifier)
172     , m_isOfflineContext(true)
173     , m_activeSourceCount(0)
174 {
175     constructCommon();
176
177     // FIXME: the passed in sampleRate MUST match the hardware sample-rate since HRTFDatabaseLoader is a singleton.
178     m_hrtfDatabaseLoader = HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(sampleRate);
179
180     // Create a new destination for offline rendering.
181     m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampleRate);
182     m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTarget.get());
183 }
184
185 void AudioContext::constructCommon()
186 {
187 #if USE(GSTREAMER)
188     initializeGStreamer();
189 #endif
190
191     FFTFrame::initialize();
192     
193     m_listener = AudioListener::create();
194 }
195
196 AudioContext::~AudioContext()
197 {
198 #if DEBUG_AUDIONODE_REFERENCES
199     printf("%p: AudioContext::~AudioContext()\n", this);
200 #endif
201     // AudioNodes keep a reference to their context, so there should be no way to be in the destructor if there are still AudioNodes around.
202     ASSERT(!m_nodesToDelete.size());
203     ASSERT(!m_referencedNodes.size());
204     ASSERT(!m_finishedNodes.size());
205     ASSERT(!m_automaticPullNodes.size());
206     ASSERT(!m_renderingAutomaticPullNodes.size());
207 }
208
209 void AudioContext::lazyInitialize()
210 {
211     if (!m_isInitialized) {
212         // Don't allow the context to initialize a second time after it's already been explicitly uninitialized.
213         ASSERT(!m_isAudioThreadFinished);
214         if (!m_isAudioThreadFinished) {
215             if (m_destinationNode.get()) {
216                 m_destinationNode->initialize();
217
218                 if (!isOfflineContext()) {
219                     // This starts the audio thread. The destination node's provideInput() method will now be called repeatedly to render audio.
220                     // Each time provideInput() is called, a portion of the audio stream is rendered. Let's call this time period a "render quantum".
221                     // NOTE: for now default AudioContext does not need an explicit startRendering() call from JavaScript.
222                     // We may want to consider requiring it for symmetry with OfflineAudioContext.
223                     m_destinationNode->startRendering();                    
224                     ++s_hardwareContextCount;
225                 }
226
227             }
228             m_isInitialized = true;
229         }
230     }
231 }
232
233 void AudioContext::uninitialize()
234 {
235     ASSERT(isMainThread());
236
237     if (m_isInitialized) {
238         // Protect this object from being deleted before we finish uninitializing.
239         RefPtr<AudioContext> protect(this);
240
241         // This stops the audio thread and all audio rendering.
242         m_destinationNode->uninitialize();
243
244         // Don't allow the context to initialize a second time after it's already been explicitly uninitialized.
245         m_isAudioThreadFinished = true;
246
247         // We have to release our reference to the destination node before the context will ever be deleted since the destination node holds a reference to the context.
248         m_destinationNode.clear();
249
250         if (!isOfflineContext()) {
251             ASSERT(s_hardwareContextCount);
252             --s_hardwareContextCount;
253         }
254         
255         // Get rid of the sources which may still be playing.
256         derefUnfinishedSourceNodes();
257
258         deleteMarkedNodes();
259
260         m_isInitialized = false;
261     }
262 }
263
264 bool AudioContext::isInitialized() const
265 {
266     return m_isInitialized;
267 }
268
269 bool AudioContext::isRunnable() const
270 {
271     if (!isInitialized())
272         return false;
273     
274     // Check with the HRTF spatialization system to see if it's finished loading.
275     return m_hrtfDatabaseLoader->isLoaded();
276 }
277
278 void AudioContext::uninitializeDispatch(void* userData)
279 {
280     AudioContext* context = reinterpret_cast<AudioContext*>(userData);
281     ASSERT(context);
282     if (!context)
283         return;
284
285     context->uninitialize();
286 }
287
288 void AudioContext::stop()
289 {
290     m_document = 0; // document is going away
291
292     // Don't call uninitialize() immediately here because the ScriptExecutionContext is in the middle
293     // of dealing with all of its ActiveDOMObjects at this point. uninitialize() can de-reference other
294     // ActiveDOMObjects so let's schedule uninitialize() to be called later.
295     // FIXME: see if there's a more direct way to handle this issue.
296     callOnMainThread(uninitializeDispatch, this);
297 }
298
299 Document* AudioContext::document() const
300 {
301     ASSERT(m_document);
302     return m_document;
303 }
304
305 bool AudioContext::hasDocument()
306 {
307     return m_document;
308 }
309
310 PassRefPtr<AudioBuffer> AudioContext::createBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionCode& ec)
311 {
312     RefPtr<AudioBuffer> audioBuffer = AudioBuffer::create(numberOfChannels, numberOfFrames, sampleRate);
313     if (!audioBuffer.get()) {
314         ec = SYNTAX_ERR;
315         return 0;
316     }
317
318     return audioBuffer;
319 }
320
321 PassRefPtr<AudioBuffer> AudioContext::createBuffer(ArrayBuffer* arrayBuffer, bool mixToMono, ExceptionCode& ec)
322 {
323     ASSERT(arrayBuffer);
324     if (!arrayBuffer) {
325         ec = SYNTAX_ERR;
326         return 0;
327     }
328
329     RefPtr<AudioBuffer> audioBuffer = AudioBuffer::createFromAudioFileData(arrayBuffer->data(), arrayBuffer->byteLength(), mixToMono, sampleRate());
330     if (!audioBuffer.get()) {
331         ec = SYNTAX_ERR;
332         return 0;
333     }
334
335     return audioBuffer;
336 }
337
338 void AudioContext::decodeAudioData(ArrayBuffer* audioData, PassRefPtr<AudioBufferCallback> successCallback, PassRefPtr<AudioBufferCallback> errorCallback, ExceptionCode& ec)
339 {
340     if (!audioData) {
341         ec = SYNTAX_ERR;
342         return;
343     }
344     m_audioDecoder.decodeAsync(audioData, sampleRate(), successCallback, errorCallback);
345 }
346
347 PassRefPtr<AudioBufferSourceNode> AudioContext::createBufferSource()
348 {
349     ASSERT(isMainThread());
350     lazyInitialize();
351     RefPtr<AudioBufferSourceNode> node = AudioBufferSourceNode::create(this, m_destinationNode->sampleRate());
352
353     // Because this is an AudioScheduledSourceNode, the context keeps a reference until it has finished playing.
354     // When this happens, AudioScheduledSourceNode::finish() calls AudioContext::notifyNodeFinishedProcessing().
355     refNode(node.get());
356
357     return node;
358 }
359
360 #if ENABLE(VIDEO)
361 PassRefPtr<MediaElementAudioSourceNode> AudioContext::createMediaElementSource(HTMLMediaElement* mediaElement, ExceptionCode& ec)
362 {
363     ASSERT(mediaElement);
364     if (!mediaElement) {
365         ec = INVALID_STATE_ERR;
366         return 0;
367     }
368         
369     ASSERT(isMainThread());
370     lazyInitialize();
371     
372     // First check if this media element already has a source node.
373     if (mediaElement->audioSourceNode()) {
374         ec = INVALID_STATE_ERR;
375         return 0;
376     }
377         
378     RefPtr<MediaElementAudioSourceNode> node = MediaElementAudioSourceNode::create(this, mediaElement);
379
380     mediaElement->setAudioSourceNode(node.get());
381
382     refNode(node.get()); // context keeps reference until node is disconnected
383     return node;
384 }
385 #endif
386
387 PassRefPtr<JavaScriptAudioNode> AudioContext::createJavaScriptNode(size_t bufferSize, ExceptionCode& ec)
388 {
389     // Set number of input/output channels to stereo by default.
390     return createJavaScriptNode(bufferSize, 2, 2, ec);
391 }
392
393 PassRefPtr<JavaScriptAudioNode> AudioContext::createJavaScriptNode(size_t bufferSize, size_t numberOfInputChannels, ExceptionCode& ec)
394 {
395     // Set number of output channels to stereo by default.
396     return createJavaScriptNode(bufferSize, numberOfInputChannels, 2, ec);
397 }
398
399 PassRefPtr<JavaScriptAudioNode> AudioContext::createJavaScriptNode(size_t bufferSize, size_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionCode& ec)
400 {
401     ASSERT(isMainThread());
402     lazyInitialize();
403     RefPtr<JavaScriptAudioNode> node = JavaScriptAudioNode::create(this, m_destinationNode->sampleRate(), bufferSize, numberOfInputChannels, numberOfOutputChannels);
404
405     if (!node.get()) {
406         ec = SYNTAX_ERR;
407         return 0;
408     }
409
410     refNode(node.get()); // context keeps reference until we stop making javascript rendering callbacks
411     return node;
412 }
413
414 PassRefPtr<BiquadFilterNode> AudioContext::createBiquadFilter()
415 {
416     ASSERT(isMainThread());
417     lazyInitialize();
418     return BiquadFilterNode::create(this, m_destinationNode->sampleRate());
419 }
420
421 PassRefPtr<WaveShaperNode> AudioContext::createWaveShaper()
422 {
423     ASSERT(isMainThread());
424     lazyInitialize();
425     return WaveShaperNode::create(this);
426 }
427
428 PassRefPtr<AudioPannerNode> AudioContext::createPanner()
429 {
430     ASSERT(isMainThread());
431     lazyInitialize();
432     return AudioPannerNode::create(this, m_destinationNode->sampleRate());
433 }
434
435 PassRefPtr<ConvolverNode> AudioContext::createConvolver()
436 {
437     ASSERT(isMainThread());
438     lazyInitialize();
439     return ConvolverNode::create(this, m_destinationNode->sampleRate());
440 }
441
442 PassRefPtr<DynamicsCompressorNode> AudioContext::createDynamicsCompressor()
443 {
444     ASSERT(isMainThread());
445     lazyInitialize();
446     return DynamicsCompressorNode::create(this, m_destinationNode->sampleRate());
447 }
448
449 PassRefPtr<RealtimeAnalyserNode> AudioContext::createAnalyser()
450 {
451     ASSERT(isMainThread());
452     lazyInitialize();
453     return RealtimeAnalyserNode::create(this, m_destinationNode->sampleRate());
454 }
455
456 PassRefPtr<AudioGainNode> AudioContext::createGainNode()
457 {
458     ASSERT(isMainThread());
459     lazyInitialize();
460     return AudioGainNode::create(this, m_destinationNode->sampleRate());
461 }
462
463 PassRefPtr<DelayNode> AudioContext::createDelayNode()
464 {
465     const double defaultMaxDelayTime = 1;
466     return createDelayNode(defaultMaxDelayTime);
467 }
468
469 PassRefPtr<DelayNode> AudioContext::createDelayNode(double maxDelayTime)
470 {
471     ASSERT(isMainThread());
472     lazyInitialize();
473     return DelayNode::create(this, m_destinationNode->sampleRate(), maxDelayTime);
474 }
475
476 PassRefPtr<AudioChannelSplitter> AudioContext::createChannelSplitter(ExceptionCode& ec)
477 {
478     const unsigned ChannelSplitterDefaultNumberOfOutputs = 6;
479     return createChannelSplitter(ChannelSplitterDefaultNumberOfOutputs, ec);
480 }
481
482 PassRefPtr<AudioChannelSplitter> AudioContext::createChannelSplitter(size_t numberOfOutputs, ExceptionCode& ec)
483 {
484     ASSERT(isMainThread());
485     lazyInitialize();
486
487     RefPtr<AudioChannelSplitter> node = AudioChannelSplitter::create(this, m_destinationNode->sampleRate(), numberOfOutputs);
488
489     if (!node.get()) {
490         ec = SYNTAX_ERR;
491         return 0;
492     }
493
494     return node;
495 }
496
497 PassRefPtr<AudioChannelMerger> AudioContext::createChannelMerger(ExceptionCode& ec)
498 {
499     const unsigned ChannelMergerDefaultNumberOfInputs = 6;
500     return createChannelMerger(ChannelMergerDefaultNumberOfInputs, ec);
501 }
502
503 PassRefPtr<AudioChannelMerger> AudioContext::createChannelMerger(size_t numberOfInputs, ExceptionCode& ec)
504 {
505     ASSERT(isMainThread());
506     lazyInitialize();
507
508     RefPtr<AudioChannelMerger> node = AudioChannelMerger::create(this, m_destinationNode->sampleRate(), numberOfInputs);
509
510     if (!node.get()) {
511         ec = SYNTAX_ERR;
512         return 0;
513     }
514
515     return node;
516 }
517
518 PassRefPtr<Oscillator> AudioContext::createOscillator()
519 {
520     ASSERT(isMainThread());
521     lazyInitialize();
522
523     RefPtr<Oscillator> node = Oscillator::create(this, m_destinationNode->sampleRate());
524
525     // Because this is an AudioScheduledSourceNode, the context keeps a reference until it has finished playing.
526     // When this happens, AudioScheduledSourceNode::finish() calls AudioContext::notifyNodeFinishedProcessing().
527     refNode(node.get());
528
529     return node;
530 }
531
532 PassRefPtr<WaveTable> AudioContext::createWaveTable(Float32Array* real, Float32Array* imag, ExceptionCode& ec)
533 {
534     ASSERT(isMainThread());
535     
536     if (!real || !imag || (real->length() != imag->length())) {
537         ec = SYNTAX_ERR;
538         return 0;
539     }
540     
541     lazyInitialize();
542     return WaveTable::create(sampleRate(), real, imag);
543 }
544
545 void AudioContext::notifyNodeFinishedProcessing(AudioNode* node)
546 {
547     ASSERT(isAudioThread());
548     m_finishedNodes.append(node);
549 }
550
551 void AudioContext::derefFinishedSourceNodes()
552 {
553     ASSERT(isGraphOwner());
554     ASSERT(isAudioThread() || isAudioThreadFinished());
555     for (unsigned i = 0; i < m_finishedNodes.size(); i++)
556         derefNode(m_finishedNodes[i]);
557
558     m_finishedNodes.clear();
559 }
560
561 void AudioContext::refNode(AudioNode* node)
562 {
563     ASSERT(isMainThread());
564     AutoLocker locker(this);
565     
566     node->ref(AudioNode::RefTypeConnection);
567     m_referencedNodes.append(node);
568 }
569
570 void AudioContext::derefNode(AudioNode* node)
571 {
572     ASSERT(isGraphOwner());
573     
574     node->deref(AudioNode::RefTypeConnection);
575
576     for (unsigned i = 0; i < m_referencedNodes.size(); ++i) {
577         if (node == m_referencedNodes[i]) {
578             m_referencedNodes.remove(i);
579             break;
580         }
581     }
582 }
583
584 void AudioContext::derefUnfinishedSourceNodes()
585 {
586     ASSERT(isMainThread() && isAudioThreadFinished());
587     for (unsigned i = 0; i < m_referencedNodes.size(); ++i)
588         m_referencedNodes[i]->deref(AudioNode::RefTypeConnection);
589
590     m_referencedNodes.clear();
591 }
592
593 void AudioContext::lock(bool& mustReleaseLock)
594 {
595     // Don't allow regular lock in real-time audio thread.
596     ASSERT(isMainThread());
597
598     ThreadIdentifier thisThread = currentThread();
599
600     if (thisThread == m_graphOwnerThread) {
601         // We already have the lock.
602         mustReleaseLock = false;
603     } else {
604         // Acquire the lock.
605         m_contextGraphMutex.lock();
606         m_graphOwnerThread = thisThread;
607         mustReleaseLock = true;
608     }
609 }
610
611 bool AudioContext::tryLock(bool& mustReleaseLock)
612 {
613     ThreadIdentifier thisThread = currentThread();
614     bool isAudioThread = thisThread == audioThread();
615
616     // Try to catch cases of using try lock on main thread - it should use regular lock.
617     ASSERT(isAudioThread || isAudioThreadFinished());
618     
619     if (!isAudioThread) {
620         // In release build treat tryLock() as lock() (since above ASSERT(isAudioThread) never fires) - this is the best we can do.
621         lock(mustReleaseLock);
622         return true;
623     }
624     
625     bool hasLock;
626     
627     if (thisThread == m_graphOwnerThread) {
628         // Thread already has the lock.
629         hasLock = true;
630         mustReleaseLock = false;
631     } else {
632         // Don't already have the lock - try to acquire it.
633         hasLock = m_contextGraphMutex.tryLock();
634         
635         if (hasLock)
636             m_graphOwnerThread = thisThread;
637
638         mustReleaseLock = hasLock;
639     }
640     
641     return hasLock;
642 }
643
644 void AudioContext::unlock()
645 {
646     ASSERT(currentThread() == m_graphOwnerThread);
647
648     m_graphOwnerThread = UndefinedThreadIdentifier;
649     m_contextGraphMutex.unlock();
650 }
651
652 bool AudioContext::isAudioThread() const
653 {
654     return currentThread() == m_audioThread;
655 }
656
657 bool AudioContext::isGraphOwner() const
658 {
659     return currentThread() == m_graphOwnerThread;
660 }
661
662 void AudioContext::addDeferredFinishDeref(AudioNode* node, AudioNode::RefType refType)
663 {
664     ASSERT(isAudioThread());
665     m_deferredFinishDerefList.append(AudioContext::RefInfo(node, refType));
666 }
667
668 void AudioContext::handlePreRenderTasks()
669 {
670     ASSERT(isAudioThread());
671  
672     // At the beginning of every render quantum, try to update the internal rendering graph state (from main thread changes).
673     // It's OK if the tryLock() fails, we'll just take slightly longer to pick up the changes.
674     bool mustReleaseLock;
675     if (tryLock(mustReleaseLock)) {
676         // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutputs.
677         handleDirtyAudioSummingJunctions();
678         handleDirtyAudioNodeOutputs();
679
680         updateAutomaticPullNodes();
681
682         if (mustReleaseLock)
683             unlock();
684     }
685 }
686
687 void AudioContext::handlePostRenderTasks()
688 {
689     ASSERT(isAudioThread());
690  
691     // Must use a tryLock() here too.  Don't worry, the lock will very rarely be contended and this method is called frequently.
692     // The worst that can happen is that there will be some nodes which will take slightly longer than usual to be deleted or removed
693     // from the render graph (in which case they'll render silence).
694     bool mustReleaseLock;
695     if (tryLock(mustReleaseLock)) {
696         // Take care of finishing any derefs where the tryLock() failed previously.
697         handleDeferredFinishDerefs();
698
699         // Dynamically clean up nodes which are no longer needed.
700         derefFinishedSourceNodes();
701
702         // Don't delete in the real-time thread. Let the main thread do it.
703         // Ref-counted objects held by certain AudioNodes may not be thread-safe.
704         scheduleNodeDeletion();
705
706         // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutputs.
707         handleDirtyAudioSummingJunctions();
708         handleDirtyAudioNodeOutputs();
709
710         updateAutomaticPullNodes();
711
712         if (mustReleaseLock)
713             unlock();
714     }
715 }
716
717 void AudioContext::handleDeferredFinishDerefs()
718 {
719     ASSERT(isAudioThread() && isGraphOwner());
720     for (unsigned i = 0; i < m_deferredFinishDerefList.size(); ++i) {
721         AudioNode* node = m_deferredFinishDerefList[i].m_node;
722         AudioNode::RefType refType = m_deferredFinishDerefList[i].m_refType;
723         node->finishDeref(refType);
724     }
725     
726     m_deferredFinishDerefList.clear();
727 }
728
729 void AudioContext::markForDeletion(AudioNode* node)
730 {
731     ASSERT(isGraphOwner());
732     m_nodesToDelete.append(node);
733
734     // This is probably the best time for us to remove the node from automatic pull list,
735     // since all connections are gone and we hold the graph lock. Then when handlePostRenderTasks()
736     // gets a chance to schedule the deletion work, updateAutomaticPullNodes() also gets a chance to
737     // modify m_renderingAutomaticPullNodes.
738     removeAutomaticPullNode(node);
739 }
740
741 void AudioContext::scheduleNodeDeletion()
742 {
743     bool isGood = m_isInitialized && isGraphOwner();
744     ASSERT(isGood);
745     if (!isGood)
746         return;
747
748     // Make sure to call deleteMarkedNodes() on main thread.    
749     if (m_nodesToDelete.size() && !m_isDeletionScheduled) {
750         m_isDeletionScheduled = true;
751
752         // Don't let ourself get deleted before the callback.
753         // See matching deref() in deleteMarkedNodesDispatch().
754         ref();
755         callOnMainThread(deleteMarkedNodesDispatch, this);
756     }
757 }
758
759 void AudioContext::deleteMarkedNodesDispatch(void* userData)
760 {
761     AudioContext* context = reinterpret_cast<AudioContext*>(userData);
762     ASSERT(context);
763     if (!context)
764         return;
765
766     context->deleteMarkedNodes();
767     context->deref();
768 }
769
770 void AudioContext::deleteMarkedNodes()
771 {
772     ASSERT(isMainThread());
773
774     AutoLocker locker(this);
775     
776     // Note: deleting an AudioNode can cause m_nodesToDelete to grow.
777     while (size_t n = m_nodesToDelete.size()) {
778         AudioNode* node = m_nodesToDelete[n - 1];
779         m_nodesToDelete.removeLast();
780
781         // Before deleting the node, clear out any AudioNodeInputs from m_dirtySummingJunctions.
782         unsigned numberOfInputs = node->numberOfInputs();
783         for (unsigned i = 0; i < numberOfInputs; ++i)
784             m_dirtySummingJunctions.remove(node->input(i));
785
786         // Before deleting the node, clear out any AudioNodeOutputs from m_dirtyAudioNodeOutputs.
787         unsigned numberOfOutputs = node->numberOfOutputs();
788         for (unsigned i = 0; i < numberOfOutputs; ++i)
789             m_dirtyAudioNodeOutputs.remove(node->output(i));
790
791         // Finally, delete it.
792         delete node;
793     }
794     
795     m_isDeletionScheduled = false;
796 }
797
798 void AudioContext::markSummingJunctionDirty(AudioSummingJunction* summingJunction)
799 {
800     ASSERT(isGraphOwner());    
801     m_dirtySummingJunctions.add(summingJunction);
802 }
803
804 void AudioContext::removeMarkedSummingJunction(AudioSummingJunction* summingJunction)
805 {
806     ASSERT(isMainThread());
807     AutoLocker locker(this);
808     m_dirtySummingJunctions.remove(summingJunction);
809 }
810
811 void AudioContext::markAudioNodeOutputDirty(AudioNodeOutput* output)
812 {
813     ASSERT(isGraphOwner());    
814     m_dirtyAudioNodeOutputs.add(output);
815 }
816
817 void AudioContext::handleDirtyAudioSummingJunctions()
818 {
819     ASSERT(isGraphOwner());    
820
821     for (HashSet<AudioSummingJunction*>::iterator i = m_dirtySummingJunctions.begin(); i != m_dirtySummingJunctions.end(); ++i)
822         (*i)->updateRenderingState();
823
824     m_dirtySummingJunctions.clear();
825 }
826
827 void AudioContext::handleDirtyAudioNodeOutputs()
828 {
829     ASSERT(isGraphOwner());    
830
831     for (HashSet<AudioNodeOutput*>::iterator i = m_dirtyAudioNodeOutputs.begin(); i != m_dirtyAudioNodeOutputs.end(); ++i)
832         (*i)->updateRenderingState();
833
834     m_dirtyAudioNodeOutputs.clear();
835 }
836
837 void AudioContext::addAutomaticPullNode(AudioNode* node)
838 {
839     ASSERT(isGraphOwner());
840
841     if (!m_automaticPullNodes.contains(node)) {
842         m_automaticPullNodes.add(node);
843         m_automaticPullNodesNeedUpdating = true;
844     }
845 }
846
847 void AudioContext::removeAutomaticPullNode(AudioNode* node)
848 {
849     ASSERT(isGraphOwner());
850
851     if (m_automaticPullNodes.contains(node)) {
852         m_automaticPullNodes.remove(node);
853         m_automaticPullNodesNeedUpdating = true;
854     }
855 }
856
857 void AudioContext::updateAutomaticPullNodes()
858 {
859     ASSERT(isGraphOwner());
860
861     if (m_automaticPullNodesNeedUpdating) {
862         // Copy from m_automaticPullNodes to m_renderingAutomaticPullNodes.
863         m_renderingAutomaticPullNodes.resize(m_automaticPullNodes.size());
864
865         unsigned j = 0;
866         for (HashSet<AudioNode*>::iterator i = m_automaticPullNodes.begin(); i != m_automaticPullNodes.end(); ++i, ++j) {
867             AudioNode* output = *i;
868             m_renderingAutomaticPullNodes[j] = output;
869         }
870
871         m_automaticPullNodesNeedUpdating = false;
872     }
873 }
874
875 void AudioContext::processAutomaticPullNodes(size_t framesToProcess)
876 {
877     ASSERT(isAudioThread());
878
879     for (unsigned i = 0; i < m_renderingAutomaticPullNodes.size(); ++i)
880         m_renderingAutomaticPullNodes[i]->processIfNecessary(framesToProcess);
881 }
882
883 const AtomicString& AudioContext::interfaceName() const
884 {
885     return eventNames().interfaceForAudioContext;
886 }
887
888 ScriptExecutionContext* AudioContext::scriptExecutionContext() const
889 {
890     return document();
891 }
892
893 void AudioContext::startRendering()
894 {
895     destination()->startRendering();
896 }
897
898 void AudioContext::fireCompletionEvent()
899 {
900     ASSERT(isMainThread());
901     if (!isMainThread())
902         return;
903         
904     AudioBuffer* renderedBuffer = m_renderTarget.get();
905
906     ASSERT(renderedBuffer);
907     if (!renderedBuffer)
908         return;
909
910     // Avoid firing the event if the document has already gone away.
911     if (hasDocument()) {
912         // Call the offline rendering completion event listener.
913         dispatchEvent(OfflineAudioCompletionEvent::create(renderedBuffer));
914     }
915 }
916
917 void AudioContext::incrementActiveSourceCount()
918 {
919     atomicIncrement(&m_activeSourceCount);
920 }
921
922 void AudioContext::decrementActiveSourceCount()
923 {
924     atomicDecrement(&m_activeSourceCount);
925 }
926
927 } // namespace WebCore
928
929 #endif // ENABLE(WEB_AUDIO)