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