Add stub implementation for MediaStreamAudioSourceNode
[WebKit-https.git] / Source / WebCore / Modules / webaudio / AudioContext.h
1 /*
2  * Copyright (C) 2010, Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #ifndef AudioContext_h
26 #define AudioContext_h
27
28 #include "ActiveDOMObject.h"
29 #include "AsyncAudioDecoder.h"
30 #include "AudioBus.h"
31 #include "AudioDestinationNode.h"
32 #include "EventListener.h"
33 #include "EventTarget.h"
34 #include "HRTFDatabaseLoader.h"
35 #include <wtf/HashSet.h>
36 #include <wtf/MainThread.h>
37 #include <wtf/OwnPtr.h>
38 #include <wtf/PassRefPtr.h>
39 #include <wtf/RefCounted.h>
40 #include <wtf/RefPtr.h>
41 #include <wtf/ThreadSafeRefCounted.h>
42 #include <wtf/Threading.h>
43 #include <wtf/Vector.h>
44 #include <wtf/text/AtomicStringHash.h>
45
46 namespace WebCore {
47
48 class AudioBuffer;
49 class AudioBufferCallback;
50 class AudioBufferSourceNode;
51 class MediaElementAudioSourceNode;
52 class MediaStreamAudioSourceNode;
53 class HTMLMediaElement;
54 class AudioChannelMerger;
55 class AudioChannelSplitter;
56 class AudioGainNode;
57 class AudioPannerNode;
58 class AudioListener;
59 class AudioSummingJunction;
60 class BiquadFilterNode;
61 class DelayNode;
62 class Document;
63 class ConvolverNode;
64 class DynamicsCompressorNode;
65 class RealtimeAnalyserNode;
66 class WaveShaperNode;
67 class JavaScriptAudioNode;
68 class Oscillator;
69 class WaveTable;
70
71 // AudioContext is the cornerstone of the web audio API and all AudioNodes are created from it.
72 // For thread safety between the audio thread and the main thread, it has a rendering graph locking mechanism. 
73
74 class AudioContext : public ActiveDOMObject, public ThreadSafeRefCounted<AudioContext>, public EventTarget {
75 public:
76     // Create an AudioContext for rendering to the audio hardware.
77     static PassRefPtr<AudioContext> create(Document*, ExceptionCode&);
78
79     // Create an AudioContext for offline (non-realtime) rendering.
80     static PassRefPtr<AudioContext> createOfflineContext(Document*, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionCode&);
81
82     virtual ~AudioContext();
83
84     bool isInitialized() const;
85     
86     bool isOfflineContext() { return m_isOfflineContext; }
87
88     // Returns true when initialize() was called AND all asynchronous initialization has completed.
89     bool isRunnable() const;
90
91     // Document notification
92     virtual void stop();
93
94     Document* document() const; // ASSERTs if document no longer exists.
95     bool hasDocument();
96
97     AudioDestinationNode* destination() { return m_destinationNode.get(); }
98     size_t currentSampleFrame() const { return m_destinationNode->currentSampleFrame(); }
99     double currentTime() const { return m_destinationNode->currentTime(); }
100     float sampleRate() const { return m_destinationNode->sampleRate(); }
101     unsigned long activeSourceCount() const { return static_cast<unsigned long>(m_activeSourceCount); }
102
103     void incrementActiveSourceCount();
104     void decrementActiveSourceCount();
105     
106     PassRefPtr<AudioBuffer> createBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionCode&);
107     PassRefPtr<AudioBuffer> createBuffer(ArrayBuffer*, bool mixToMono, ExceptionCode&);
108
109     // Asynchronous audio file data decoding.
110     void decodeAudioData(ArrayBuffer*, PassRefPtr<AudioBufferCallback>, PassRefPtr<AudioBufferCallback>, ExceptionCode& ec);
111
112     AudioListener* listener() { return m_listener.get(); }
113
114     // The AudioNode create methods are called on the main thread (from JavaScript).
115     PassRefPtr<AudioBufferSourceNode> createBufferSource();
116 #if ENABLE(VIDEO)
117     PassRefPtr<MediaElementAudioSourceNode> createMediaElementSource(HTMLMediaElement*, ExceptionCode&);
118 #endif
119 #if ENABLE(MEDIA_STREAM)
120     PassRefPtr<MediaStreamAudioSourceNode> createMediaStreamSource(MediaStream*, ExceptionCode&);
121 #endif
122     PassRefPtr<AudioGainNode> createGainNode();
123     PassRefPtr<BiquadFilterNode> createBiquadFilter();
124     PassRefPtr<WaveShaperNode> createWaveShaper();
125     PassRefPtr<DelayNode> createDelayNode();
126     PassRefPtr<DelayNode> createDelayNode(double maxDelayTime);
127     PassRefPtr<AudioPannerNode> createPanner();
128     PassRefPtr<ConvolverNode> createConvolver();
129     PassRefPtr<DynamicsCompressorNode> createDynamicsCompressor();    
130     PassRefPtr<RealtimeAnalyserNode> createAnalyser();
131     PassRefPtr<JavaScriptAudioNode> createJavaScriptNode(size_t bufferSize, ExceptionCode&);
132     PassRefPtr<JavaScriptAudioNode> createJavaScriptNode(size_t bufferSize, size_t numberOfInputChannels, ExceptionCode&);
133     PassRefPtr<JavaScriptAudioNode> createJavaScriptNode(size_t bufferSize, size_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionCode&);
134     PassRefPtr<AudioChannelSplitter> createChannelSplitter(ExceptionCode&);
135     PassRefPtr<AudioChannelSplitter> createChannelSplitter(size_t numberOfOutputs, ExceptionCode&);
136     PassRefPtr<AudioChannelMerger> createChannelMerger(ExceptionCode&);
137     PassRefPtr<AudioChannelMerger> createChannelMerger(size_t numberOfInputs, ExceptionCode&);
138     PassRefPtr<Oscillator> createOscillator();
139     PassRefPtr<WaveTable> createWaveTable(Float32Array* real, Float32Array* imag, ExceptionCode&);
140
141     // When a source node has no more processing to do (has finished playing), then it tells the context to dereference it.
142     void notifyNodeFinishedProcessing(AudioNode*);
143
144     // Called at the start of each render quantum.
145     void handlePreRenderTasks();
146
147     // Called at the end of each render quantum.
148     void handlePostRenderTasks();
149
150     // Called periodically at the end of each render quantum to dereference finished source nodes.
151     void derefFinishedSourceNodes();
152
153     // We schedule deletion of all marked nodes at the end of each realtime render quantum.
154     void markForDeletion(AudioNode*);
155     void deleteMarkedNodes();
156
157     // AudioContext can pull node(s) at the end of each render quantum even when they are not connected to any downstream nodes.
158     // These two methods are called by the nodes who want to add/remove themselves into/from the automatic pull lists.
159     void addAutomaticPullNode(AudioNode*);
160     void removeAutomaticPullNode(AudioNode*);
161
162     // Called right before handlePostRenderTasks() to handle nodes which need to be pulled even when they are not connected to anything.
163     void processAutomaticPullNodes(size_t framesToProcess);
164
165     // Keeps track of the number of connections made.
166     void incrementConnectionCount()
167     {
168         ASSERT(isMainThread());
169         m_connectionCount++;
170     }
171
172     unsigned connectionCount() const { return m_connectionCount; }
173
174     //
175     // Thread Safety and Graph Locking:
176     //
177     
178     void setAudioThread(ThreadIdentifier thread) { m_audioThread = thread; } // FIXME: check either not initialized or the same
179     ThreadIdentifier audioThread() const { return m_audioThread; }
180     bool isAudioThread() const;
181
182     // Returns true only after the audio thread has been started and then shutdown.
183     bool isAudioThreadFinished() { return m_isAudioThreadFinished; }
184     
185     // mustReleaseLock is set to true if we acquired the lock in this method call and caller must unlock(), false if it was previously acquired.
186     void lock(bool& mustReleaseLock);
187
188     // Returns true if we own the lock.
189     // mustReleaseLock is set to true if we acquired the lock in this method call and caller must unlock(), false if it was previously acquired.
190     bool tryLock(bool& mustReleaseLock);
191
192     void unlock();
193
194     // Returns true if this thread owns the context's lock.
195     bool isGraphOwner() const;
196
197     // Returns the maximum numuber of channels we can support.
198     static unsigned maxNumberOfChannels() { return MaxNumberOfChannels;}
199
200     class AutoLocker {
201     public:
202         AutoLocker(AudioContext* context)
203             : m_context(context)
204         {
205             ASSERT(context);
206             context->lock(m_mustReleaseLock);
207         }
208         
209         ~AutoLocker()
210         {
211             if (m_mustReleaseLock)
212                 m_context->unlock();
213         }
214     private:
215         AudioContext* m_context;
216         bool m_mustReleaseLock;
217     };
218     
219     // In AudioNode::deref() a tryLock() is used for calling finishDeref(), but if it fails keep track here.
220     void addDeferredFinishDeref(AudioNode*);
221
222     // In the audio thread at the start of each render cycle, we'll call handleDeferredFinishDerefs().
223     void handleDeferredFinishDerefs();
224
225     // Only accessed when the graph lock is held.
226     void markSummingJunctionDirty(AudioSummingJunction*);
227     void markAudioNodeOutputDirty(AudioNodeOutput*);
228
229     // Must be called on main thread.
230     void removeMarkedSummingJunction(AudioSummingJunction*);
231
232     // EventTarget
233     virtual const AtomicString& interfaceName() const;
234     virtual ScriptExecutionContext* scriptExecutionContext() const;
235     virtual EventTargetData* eventTargetData() { return &m_eventTargetData; }
236     virtual EventTargetData* ensureEventTargetData() { return &m_eventTargetData; }
237
238     DEFINE_ATTRIBUTE_EVENT_LISTENER(complete);
239
240     // Reconcile ref/deref which are defined both in ThreadSafeRefCounted and EventTarget.
241     using ThreadSafeRefCounted<AudioContext>::ref;
242     using ThreadSafeRefCounted<AudioContext>::deref;
243
244     void startRendering();
245     void fireCompletionEvent();
246     
247     static unsigned s_hardwareContextCount;
248     
249 private:
250     explicit AudioContext(Document*);
251     AudioContext(Document*, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate);
252     void constructCommon();
253
254     void lazyInitialize();
255     void uninitialize();
256     static void uninitializeDispatch(void* userData);
257
258     void scheduleNodeDeletion();
259     static void deleteMarkedNodesDispatch(void* userData);
260     
261     bool m_isInitialized;
262     bool m_isAudioThreadFinished;
263
264     Document* m_document;
265
266     // The context itself keeps a reference to all source nodes.  The source nodes, then reference all nodes they're connected to.
267     // In turn, these nodes reference all nodes they're connected to.  All nodes are ultimately connected to the AudioDestinationNode.
268     // When the context dereferences a source node, it will be deactivated from the rendering graph along with all other nodes it is
269     // uniquely connected to.  See the AudioNode::ref() and AudioNode::deref() methods for more details.
270     void refNode(AudioNode*);
271     void derefNode(AudioNode*);
272
273     // When the context goes away, there might still be some sources which haven't finished playing.
274     // Make sure to dereference them here.
275     void derefUnfinishedSourceNodes();
276
277     RefPtr<AudioDestinationNode> m_destinationNode;
278     RefPtr<AudioListener> m_listener;
279
280     // Only accessed in the audio thread.
281     Vector<AudioNode*> m_finishedNodes;
282
283     // We don't use RefPtr<AudioNode> here because AudioNode has a more complex ref() / deref() implementation
284     // with an optional argument for refType.  We need to use the special refType: RefTypeConnection
285     // Either accessed when the graph lock is held, or on the main thread when the audio thread has finished.
286     Vector<AudioNode*> m_referencedNodes;
287
288     // Accumulate nodes which need to be deleted here.
289     // They will be scheduled for deletion (on the main thread) at the end of a render cycle (in realtime thread).
290     Vector<AudioNode*> m_nodesToDelete;
291     bool m_isDeletionScheduled;
292
293     // Only accessed when the graph lock is held.
294     HashSet<AudioSummingJunction*> m_dirtySummingJunctions;
295     HashSet<AudioNodeOutput*> m_dirtyAudioNodeOutputs;
296     void handleDirtyAudioSummingJunctions();
297     void handleDirtyAudioNodeOutputs();
298
299     // For the sake of thread safety, we maintain a seperate Vector of automatic pull nodes for rendering in m_renderingAutomaticPullNodes.
300     // It will be copied from m_automaticPullNodes by updateAutomaticPullNodes() at the very start or end of the rendering quantum.
301     HashSet<AudioNode*> m_automaticPullNodes;
302     Vector<AudioNode*> m_renderingAutomaticPullNodes;
303     // m_automaticPullNodesNeedUpdating keeps track if m_automaticPullNodes is modified.
304     bool m_automaticPullNodesNeedUpdating;
305     void updateAutomaticPullNodes();
306
307     unsigned m_connectionCount;
308
309     // Graph locking.
310     Mutex m_contextGraphMutex;
311     volatile ThreadIdentifier m_audioThread;
312     volatile ThreadIdentifier m_graphOwnerThread; // if the lock is held then this is the thread which owns it, otherwise == UndefinedThreadIdentifier
313     
314     // Only accessed in the audio thread.
315     Vector<AudioNode*> m_deferredFinishDerefList;
316     
317     // HRTF Database loader
318     RefPtr<HRTFDatabaseLoader> m_hrtfDatabaseLoader;
319
320     // EventTarget
321     virtual void refEventTarget() { ref(); }
322     virtual void derefEventTarget() { deref(); }
323     EventTargetData m_eventTargetData;
324
325     RefPtr<AudioBuffer> m_renderTarget;
326     
327     bool m_isOfflineContext;
328
329     AsyncAudioDecoder m_audioDecoder;
330
331     // This is considering 32 is large enough for multiple channels audio. 
332     // It is somewhat arbitrary and could be increased if necessary.
333     enum { MaxNumberOfChannels = 32 };
334
335     // Number of AudioBufferSourceNodes that are active (playing).
336     int m_activeSourceCount;
337 };
338
339 } // WebCore
340
341 #endif // AudioContext_h