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