WTF shouldn't have both Thread and ThreadIdentifier
[WebKit.git] / Source / WebCore / Modules / webaudio / AudioContext.cpp
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  * Copyright (C) 2016 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1.  Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #if ENABLE(WEB_AUDIO)
29
30 #include "AudioContext.h"
31
32 #include "AnalyserNode.h"
33 #include "AsyncAudioDecoder.h"
34 #include "AudioBuffer.h"
35 #include "AudioBufferCallback.h"
36 #include "AudioBufferSourceNode.h"
37 #include "AudioListener.h"
38 #include "AudioNodeInput.h"
39 #include "AudioNodeOutput.h"
40 #include "AudioSession.h"
41 #include "BiquadFilterNode.h"
42 #include "ChannelMergerNode.h"
43 #include "ChannelSplitterNode.h"
44 #include "ConvolverNode.h"
45 #include "DefaultAudioDestinationNode.h"
46 #include "DelayNode.h"
47 #include "Document.h"
48 #include "DynamicsCompressorNode.h"
49 #include "EventNames.h"
50 #include "FFTFrame.h"
51 #include "Frame.h"
52 #include "FrameLoader.h"
53 #include "GainNode.h"
54 #include "GenericEventQueue.h"
55 #include "HRTFDatabaseLoader.h"
56 #include "HRTFPanner.h"
57 #include "JSDOMPromiseDeferred.h"
58 #include "Logging.h"
59 #include "NetworkingContext.h"
60 #include "OfflineAudioCompletionEvent.h"
61 #include "OfflineAudioDestinationNode.h"
62 #include "OscillatorNode.h"
63 #include "Page.h"
64 #include "PannerNode.h"
65 #include "PeriodicWave.h"
66 #include "ScriptController.h"
67 #include "ScriptProcessorNode.h"
68 #include "WaveShaperNode.h"
69 #include <inspector/ScriptCallStack.h>
70
71 #if ENABLE(MEDIA_STREAM)
72 #include "MediaStream.h"
73 #include "MediaStreamAudioDestinationNode.h"
74 #include "MediaStreamAudioSource.h"
75 #include "MediaStreamAudioSourceNode.h"
76 #endif
77
78 #if ENABLE(VIDEO)
79 #include "HTMLMediaElement.h"
80 #include "MediaElementAudioSourceNode.h"
81 #endif
82
83 #if DEBUG_AUDIONODE_REFERENCES
84 #include <stdio.h>
85 #endif
86
87 #if USE(GSTREAMER)
88 #include "GStreamerUtilities.h"
89 #endif
90
91 #if PLATFORM(IOS)
92 #include "ScriptController.h"
93 #include "Settings.h"
94 #endif
95
96 #include <runtime/ArrayBuffer.h>
97 #include <wtf/Atomics.h>
98 #include <wtf/MainThread.h>
99 #include <wtf/Ref.h>
100 #include <wtf/RefCounted.h>
101 #include <wtf/text/WTFString.h>
102
103 const unsigned MaxPeriodicWaveLength = 4096;
104
105 namespace WebCore {
106
107 #define RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(document()->page() && document()->page()->isAlwaysOnLoggingAllowed(), Media, "%p - AudioContext::" fmt, this, ##__VA_ARGS__)
108     
109 bool AudioContext::isSampleRateRangeGood(float sampleRate)
110 {
111     // FIXME: It would be nice if the minimum sample-rate could be less than 44.1KHz,
112     // but that will require some fixes in HRTFPanner::fftSizeForSampleRate(), and some testing there.
113     return sampleRate >= 44100 && sampleRate <= 96000;
114 }
115
116 // Don't allow more than this number of simultaneous AudioContexts talking to hardware.
117 const unsigned MaxHardwareContexts = 4;
118 unsigned AudioContext::s_hardwareContextCount = 0;
119     
120 RefPtr<AudioContext> AudioContext::create(Document& document)
121 {
122     ASSERT(isMainThread());
123     if (s_hardwareContextCount >= MaxHardwareContexts)
124         return nullptr;
125
126     RefPtr<AudioContext> audioContext(adoptRef(new AudioContext(document)));
127     audioContext->suspendIfNeeded();
128     return audioContext;
129 }
130
131 // Constructor for rendering to the audio hardware.
132 AudioContext::AudioContext(Document& document)
133     : ActiveDOMObject(&document)
134     , m_mediaSession(PlatformMediaSession::create(*this))
135     , m_eventQueue(std::make_unique<GenericEventQueue>(*this))
136 {
137     constructCommon();
138
139     m_destinationNode = DefaultAudioDestinationNode::create(*this);
140
141     // Initialize the destination node's muted state to match the page's current muted state.
142     pageMutedStateDidChange();
143 }
144
145 // Constructor for offline (non-realtime) rendering.
146 AudioContext::AudioContext(Document& document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate)
147     : ActiveDOMObject(&document)
148     , m_isOfflineContext(true)
149     , m_mediaSession(PlatformMediaSession::create(*this))
150     , m_eventQueue(std::make_unique<GenericEventQueue>(*this))
151 {
152     constructCommon();
153
154     // Create a new destination for offline rendering.
155     m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampleRate);
156     m_destinationNode = OfflineAudioDestinationNode::create(*this, m_renderTarget.get());
157 }
158
159 void AudioContext::constructCommon()
160 {
161     // According to spec AudioContext must die only after page navigate.
162     // Lets mark it as ActiveDOMObject with pending activity and unmark it in clear method.
163     setPendingActivity(this);
164
165 #if USE(GSTREAMER)
166     initializeGStreamer();
167 #endif
168
169     FFTFrame::initialize();
170     
171     m_listener = AudioListener::create();
172
173 #if PLATFORM(IOS)
174     if (document()->settings().audioPlaybackRequiresUserGesture())
175         addBehaviorRestriction(RequireUserGestureForAudioStartRestriction);
176     else
177         m_restrictions = NoRestrictions;
178 #endif
179
180 #if PLATFORM(COCOA)
181     addBehaviorRestriction(RequirePageConsentForAudioStartRestriction);
182 #endif
183 }
184
185 AudioContext::~AudioContext()
186 {
187 #if DEBUG_AUDIONODE_REFERENCES
188     fprintf(stderr, "%p: AudioContext::~AudioContext()\n", this);
189 #endif
190     ASSERT(!m_isInitialized);
191     ASSERT(m_isStopScheduled);
192     ASSERT(m_nodesToDelete.isEmpty());
193     ASSERT(m_referencedNodes.isEmpty());
194     ASSERT(m_finishedNodes.isEmpty()); // FIXME (bug 105870): This assertion fails on tests sometimes.
195     ASSERT(m_automaticPullNodes.isEmpty());
196     if (m_automaticPullNodesNeedUpdating)
197         m_renderingAutomaticPullNodes.resize(m_automaticPullNodes.size());
198     ASSERT(m_renderingAutomaticPullNodes.isEmpty());
199     // FIXME: Can we assert that m_deferredFinishDerefList is empty?
200 }
201
202 void AudioContext::lazyInitialize()
203 {
204     if (m_isInitialized)
205         return;
206
207     // Don't allow the context to initialize a second time after it's already been explicitly uninitialized.
208     ASSERT(!m_isAudioThreadFinished);
209     if (m_isAudioThreadFinished)
210         return;
211
212     if (m_destinationNode) {
213         m_destinationNode->initialize();
214
215         if (!isOfflineContext()) {
216             document()->addAudioProducer(this);
217             document()->registerForVisibilityStateChangedCallbacks(this);
218
219             // This starts the audio thread. The destination node's provideInput() method will now be called repeatedly to render audio.
220             // Each time provideInput() is called, a portion of the audio stream is rendered. Let's call this time period a "render quantum".
221             // NOTE: for now default AudioContext does not need an explicit startRendering() call from JavaScript.
222             // We may want to consider requiring it for symmetry with OfflineAudioContext.
223             startRendering();
224             ++s_hardwareContextCount;
225         }
226     }
227     m_isInitialized = true;
228 }
229
230 void AudioContext::clear()
231 {
232     // 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.
233     if (m_destinationNode)
234         m_destinationNode = nullptr;
235
236     // Audio thread is dead. Nobody will schedule node deletion action. Let's do it ourselves.
237     do {
238         deleteMarkedNodes();
239         m_nodesToDelete.appendVector(m_nodesMarkedForDeletion);
240         m_nodesMarkedForDeletion.clear();
241     } while (m_nodesToDelete.size());
242
243     // It was set in constructCommon.
244     unsetPendingActivity(this);
245 }
246
247 void AudioContext::uninitialize()
248 {
249     ASSERT(isMainThread());
250
251     if (!m_isInitialized)
252         return;
253
254     // This stops the audio thread and all audio rendering.
255     m_destinationNode->uninitialize();
256
257     // Don't allow the context to initialize a second time after it's already been explicitly uninitialized.
258     m_isAudioThreadFinished = true;
259
260     if (!isOfflineContext()) {
261         document()->removeAudioProducer(this);
262         document()->unregisterForVisibilityStateChangedCallbacks(this);
263
264         ASSERT(s_hardwareContextCount);
265         --s_hardwareContextCount;
266
267         // Offline contexts move to 'Closed' state when dispatching the completion event.
268         setState(State::Closed);
269     }
270
271     // Get rid of the sources which may still be playing.
272     derefUnfinishedSourceNodes();
273
274     m_isInitialized = false;
275 }
276
277 bool AudioContext::isInitialized() const
278 {
279     return m_isInitialized;
280 }
281
282 void AudioContext::addReaction(State state, DOMPromiseDeferred<void>&& promise)
283 {
284     size_t stateIndex = static_cast<size_t>(state);
285     if (stateIndex >= m_stateReactions.size())
286         m_stateReactions.grow(stateIndex + 1);
287
288     m_stateReactions[stateIndex].append(WTFMove(promise));
289 }
290
291 void AudioContext::setState(State state)
292 {
293     if (m_state == state)
294         return;
295
296     m_state = state;
297     m_eventQueue->enqueueEvent(Event::create(eventNames().statechangeEvent, true, false));
298
299     size_t stateIndex = static_cast<size_t>(state);
300     if (stateIndex >= m_stateReactions.size())
301         return;
302
303     Vector<DOMPromiseDeferred<void>> reactions;
304     m_stateReactions[stateIndex].swap(reactions);
305
306     for (auto& promise : reactions)
307         promise.resolve();
308 }
309
310 void AudioContext::stop()
311 {
312     ASSERT(isMainThread());
313
314     // Usually ScriptExecutionContext calls stop twice.
315     if (m_isStopScheduled)
316         return;
317     m_isStopScheduled = true;
318
319     document()->updateIsPlayingMedia();
320
321     m_eventQueue->close();
322
323     // Don't call uninitialize() immediately here because the ScriptExecutionContext is in the middle
324     // of dealing with all of its ActiveDOMObjects at this point. uninitialize() can de-reference other
325     // ActiveDOMObjects so let's schedule uninitialize() to be called later.
326     // FIXME: see if there's a more direct way to handle this issue.
327     // FIXME: This sounds very wrong. The whole idea of stop() is that it stops everything, and if we
328     // schedule some observable work for later, the work likely happens at an inappropriate time.
329     callOnMainThread([this] {
330         uninitialize();
331         clear();
332     });
333 }
334
335 bool AudioContext::canSuspendForDocumentSuspension() const
336 {
337     // FIXME: We should be able to suspend while rendering as well with some more code.
338     return m_state == State::Suspended || m_state == State::Closed;
339 }
340
341 const char* AudioContext::activeDOMObjectName() const
342 {
343     return "AudioContext";
344 }
345
346 Document* AudioContext::document() const
347 {
348     ASSERT(m_scriptExecutionContext);
349     return downcast<Document>(m_scriptExecutionContext);
350 }
351
352 const Document* AudioContext::hostingDocument() const
353 {
354     return downcast<Document>(m_scriptExecutionContext);
355 }
356
357 String AudioContext::sourceApplicationIdentifier() const
358 {
359     Document* document = this->document();
360     if (Frame* frame = document ? document->frame() : nullptr) {
361         if (NetworkingContext* networkingContext = frame->loader().networkingContext())
362             return networkingContext->sourceApplicationIdentifier();
363     }
364     return emptyString();
365 }
366
367 bool AudioContext::processingUserGestureForMedia() const
368 {
369     return document() ? document()->processingUserGestureForMedia() : false;
370 }
371
372 bool AudioContext::isSuspended() const
373 {
374     return !document() || document()->activeDOMObjectsAreSuspended() || document()->activeDOMObjectsAreStopped();
375 }
376
377 void AudioContext::visibilityStateChanged()
378 {
379     // Do not suspend if audio is audible.
380     if (mediaState() == MediaProducer::IsPlayingAudio)
381         return;
382
383     if (document()->hidden()) {
384         if (state() == State::Running) {
385             RELEASE_LOG_IF_ALLOWED("visibilityStateChanged() Suspending playback after going to the background");
386             m_mediaSession->beginInterruption(PlatformMediaSession::EnteringBackground);
387         }
388     } else {
389         if (state() == State::Interrupted) {
390             RELEASE_LOG_IF_ALLOWED("visibilityStateChanged() Resuming playback after entering foreground");
391             m_mediaSession->endInterruption(PlatformMediaSession::MayResumePlaying);
392         }
393     }
394 }
395
396 ExceptionOr<Ref<AudioBuffer>> AudioContext::createBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate)
397 {
398     auto audioBuffer = AudioBuffer::create(numberOfChannels, numberOfFrames, sampleRate);
399     if (!audioBuffer)
400         return Exception { NotSupportedError };
401     return audioBuffer.releaseNonNull();
402 }
403
404 ExceptionOr<Ref<AudioBuffer>> AudioContext::createBuffer(ArrayBuffer& arrayBuffer, bool mixToMono)
405 {
406     auto audioBuffer = AudioBuffer::createFromAudioFileData(arrayBuffer.data(), arrayBuffer.byteLength(), mixToMono, sampleRate());
407     if (!audioBuffer)
408         return Exception { SyntaxError };
409     return audioBuffer.releaseNonNull();
410 }
411
412 void AudioContext::decodeAudioData(Ref<ArrayBuffer>&& audioData, RefPtr<AudioBufferCallback>&& successCallback, RefPtr<AudioBufferCallback>&& errorCallback)
413 {
414     m_audioDecoder.decodeAsync(WTFMove(audioData), sampleRate(), WTFMove(successCallback), WTFMove(errorCallback));
415 }
416
417 Ref<AudioBufferSourceNode> AudioContext::createBufferSource()
418 {
419     ASSERT(isMainThread());
420     lazyInitialize();
421     Ref<AudioBufferSourceNode> node = AudioBufferSourceNode::create(*this, m_destinationNode->sampleRate());
422
423     // Because this is an AudioScheduledSourceNode, the context keeps a reference until it has finished playing.
424     // When this happens, AudioScheduledSourceNode::finish() calls AudioContext::notifyNodeFinishedProcessing().
425     refNode(node);
426
427     return node;
428 }
429
430 #if ENABLE(VIDEO)
431
432 ExceptionOr<Ref<MediaElementAudioSourceNode>> AudioContext::createMediaElementSource(HTMLMediaElement& mediaElement)
433 {
434     ASSERT(isMainThread());
435     lazyInitialize();
436     
437     if (mediaElement.audioSourceNode())
438         return Exception { InvalidStateError };
439
440     auto node = MediaElementAudioSourceNode::create(*this, mediaElement);
441
442     mediaElement.setAudioSourceNode(node.ptr());
443
444     refNode(node.get()); // context keeps reference until node is disconnected
445     return WTFMove(node);
446 }
447
448 #endif
449
450 #if ENABLE(MEDIA_STREAM)
451
452 ExceptionOr<Ref<MediaStreamAudioSourceNode>> AudioContext::createMediaStreamSource(MediaStream& mediaStream)
453 {
454     ASSERT(isMainThread());
455
456     auto audioTracks = mediaStream.getAudioTracks();
457     if (audioTracks.isEmpty())
458         return Exception { InvalidStateError };
459
460     MediaStreamTrack* providerTrack = nullptr;
461     for (auto& track : audioTracks) {
462         if (track->audioSourceProvider()) {
463             providerTrack = track.get();
464             break;
465         }
466     }
467     if (!providerTrack)
468         return Exception { InvalidStateError };
469
470     lazyInitialize();
471
472     auto node = MediaStreamAudioSourceNode::create(*this, mediaStream, *providerTrack);
473     node->setFormat(2, sampleRate());
474
475     refNode(node); // context keeps reference until node is disconnected
476     return WTFMove(node);
477 }
478
479 Ref<MediaStreamAudioDestinationNode> AudioContext::createMediaStreamDestination()
480 {
481     // FIXME: Add support for an optional argument which specifies the number of channels.
482     // FIXME: The default should probably be stereo instead of mono.
483     return MediaStreamAudioDestinationNode::create(*this, 1);
484 }
485
486 #endif
487
488 ExceptionOr<Ref<ScriptProcessorNode>> AudioContext::createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, size_t numberOfOutputChannels)
489 {
490     ASSERT(isMainThread());
491     lazyInitialize();
492
493     // W3C Editor's Draft 06 June 2017
494     //  https://webaudio.github.io/web-audio-api/#widl-BaseAudioContext-createScriptProcessor-ScriptProcessorNode-unsigned-long-bufferSize-unsigned-long-numberOfInputChannels-unsigned-long-numberOfOutputChannels
495
496     // The bufferSize parameter determines the buffer size in units of sample-frames. If it's not passed in,
497     // or if the value is 0, then the implementation will choose the best buffer size for the given environment,
498     // which will be constant power of 2 throughout the lifetime of the node. ... If the value of this parameter
499     // is not one of the allowed power-of-2 values listed above, an IndexSizeError must be thrown.
500     switch (bufferSize) {
501     case 0:
502 #if USE(AUDIO_SESSION)
503         // Pick a value between 256 (2^8) and 16384 (2^14), based on the buffer size of the current AudioSession:
504         bufferSize = 1 << std::max<size_t>(8, std::min<size_t>(14, std::log2(AudioSession::sharedSession().bufferSize())));
505 #else
506         bufferSize = 2048;
507 #endif
508         break;
509     case 256:
510     case 512:
511     case 1024:
512     case 2048:
513     case 4096:
514     case 8192:
515     case 16384:
516         break;
517     default:
518         return Exception { IndexSizeError };
519     }
520
521     // An IndexSizeError exception must be thrown if bufferSize or numberOfInputChannels or numberOfOutputChannels
522     // are outside the valid range. It is invalid for both numberOfInputChannels and numberOfOutputChannels to be zero.
523     // In this case an IndexSizeError must be thrown.
524
525     if (!numberOfInputChannels && !numberOfOutputChannels)
526         return Exception { NotSupportedError };
527
528     // This parameter [numberOfInputChannels] determines the number of channels for this node's input. Values of
529     // up to 32 must be supported. A NotSupportedError must be thrown if the number of channels is not supported.
530
531     if (numberOfInputChannels > maxNumberOfChannels())
532         return Exception { NotSupportedError };
533
534     // This parameter [numberOfOutputChannels] determines the number of channels for this node's output. Values of
535     // up to 32 must be supported. A NotSupportedError must be thrown if the number of channels is not supported.
536
537     if (numberOfOutputChannels > maxNumberOfChannels())
538         return Exception { NotSupportedError };
539
540     auto node = ScriptProcessorNode::create(*this, m_destinationNode->sampleRate(), bufferSize, numberOfInputChannels, numberOfOutputChannels);
541
542     refNode(node); // context keeps reference until we stop making javascript rendering callbacks
543     return WTFMove(node);
544 }
545
546 Ref<BiquadFilterNode> AudioContext::createBiquadFilter()
547 {
548     ASSERT(isMainThread());
549     lazyInitialize();
550     return BiquadFilterNode::create(*this, m_destinationNode->sampleRate());
551 }
552
553 Ref<WaveShaperNode> AudioContext::createWaveShaper()
554 {
555     ASSERT(isMainThread());
556     lazyInitialize();
557     return WaveShaperNode::create(*this);
558 }
559
560 Ref<PannerNode> AudioContext::createPanner()
561 {
562     ASSERT(isMainThread());
563     lazyInitialize();
564     return PannerNode::create(*this, m_destinationNode->sampleRate());
565 }
566
567 Ref<ConvolverNode> AudioContext::createConvolver()
568 {
569     ASSERT(isMainThread());
570     lazyInitialize();
571     return ConvolverNode::create(*this, m_destinationNode->sampleRate());
572 }
573
574 Ref<DynamicsCompressorNode> AudioContext::createDynamicsCompressor()
575 {
576     ASSERT(isMainThread());
577     lazyInitialize();
578     return DynamicsCompressorNode::create(*this, m_destinationNode->sampleRate());
579 }
580
581 Ref<AnalyserNode> AudioContext::createAnalyser()
582 {
583     ASSERT(isMainThread());
584     lazyInitialize();
585     return AnalyserNode::create(*this, m_destinationNode->sampleRate());
586 }
587
588 Ref<GainNode> AudioContext::createGain()
589 {
590     ASSERT(isMainThread());
591     lazyInitialize();
592     return GainNode::create(*this, m_destinationNode->sampleRate());
593 }
594
595 ExceptionOr<Ref<DelayNode>> AudioContext::createDelay(double maxDelayTime)
596 {
597     ASSERT(isMainThread());
598     lazyInitialize();
599     return DelayNode::create(*this, m_destinationNode->sampleRate(), maxDelayTime);
600 }
601
602 ExceptionOr<Ref<ChannelSplitterNode>> AudioContext::createChannelSplitter(size_t numberOfOutputs)
603 {
604     ASSERT(isMainThread());
605     lazyInitialize();
606     auto node = ChannelSplitterNode::create(*this, m_destinationNode->sampleRate(), numberOfOutputs);
607     if (!node)
608         return Exception { IndexSizeError };
609     return node.releaseNonNull();
610 }
611
612 ExceptionOr<Ref<ChannelMergerNode>> AudioContext::createChannelMerger(size_t numberOfInputs)
613 {
614     ASSERT(isMainThread());
615     lazyInitialize();
616     auto node = ChannelMergerNode::create(*this, m_destinationNode->sampleRate(), numberOfInputs);
617     if (!node)
618         return Exception { IndexSizeError };
619     return node.releaseNonNull();
620 }
621
622 Ref<OscillatorNode> AudioContext::createOscillator()
623 {
624     ASSERT(isMainThread());
625     lazyInitialize();
626
627     Ref<OscillatorNode> node = OscillatorNode::create(*this, m_destinationNode->sampleRate());
628
629     // Because this is an AudioScheduledSourceNode, the context keeps a reference until it has finished playing.
630     // When this happens, AudioScheduledSourceNode::finish() calls AudioContext::notifyNodeFinishedProcessing().
631     refNode(node);
632
633     return node;
634 }
635
636 ExceptionOr<Ref<PeriodicWave>> AudioContext::createPeriodicWave(Float32Array& real, Float32Array& imaginary)
637 {
638     ASSERT(isMainThread());
639     if (real.length() != imaginary.length() || (real.length() > MaxPeriodicWaveLength) || !real.length())
640         return Exception { IndexSizeError };
641     lazyInitialize();
642     return PeriodicWave::create(sampleRate(), real, imaginary);
643 }
644
645 void AudioContext::notifyNodeFinishedProcessing(AudioNode* node)
646 {
647     ASSERT(isAudioThread());
648     m_finishedNodes.append(node);
649 }
650
651 void AudioContext::derefFinishedSourceNodes()
652 {
653     ASSERT(isGraphOwner());
654     ASSERT(isAudioThread() || isAudioThreadFinished());
655     for (auto& node : m_finishedNodes)
656         derefNode(*node);
657
658     m_finishedNodes.clear();
659 }
660
661 void AudioContext::refNode(AudioNode& node)
662 {
663     ASSERT(isMainThread());
664     AutoLocker locker(*this);
665     
666     node.ref(AudioNode::RefTypeConnection);
667     m_referencedNodes.append(&node);
668 }
669
670 void AudioContext::derefNode(AudioNode& node)
671 {
672     ASSERT(isGraphOwner());
673     
674     node.deref(AudioNode::RefTypeConnection);
675
676     ASSERT(m_referencedNodes.contains(&node));
677     m_referencedNodes.removeFirst(&node);
678 }
679
680 void AudioContext::derefUnfinishedSourceNodes()
681 {
682     ASSERT(isMainThread() && isAudioThreadFinished());
683     for (auto& node : m_referencedNodes)
684         node->deref(AudioNode::RefTypeConnection);
685
686     m_referencedNodes.clear();
687 }
688
689 void AudioContext::lock(bool& mustReleaseLock)
690 {
691     // Don't allow regular lock in real-time audio thread.
692     ASSERT(isMainThread());
693
694     Thread& thisThread = Thread::current();
695
696     if (&thisThread == m_graphOwnerThread) {
697         // We already have the lock.
698         mustReleaseLock = false;
699     } else {
700         // Acquire the lock.
701         m_contextGraphMutex.lock();
702         m_graphOwnerThread = &thisThread;
703         mustReleaseLock = true;
704     }
705 }
706
707 bool AudioContext::tryLock(bool& mustReleaseLock)
708 {
709     Thread& thisThread = Thread::current();
710     bool isAudioThread = &thisThread == audioThread();
711
712     // Try to catch cases of using try lock on main thread - it should use regular lock.
713     ASSERT(isAudioThread || isAudioThreadFinished());
714     
715     if (!isAudioThread) {
716         // In release build treat tryLock() as lock() (since above ASSERT(isAudioThread) never fires) - this is the best we can do.
717         lock(mustReleaseLock);
718         return true;
719     }
720     
721     bool hasLock;
722     
723     if (&thisThread == m_graphOwnerThread) {
724         // Thread already has the lock.
725         hasLock = true;
726         mustReleaseLock = false;
727     } else {
728         // Don't already have the lock - try to acquire it.
729         hasLock = m_contextGraphMutex.tryLock();
730         
731         if (hasLock)
732             m_graphOwnerThread = &thisThread;
733
734         mustReleaseLock = hasLock;
735     }
736     
737     return hasLock;
738 }
739
740 void AudioContext::unlock()
741 {
742     ASSERT(m_graphOwnerThread == &Thread::current());
743
744     m_graphOwnerThread = nullptr;
745     m_contextGraphMutex.unlock();
746 }
747
748 bool AudioContext::isAudioThread() const
749 {
750     return m_audioThread == &Thread::current();
751 }
752
753 bool AudioContext::isGraphOwner() const
754 {
755     return m_graphOwnerThread == &Thread::current();
756 }
757
758 void AudioContext::addDeferredFinishDeref(AudioNode* node)
759 {
760     ASSERT(isAudioThread());
761     m_deferredFinishDerefList.append(node);
762 }
763
764 void AudioContext::handlePreRenderTasks()
765 {
766     ASSERT(isAudioThread());
767
768     // At the beginning of every render quantum, try to update the internal rendering graph state (from main thread changes).
769     // It's OK if the tryLock() fails, we'll just take slightly longer to pick up the changes.
770     bool mustReleaseLock;
771     if (tryLock(mustReleaseLock)) {
772         // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutputs.
773         handleDirtyAudioSummingJunctions();
774         handleDirtyAudioNodeOutputs();
775
776         updateAutomaticPullNodes();
777
778         if (mustReleaseLock)
779             unlock();
780     }
781 }
782
783 void AudioContext::handlePostRenderTasks()
784 {
785     ASSERT(isAudioThread());
786
787     // Must use a tryLock() here too. Don't worry, the lock will very rarely be contended and this method is called frequently.
788     // The worst that can happen is that there will be some nodes which will take slightly longer than usual to be deleted or removed
789     // from the render graph (in which case they'll render silence).
790     bool mustReleaseLock;
791     if (tryLock(mustReleaseLock)) {
792         // Take care of finishing any derefs where the tryLock() failed previously.
793         handleDeferredFinishDerefs();
794
795         // Dynamically clean up nodes which are no longer needed.
796         derefFinishedSourceNodes();
797
798         // Don't delete in the real-time thread. Let the main thread do it.
799         // Ref-counted objects held by certain AudioNodes may not be thread-safe.
800         scheduleNodeDeletion();
801
802         // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutputs.
803         handleDirtyAudioSummingJunctions();
804         handleDirtyAudioNodeOutputs();
805
806         updateAutomaticPullNodes();
807
808         if (mustReleaseLock)
809             unlock();
810     }
811 }
812
813 void AudioContext::handleDeferredFinishDerefs()
814 {
815     ASSERT(isAudioThread() && isGraphOwner());
816     for (auto& node : m_deferredFinishDerefList)
817         node->finishDeref(AudioNode::RefTypeConnection);
818     
819     m_deferredFinishDerefList.clear();
820 }
821
822 void AudioContext::markForDeletion(AudioNode* node)
823 {
824     ASSERT(isGraphOwner());
825
826     if (isAudioThreadFinished())
827         m_nodesToDelete.append(node);
828     else
829         m_nodesMarkedForDeletion.append(node);
830
831     // This is probably the best time for us to remove the node from automatic pull list,
832     // since all connections are gone and we hold the graph lock. Then when handlePostRenderTasks()
833     // gets a chance to schedule the deletion work, updateAutomaticPullNodes() also gets a chance to
834     // modify m_renderingAutomaticPullNodes.
835     removeAutomaticPullNode(node);
836 }
837
838 void AudioContext::scheduleNodeDeletion()
839 {
840     bool isGood = m_isInitialized && isGraphOwner();
841     ASSERT(isGood);
842     if (!isGood)
843         return;
844
845     // Make sure to call deleteMarkedNodes() on main thread.    
846     if (m_nodesMarkedForDeletion.size() && !m_isDeletionScheduled) {
847         m_nodesToDelete.appendVector(m_nodesMarkedForDeletion);
848         m_nodesMarkedForDeletion.clear();
849
850         m_isDeletionScheduled = true;
851
852         callOnMainThread([protectedThis = makeRef(*this)]() mutable {
853             protectedThis->deleteMarkedNodes();
854         });
855     }
856 }
857
858 void AudioContext::deleteMarkedNodes()
859 {
860     ASSERT(isMainThread());
861
862     // Protect this object from being deleted before we release the mutex locked by AutoLocker.
863     Ref<AudioContext> protectedThis(*this);
864     {
865         AutoLocker locker(*this);
866
867         while (m_nodesToDelete.size()) {
868             AudioNode* node = m_nodesToDelete.takeLast();
869
870             // Before deleting the node, clear out any AudioNodeInputs from m_dirtySummingJunctions.
871             unsigned numberOfInputs = node->numberOfInputs();
872             for (unsigned i = 0; i < numberOfInputs; ++i)
873                 m_dirtySummingJunctions.remove(node->input(i));
874
875             // Before deleting the node, clear out any AudioNodeOutputs from m_dirtyAudioNodeOutputs.
876             unsigned numberOfOutputs = node->numberOfOutputs();
877             for (unsigned i = 0; i < numberOfOutputs; ++i)
878                 m_dirtyAudioNodeOutputs.remove(node->output(i));
879
880             // Finally, delete it.
881             delete node;
882         }
883         m_isDeletionScheduled = false;
884     }
885 }
886
887 void AudioContext::markSummingJunctionDirty(AudioSummingJunction* summingJunction)
888 {
889     ASSERT(isGraphOwner());    
890     m_dirtySummingJunctions.add(summingJunction);
891 }
892
893 void AudioContext::removeMarkedSummingJunction(AudioSummingJunction* summingJunction)
894 {
895     ASSERT(isMainThread());
896     AutoLocker locker(*this);
897     m_dirtySummingJunctions.remove(summingJunction);
898 }
899
900 void AudioContext::markAudioNodeOutputDirty(AudioNodeOutput* output)
901 {
902     ASSERT(isGraphOwner());    
903     m_dirtyAudioNodeOutputs.add(output);
904 }
905
906 void AudioContext::handleDirtyAudioSummingJunctions()
907 {
908     ASSERT(isGraphOwner());    
909
910     for (auto& junction : m_dirtySummingJunctions)
911         junction->updateRenderingState();
912
913     m_dirtySummingJunctions.clear();
914 }
915
916 void AudioContext::handleDirtyAudioNodeOutputs()
917 {
918     ASSERT(isGraphOwner());    
919
920     for (auto& output : m_dirtyAudioNodeOutputs)
921         output->updateRenderingState();
922
923     m_dirtyAudioNodeOutputs.clear();
924 }
925
926 void AudioContext::addAutomaticPullNode(AudioNode* node)
927 {
928     ASSERT(isGraphOwner());
929
930     if (m_automaticPullNodes.add(node).isNewEntry)
931         m_automaticPullNodesNeedUpdating = true;
932 }
933
934 void AudioContext::removeAutomaticPullNode(AudioNode* node)
935 {
936     ASSERT(isGraphOwner());
937
938     if (m_automaticPullNodes.remove(node))
939         m_automaticPullNodesNeedUpdating = true;
940 }
941
942 void AudioContext::updateAutomaticPullNodes()
943 {
944     ASSERT(isGraphOwner());
945
946     if (m_automaticPullNodesNeedUpdating) {
947         // Copy from m_automaticPullNodes to m_renderingAutomaticPullNodes.
948         m_renderingAutomaticPullNodes.resize(m_automaticPullNodes.size());
949
950         unsigned i = 0;
951         for (auto& output : m_automaticPullNodes)
952             m_renderingAutomaticPullNodes[i++] = output;
953
954         m_automaticPullNodesNeedUpdating = false;
955     }
956 }
957
958 void AudioContext::processAutomaticPullNodes(size_t framesToProcess)
959 {
960     ASSERT(isAudioThread());
961
962     for (auto& node : m_renderingAutomaticPullNodes)
963         node->processIfNecessary(framesToProcess);
964 }
965
966 ScriptExecutionContext* AudioContext::scriptExecutionContext() const
967 {
968     return m_isStopScheduled ? 0 : ActiveDOMObject::scriptExecutionContext();
969 }
970
971 void AudioContext::nodeWillBeginPlayback()
972 {
973     // Called by scheduled AudioNodes when clients schedule their start times.
974     // Prior to the introduction of suspend(), resume(), and stop(), starting
975     // a scheduled AudioNode would remove the user-gesture restriction, if present,
976     // and would thus unmute the context. Now that AudioContext stays in the
977     // "suspended" state if a user-gesture restriction is present, starting a
978     // schedule AudioNode should set the state to "running", but only if the
979     // user-gesture restriction is set.
980     if (userGestureRequiredForAudioStart())
981         startRendering();
982 }
983
984 bool AudioContext::willBeginPlayback()
985 {
986     if (userGestureRequiredForAudioStart()) {
987         if (!processingUserGestureForMedia())
988             return false;
989         removeBehaviorRestriction(AudioContext::RequireUserGestureForAudioStartRestriction);
990     }
991
992     if (pageConsentRequiredForAudioStart()) {
993         Page* page = document()->page();
994         if (page && !page->canStartMedia()) {
995             document()->addMediaCanStartListener(this);
996             return false;
997         }
998         removeBehaviorRestriction(AudioContext::RequirePageConsentForAudioStartRestriction);
999     }
1000
1001     return m_mediaSession->clientWillBeginPlayback();
1002 }
1003
1004 bool AudioContext::willPausePlayback()
1005 {
1006     if (userGestureRequiredForAudioStart()) {
1007         if (!processingUserGestureForMedia())
1008             return false;
1009         removeBehaviorRestriction(AudioContext::RequireUserGestureForAudioStartRestriction);
1010     }
1011
1012     if (pageConsentRequiredForAudioStart()) {
1013         Page* page = document()->page();
1014         if (page && !page->canStartMedia()) {
1015             document()->addMediaCanStartListener(this);
1016             return false;
1017         }
1018         removeBehaviorRestriction(AudioContext::RequirePageConsentForAudioStartRestriction);
1019     }
1020     
1021     return m_mediaSession->clientWillPausePlayback();
1022 }
1023
1024 void AudioContext::startRendering()
1025 {
1026     if (!willBeginPlayback())
1027         return;
1028
1029     destination()->startRendering();
1030     setState(State::Running);
1031 }
1032
1033 void AudioContext::mediaCanStart(Document& document)
1034 {
1035     ASSERT_UNUSED(document, &document == this->document());
1036     removeBehaviorRestriction(AudioContext::RequirePageConsentForAudioStartRestriction);
1037     mayResumePlayback(true);
1038 }
1039
1040 MediaProducer::MediaStateFlags AudioContext::mediaState() const
1041 {
1042     if (!m_isStopScheduled && m_destinationNode && m_destinationNode->isPlayingAudio())
1043         return MediaProducer::IsPlayingAudio;
1044
1045     return MediaProducer::IsNotPlaying;
1046 }
1047
1048 void AudioContext::pageMutedStateDidChange()
1049 {
1050     if (m_destinationNode && document()->page())
1051         m_destinationNode->setMuted(document()->page()->isAudioMuted());
1052 }
1053
1054 void AudioContext::isPlayingAudioDidChange()
1055 {
1056     // Make sure to call Document::updateIsPlayingMedia() on the main thread, since
1057     // we could be on the audio I/O thread here and the call into WebCore could block.
1058     callOnMainThread([protectedThis = makeRef(*this)] {
1059         if (protectedThis->document())
1060             protectedThis->document()->updateIsPlayingMedia();
1061     });
1062 }
1063
1064 void AudioContext::fireCompletionEvent()
1065 {
1066     ASSERT(isMainThread());
1067     if (!isMainThread())
1068         return;
1069         
1070     AudioBuffer* renderedBuffer = m_renderTarget.get();
1071     setState(State::Closed);
1072
1073     ASSERT(renderedBuffer);
1074     if (!renderedBuffer)
1075         return;
1076
1077     // Avoid firing the event if the document has already gone away.
1078     if (scriptExecutionContext()) {
1079         // Call the offline rendering completion event listener.
1080         m_eventQueue->enqueueEvent(OfflineAudioCompletionEvent::create(renderedBuffer));
1081     }
1082 }
1083
1084 void AudioContext::incrementActiveSourceCount()
1085 {
1086     ++m_activeSourceCount;
1087 }
1088
1089 void AudioContext::decrementActiveSourceCount()
1090 {
1091     --m_activeSourceCount;
1092 }
1093
1094 void AudioContext::suspend(DOMPromiseDeferred<void>&& promise)
1095 {
1096     if (isOfflineContext()) {
1097         promise.reject(InvalidStateError);
1098         return;
1099     }
1100
1101     if (m_state == State::Suspended) {
1102         promise.resolve();
1103         return;
1104     }
1105
1106     if (m_state == State::Closed || m_state == State::Interrupted || !m_destinationNode) {
1107         promise.reject();
1108         return;
1109     }
1110
1111     addReaction(State::Suspended, WTFMove(promise));
1112
1113     if (!willPausePlayback())
1114         return;
1115
1116     lazyInitialize();
1117
1118     m_destinationNode->suspend([this, protectedThis = makeRef(*this)] {
1119         setState(State::Suspended);
1120     });
1121 }
1122
1123 void AudioContext::resume(DOMPromiseDeferred<void>&& promise)
1124 {
1125     if (isOfflineContext()) {
1126         promise.reject(InvalidStateError);
1127         return;
1128     }
1129
1130     if (m_state == State::Running) {
1131         promise.resolve();
1132         return;
1133     }
1134
1135     if (m_state == State::Closed || !m_destinationNode) {
1136         promise.reject();
1137         return;
1138     }
1139
1140     addReaction(State::Running, WTFMove(promise));
1141
1142     if (!willBeginPlayback())
1143         return;
1144
1145     lazyInitialize();
1146
1147     m_destinationNode->resume([this, protectedThis = makeRef(*this)] {
1148         setState(State::Running);
1149     });
1150 }
1151
1152 void AudioContext::close(DOMPromiseDeferred<void>&& promise)
1153 {
1154     if (isOfflineContext()) {
1155         promise.reject(InvalidStateError);
1156         return;
1157     }
1158
1159     if (m_state == State::Closed || !m_destinationNode) {
1160         promise.resolve();
1161         return;
1162     }
1163
1164     addReaction(State::Closed, WTFMove(promise));
1165
1166     lazyInitialize();
1167
1168     m_destinationNode->close([this, protectedThis = makeRef(*this)] {
1169         setState(State::Closed);
1170         uninitialize();
1171     });
1172 }
1173
1174
1175 void AudioContext::suspendPlayback()
1176 {
1177     if (!m_destinationNode || m_state == State::Closed)
1178         return;
1179
1180     if (m_state == State::Suspended) {
1181         if (m_mediaSession->state() == PlatformMediaSession::Interrupted)
1182             setState(State::Interrupted);
1183         return;
1184     }
1185
1186     lazyInitialize();
1187
1188     m_destinationNode->suspend([this, protectedThis = makeRef(*this)] {
1189         bool interrupted = m_mediaSession->state() == PlatformMediaSession::Interrupted;
1190         setState(interrupted ? State::Interrupted : State::Suspended);
1191     });
1192 }
1193
1194 void AudioContext::mayResumePlayback(bool shouldResume)
1195 {
1196     if (!m_destinationNode || m_state == State::Closed || m_state == State::Running)
1197         return;
1198
1199     if (!shouldResume) {
1200         setState(State::Suspended);
1201         return;
1202     }
1203
1204     if (!willBeginPlayback())
1205         return;
1206
1207     lazyInitialize();
1208
1209     m_destinationNode->resume([this, protectedThis = makeRef(*this)] {
1210         setState(State::Running);
1211     });
1212 }
1213
1214
1215 } // namespace WebCore
1216
1217 #endif // ENABLE(WEB_AUDIO)