Remove excessive headers from WebCore/{Modules,animation,crypto,domjit}
[WebKit-https.git] / Source / WebCore / Modules / webaudio / AudioContext.h
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 #pragma once
27
28 #include "ActiveDOMObject.h"
29 #include "AsyncAudioDecoder.h"
30 #include "AudioBus.h"
31 #include "AudioDestinationNode.h"
32 #include "EventTarget.h"
33 #include "JSDOMPromiseDeferred.h"
34 #include "MediaCanStartListener.h"
35 #include "MediaProducer.h"
36 #include "PlatformMediaSession.h"
37 #include "VisibilityChangeClient.h"
38 #include <atomic>
39 #include <wtf/HashSet.h>
40 #include <wtf/MainThread.h>
41 #include <wtf/RefPtr.h>
42 #include <wtf/ThreadSafeRefCounted.h>
43 #include <wtf/Threading.h>
44 #include <wtf/Vector.h>
45 #include <wtf/text/AtomicStringHash.h>
46
47 namespace WebCore {
48
49 class AnalyserNode;
50 class AudioBuffer;
51 class AudioBufferCallback;
52 class AudioBufferSourceNode;
53 class AudioListener;
54 class AudioSummingJunction;
55 class BiquadFilterNode;
56 class ChannelMergerNode;
57 class ChannelSplitterNode;
58 class ConvolverNode;
59 class DelayNode;
60 class Document;
61 class DynamicsCompressorNode;
62 class GainNode;
63 class GenericEventQueue;
64 class HTMLMediaElement;
65 class MediaElementAudioSourceNode;
66 class MediaStream;
67 class MediaStreamAudioDestinationNode;
68 class MediaStreamAudioSourceNode;
69 class OscillatorNode;
70 class PannerNode;
71 class PeriodicWave;
72 class ScriptProcessorNode;
73 class WaveShaperNode;
74
75 // AudioContext is the cornerstone of the web audio API and all AudioNodes are created from it.
76 // For thread safety between the audio thread and the main thread, it has a rendering graph locking mechanism. 
77
78 class AudioContext : public ActiveDOMObject, public ThreadSafeRefCounted<AudioContext>, public EventTargetWithInlineData, public MediaCanStartListener, public MediaProducer, private PlatformMediaSessionClient, private VisibilityChangeClient {
79 public:
80     // Create an AudioContext for rendering to the audio hardware.
81     static RefPtr<AudioContext> create(Document&);
82
83     virtual ~AudioContext();
84
85     bool isInitialized() const;
86     
87     bool isOfflineContext() { return m_isOfflineContext; }
88
89     Document* document() const; // ASSERTs if document no longer exists.
90
91     const Document* hostingDocument() const override;
92
93     AudioDestinationNode* destination() { return m_destinationNode.get(); }
94     size_t currentSampleFrame() const { return m_destinationNode->currentSampleFrame(); }
95     double currentTime() const { return m_destinationNode->currentTime(); }
96     float sampleRate() const { return m_destinationNode->sampleRate(); }
97     unsigned long activeSourceCount() const { return static_cast<unsigned long>(m_activeSourceCount); }
98
99     void incrementActiveSourceCount();
100     void decrementActiveSourceCount();
101     
102     ExceptionOr<Ref<AudioBuffer>> createBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate);
103     ExceptionOr<Ref<AudioBuffer>> createBuffer(ArrayBuffer&, bool mixToMono);
104
105     // Asynchronous audio file data decoding.
106     void decodeAudioData(Ref<ArrayBuffer>&&, RefPtr<AudioBufferCallback>&&, RefPtr<AudioBufferCallback>&&);
107
108     AudioListener* listener() { return m_listener.get(); }
109
110     using ActiveDOMObject::suspend;
111     using ActiveDOMObject::resume;
112
113     void suspend(DOMPromiseDeferred<void>&&);
114     void resume(DOMPromiseDeferred<void>&&);
115     void close(DOMPromiseDeferred<void>&&);
116
117     enum class State { Suspended, Running, Interrupted, Closed };
118     State state() const;
119
120     // The AudioNode create methods are called on the main thread (from JavaScript).
121     Ref<AudioBufferSourceNode> createBufferSource();
122 #if ENABLE(VIDEO)
123     ExceptionOr<Ref<MediaElementAudioSourceNode>> createMediaElementSource(HTMLMediaElement&);
124 #endif
125 #if ENABLE(MEDIA_STREAM)
126     ExceptionOr<Ref<MediaStreamAudioSourceNode>> createMediaStreamSource(MediaStream&);
127     Ref<MediaStreamAudioDestinationNode> createMediaStreamDestination();
128 #endif
129     Ref<GainNode> createGain();
130     Ref<BiquadFilterNode> createBiquadFilter();
131     Ref<WaveShaperNode> createWaveShaper();
132     ExceptionOr<Ref<DelayNode>> createDelay(double maxDelayTime);
133     Ref<PannerNode> createPanner();
134     Ref<ConvolverNode> createConvolver();
135     Ref<DynamicsCompressorNode> createDynamicsCompressor();
136     Ref<AnalyserNode> createAnalyser();
137     ExceptionOr<Ref<ScriptProcessorNode>> createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, size_t numberOfOutputChannels);
138     ExceptionOr<Ref<ChannelSplitterNode>> createChannelSplitter(size_t numberOfOutputs);
139     ExceptionOr<Ref<ChannelMergerNode>> createChannelMerger(size_t numberOfInputs);
140     Ref<OscillatorNode> createOscillator();
141     ExceptionOr<Ref<PeriodicWave>> createPeriodicWave(Float32Array& real, Float32Array& imaginary);
142
143     // When a source node has no more processing to do (has finished playing), then it tells the context to dereference it.
144     void notifyNodeFinishedProcessing(AudioNode*);
145
146     // Called at the start of each render quantum.
147     void handlePreRenderTasks();
148
149     // Called at the end of each render quantum.
150     void handlePostRenderTasks();
151
152     // Called periodically at the end of each render quantum to dereference finished source nodes.
153     void derefFinishedSourceNodes();
154
155     // We schedule deletion of all marked nodes at the end of each realtime render quantum.
156     void markForDeletion(AudioNode*);
157     void deleteMarkedNodes();
158
159     // AudioContext can pull node(s) at the end of each render quantum even when they are not connected to any downstream nodes.
160     // These two methods are called by the nodes who want to add/remove themselves into/from the automatic pull lists.
161     void addAutomaticPullNode(AudioNode*);
162     void removeAutomaticPullNode(AudioNode*);
163
164     // Called right before handlePostRenderTasks() to handle nodes which need to be pulled even when they are not connected to anything.
165     void processAutomaticPullNodes(size_t framesToProcess);
166
167     // Keeps track of the number of connections made.
168     void incrementConnectionCount()
169     {
170         ASSERT(isMainThread());
171         m_connectionCount++;
172     }
173
174     unsigned connectionCount() const { return m_connectionCount; }
175
176     //
177     // Thread Safety and Graph Locking:
178     //
179     
180     void setAudioThread(ThreadIdentifier thread) { m_audioThread = thread; } // FIXME: check either not initialized or the same
181     ThreadIdentifier audioThread() const { return m_audioThread; }
182     bool isAudioThread() const;
183
184     // Returns true only after the audio thread has been started and then shutdown.
185     bool isAudioThreadFinished() { return m_isAudioThreadFinished; }
186     
187     // mustReleaseLock is set to true if we acquired the lock in this method call and caller must unlock(), false if it was previously acquired.
188     void lock(bool& mustReleaseLock);
189
190     // Returns true if we own the lock.
191     // mustReleaseLock is set to true if we acquired the lock in this method call and caller must unlock(), false if it was previously acquired.
192     bool tryLock(bool& mustReleaseLock);
193
194     void unlock();
195
196     // Returns true if this thread owns the context's lock.
197     bool isGraphOwner() const;
198
199     // Returns the maximum number of channels we can support.
200     static unsigned maxNumberOfChannels() { return MaxNumberOfChannels; }
201
202     class AutoLocker {
203     public:
204         explicit AutoLocker(AudioContext& context)
205             : m_context(context)
206         {
207             m_context.lock(m_mustReleaseLock);
208         }
209         
210         ~AutoLocker()
211         {
212             if (m_mustReleaseLock)
213                 m_context.unlock();
214         }
215
216     private:
217         AudioContext& m_context;
218         bool m_mustReleaseLock;
219     };
220     
221     // In AudioNode::deref() a tryLock() is used for calling finishDeref(), but if it fails keep track here.
222     void addDeferredFinishDeref(AudioNode*);
223
224     // In the audio thread at the start of each render cycle, we'll call handleDeferredFinishDerefs().
225     void handleDeferredFinishDerefs();
226
227     // Only accessed when the graph lock is held.
228     void markSummingJunctionDirty(AudioSummingJunction*);
229     void markAudioNodeOutputDirty(AudioNodeOutput*);
230
231     // Must be called on main thread.
232     void removeMarkedSummingJunction(AudioSummingJunction*);
233
234     // EventTarget
235     EventTargetInterface eventTargetInterface() const final { return AudioContextEventTargetInterfaceType; }
236     ScriptExecutionContext* scriptExecutionContext() const final;
237
238     // Reconcile ref/deref which are defined both in ThreadSafeRefCounted and EventTarget.
239     using ThreadSafeRefCounted::ref;
240     using ThreadSafeRefCounted::deref;
241
242     void startRendering();
243     void fireCompletionEvent();
244     
245     static unsigned s_hardwareContextCount;
246
247     // Restrictions to change default behaviors.
248     enum BehaviorRestrictionFlags {
249         NoRestrictions = 0,
250         RequireUserGestureForAudioStartRestriction = 1 << 0,
251         RequirePageConsentForAudioStartRestriction = 1 << 1,
252     };
253     typedef unsigned BehaviorRestrictions;
254
255     BehaviorRestrictions behaviorRestrictions() const { return m_restrictions; }
256     void addBehaviorRestriction(BehaviorRestrictions restriction) { m_restrictions |= restriction; }
257     void removeBehaviorRestriction(BehaviorRestrictions restriction) { m_restrictions &= ~restriction; }
258
259     void isPlayingAudioDidChange();
260
261     void nodeWillBeginPlayback();
262
263 protected:
264     explicit AudioContext(Document&);
265     AudioContext(Document&, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate);
266     
267     static bool isSampleRateRangeGood(float sampleRate);
268     
269 private:
270     void constructCommon();
271
272     void lazyInitialize();
273     void uninitialize();
274
275     bool willBeginPlayback();
276     bool willPausePlayback();
277
278     bool userGestureRequiredForAudioStart() const { return m_restrictions & RequireUserGestureForAudioStartRestriction; }
279     bool pageConsentRequiredForAudioStart() const { return m_restrictions & RequirePageConsentForAudioStartRestriction; }
280
281     void setState(State);
282
283     void clear();
284
285     void scheduleNodeDeletion();
286
287     void mediaCanStart(Document&) override;
288
289     // MediaProducer
290     MediaProducer::MediaStateFlags mediaState() const override;
291     void pageMutedStateDidChange() override;
292
293     // The context itself keeps a reference to all source nodes.  The source nodes, then reference all nodes they're connected to.
294     // In turn, these nodes reference all nodes they're connected to.  All nodes are ultimately connected to the AudioDestinationNode.
295     // When the context dereferences a source node, it will be deactivated from the rendering graph along with all other nodes it is
296     // uniquely connected to.  See the AudioNode::ref() and AudioNode::deref() methods for more details.
297     void refNode(AudioNode&);
298     void derefNode(AudioNode&);
299
300     // ActiveDOMObject API.
301     void stop() override;
302     bool canSuspendForDocumentSuspension() const override;
303     const char* activeDOMObjectName() const override;
304
305     // When the context goes away, there might still be some sources which haven't finished playing.
306     // Make sure to dereference them here.
307     void derefUnfinishedSourceNodes();
308
309     // PlatformMediaSessionClient
310     PlatformMediaSession::MediaType mediaType() const override { return PlatformMediaSession::WebAudio; }
311     PlatformMediaSession::MediaType presentationType() const override { return PlatformMediaSession::WebAudio; }
312     PlatformMediaSession::CharacteristicsFlags characteristics() const override { return m_state == State::Running ? PlatformMediaSession::HasAudio : PlatformMediaSession::HasNothing; }
313     void mayResumePlayback(bool shouldResume) override;
314     void suspendPlayback() override;
315     bool canReceiveRemoteControlCommands() const override { return false; }
316     void didReceiveRemoteControlCommand(PlatformMediaSession::RemoteControlCommandType, const PlatformMediaSession::RemoteCommandArgument*) override { }
317     bool supportsSeeking() const override { return false; }
318     bool shouldOverrideBackgroundPlaybackRestriction(PlatformMediaSession::InterruptionType) const override { return false; }
319     String sourceApplicationIdentifier() const override;
320     bool canProduceAudio() const final { return true; }
321     bool isSuspended() const final;
322     bool processingUserGestureForMedia() const final;
323
324     void visibilityStateChanged() final;
325
326     // EventTarget
327     void refEventTarget() override { ref(); }
328     void derefEventTarget() override { deref(); }
329
330     void handleDirtyAudioSummingJunctions();
331     void handleDirtyAudioNodeOutputs();
332
333     void addReaction(State, DOMPromiseDeferred<void>&&);
334     void updateAutomaticPullNodes();
335
336     // Only accessed in the audio thread.
337     Vector<AudioNode*> m_finishedNodes;
338
339     // We don't use RefPtr<AudioNode> here because AudioNode has a more complex ref() / deref() implementation
340     // with an optional argument for refType.  We need to use the special refType: RefTypeConnection
341     // Either accessed when the graph lock is held, or on the main thread when the audio thread has finished.
342     Vector<AudioNode*> m_referencedNodes;
343
344     // Accumulate nodes which need to be deleted here.
345     // This is copied to m_nodesToDelete at the end of a render cycle in handlePostRenderTasks(), where we're assured of a stable graph
346     // state which will have no references to any of the nodes in m_nodesToDelete once the context lock is released
347     // (when handlePostRenderTasks() has completed).
348     Vector<AudioNode*> m_nodesMarkedForDeletion;
349
350     // They will be scheduled for deletion (on the main thread) at the end of a render cycle (in realtime thread).
351     Vector<AudioNode*> m_nodesToDelete;
352
353     bool m_isDeletionScheduled { false };
354     bool m_isStopScheduled { false };
355     bool m_isInitialized { false };
356     bool m_isAudioThreadFinished { false };
357     bool m_automaticPullNodesNeedUpdating { false };
358     bool m_isOfflineContext { false };
359
360     // Only accessed when the graph lock is held.
361     HashSet<AudioSummingJunction*> m_dirtySummingJunctions;
362     HashSet<AudioNodeOutput*> m_dirtyAudioNodeOutputs;
363
364     // For the sake of thread safety, we maintain a seperate Vector of automatic pull nodes for rendering in m_renderingAutomaticPullNodes.
365     // It will be copied from m_automaticPullNodes by updateAutomaticPullNodes() at the very start or end of the rendering quantum.
366     HashSet<AudioNode*> m_automaticPullNodes;
367     Vector<AudioNode*> m_renderingAutomaticPullNodes;
368     // Only accessed in the audio thread.
369     Vector<AudioNode*> m_deferredFinishDerefList;
370     Vector<Vector<DOMPromiseDeferred<void>>> m_stateReactions;
371
372     std::unique_ptr<PlatformMediaSession> m_mediaSession;
373     std::unique_ptr<GenericEventQueue> m_eventQueue;
374
375     RefPtr<AudioBuffer> m_renderTarget;
376     RefPtr<AudioDestinationNode> m_destinationNode;
377     RefPtr<AudioListener> m_listener;
378
379     unsigned m_connectionCount { 0 };
380
381     // Graph locking.
382     Lock m_contextGraphMutex;
383     volatile ThreadIdentifier m_audioThread { 0 };
384     volatile ThreadIdentifier m_graphOwnerThread; // if the lock is held then this is the thread which owns it, otherwise == UndefinedThreadIdentifier
385
386     AsyncAudioDecoder m_audioDecoder;
387
388     // This is considering 32 is large enough for multiple channels audio. 
389     // It is somewhat arbitrary and could be increased if necessary.
390     enum { MaxNumberOfChannels = 32 };
391
392     // Number of AudioBufferSourceNodes that are active (playing).
393     std::atomic<int> m_activeSourceCount { 0 };
394
395     BehaviorRestrictions m_restrictions { NoRestrictions };
396
397     State m_state { State::Suspended };
398 };
399
400 // FIXME: Find out why these ==/!= functions are needed and remove them if possible.
401
402 inline bool operator==(const AudioContext& lhs, const AudioContext& rhs)
403 {
404     return &lhs == &rhs;
405 }
406
407 inline bool operator!=(const AudioContext& lhs, const AudioContext& rhs)
408 {
409     return &lhs != &rhs;
410 }
411
412 inline AudioContext::State AudioContext::state() const
413 {
414     return m_state;
415 }
416
417 } // WebCore