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