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