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