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