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