1bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen/* 2a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) 2010, Google Inc. All rights reserved. 3bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * 4bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * Redistribution and use in source and binary forms, with or without 5bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * modification, are permitted provided that the following conditions 6bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * are met: 7bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * 1. Redistributions of source code must retain the above copyright 8a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * notice, this list of conditions and the following disclaimer. 9bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * 2. Redistributions in binary form must reproduce the above copyright 10a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * notice, this list of conditions and the following disclaimer in the 11a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * documentation and/or other materials provided with the distribution. 12bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * 13a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 14bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 17bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen */ 24bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 25bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#ifndef AudioContext_h 26bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#define AudioContext_h 27bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 28bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "ActiveDOMObject.h" 29bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "AudioBus.h" 30bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "AudioDestinationNode.h" 312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "EventListener.h" 322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "EventTarget.h" 33a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "HRTFDatabaseLoader.h" 34e14391e94c850b8bd03680c23b38978db68687a8John Reck#include <wtf/HashSet.h> 35bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include <wtf/OwnPtr.h> 36bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include <wtf/PassRefPtr.h> 37bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include <wtf/RefCounted.h> 38bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include <wtf/RefPtr.h> 39bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include <wtf/Threading.h> 40bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include <wtf/Vector.h> 41bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include <wtf/text/AtomicStringHash.h> 42bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 43bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsennamespace WebCore { 44bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 45f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochclass ArrayBuffer; 46bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenclass AudioBuffer; 47bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenclass AudioBufferSourceNode; 48bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenclass AudioChannelMerger; 49bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenclass AudioChannelSplitter; 50bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenclass AudioGainNode; 51bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenclass AudioPannerNode; 52bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenclass AudioListener; 53bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenclass DelayNode; 54bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenclass Document; 55bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenclass LowPass2FilterNode; 56bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenclass HighPass2FilterNode; 57bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenclass ConvolverNode; 58bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenclass RealtimeAnalyserNode; 59bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenclass JavaScriptAudioNode; 60bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 61bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen// AudioContext is the cornerstone of the web audio API and all AudioNodes are created from it. 62bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen// For thread safety between the audio thread and the main thread, it has a rendering graph locking mechanism. 63bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass AudioContext : public ActiveDOMObject, public RefCounted<AudioContext>, public EventTarget { 65bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenpublic: 662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // Create an AudioContext for rendering to the audio hardware. 67bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen static PassRefPtr<AudioContext> create(Document*); 68bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // Create an AudioContext for offline (non-realtime) rendering. 702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch static PassRefPtr<AudioContext> createOfflineContext(Document*, unsigned numberOfChannels, size_t numberOfFrames, double sampleRate); 712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 72bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen virtual ~AudioContext(); 73bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 74bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen bool isInitialized() const; 752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch bool isOfflineContext() { return m_isOfflineContext; } 77bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 78bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Returns true when initialize() was called AND all asynchronous initialization has completed. 79bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen bool isRunnable() const; 80bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 81bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Document notification 82bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen virtual void stop(); 83bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch Document* document() const; // ASSERTs if document no longer exists. 85bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen bool hasDocument(); 86bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 87bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen AudioDestinationNode* destination() { return m_destinationNode.get(); } 88bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen double currentTime() { return m_destinationNode->currentTime(); } 89bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen double sampleRate() { return m_destinationNode->sampleRate(); } 90bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 91bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen PassRefPtr<AudioBuffer> createBuffer(unsigned numberOfChannels, size_t numberOfFrames, double sampleRate); 92f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch PassRefPtr<AudioBuffer> createBuffer(ArrayBuffer* arrayBuffer, bool mixToMono); 93bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 94bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Keep track of this buffer so we can release memory after the context is shut down... 95bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen void refBuffer(PassRefPtr<AudioBuffer> buffer); 96bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 97bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen AudioListener* listener() { return m_listener.get(); } 98bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 99bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // The AudioNode create methods are called on the main thread (from JavaScript). 100bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen PassRefPtr<AudioBufferSourceNode> createBufferSource(); 101bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen PassRefPtr<AudioGainNode> createGainNode(); 102bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen PassRefPtr<DelayNode> createDelayNode(); 103bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen PassRefPtr<LowPass2FilterNode> createLowPass2Filter(); 104bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen PassRefPtr<HighPass2FilterNode> createHighPass2Filter(); 105bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen PassRefPtr<AudioPannerNode> createPanner(); 106bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen PassRefPtr<ConvolverNode> createConvolver(); 107bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen PassRefPtr<RealtimeAnalyserNode> createAnalyser(); 108bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen PassRefPtr<JavaScriptAudioNode> createJavaScriptNode(size_t bufferSize); 109bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen PassRefPtr<AudioChannelSplitter> createChannelSplitter(); 110bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen PassRefPtr<AudioChannelMerger> createChannelMerger(); 111bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 112bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen AudioBus* temporaryMonoBus() { return m_temporaryMonoBus.get(); } 113bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen AudioBus* temporaryStereoBus() { return m_temporaryStereoBus.get(); } 114bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 115bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // When a source node has no more processing to do (has finished playing), then it tells the context to dereference it. 116bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen void notifyNodeFinishedProcessing(AudioNode*); 117bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 118e14391e94c850b8bd03680c23b38978db68687a8John Reck // Called at the start of each render quantum. 119e14391e94c850b8bd03680c23b38978db68687a8John Reck void handlePreRenderTasks(); 120e14391e94c850b8bd03680c23b38978db68687a8John Reck 121bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Called at the end of each render quantum. 122bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen void handlePostRenderTasks(); 123bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 124bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Called periodically at the end of each render quantum to dereference finished source nodes. 125bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen void derefFinishedSourceNodes(); 126bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 127bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // We reap all marked nodes at the end of each realtime render quantum in deleteMarkedNodes(). 128bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen void markForDeletion(AudioNode*); 129bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen void deleteMarkedNodes(); 130bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 131bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Keeps track of the number of connections made. 132bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen void incrementConnectionCount() 133bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen { 134bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen ASSERT(isMainThread()); 135bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen m_connectionCount++; 136bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen } 137bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 138bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen unsigned connectionCount() const { return m_connectionCount; } 139bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 140bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // 141bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Thread Safety and Graph Locking: 142bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // 143bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 144bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen void setAudioThread(ThreadIdentifier thread) { m_audioThread = thread; } // FIXME: check either not initialized or the same 145bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen ThreadIdentifier audioThread() const { return m_audioThread; } 146e14391e94c850b8bd03680c23b38978db68687a8John Reck bool isAudioThread() const; 147bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 148bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Returns true only after the audio thread has been started and then shutdown. 149bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen bool isAudioThreadFinished() { return m_isAudioThreadFinished; } 150bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 151bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // mustReleaseLock is set to true if we acquired the lock in this method call and caller must unlock(), false if it was previously acquired. 152bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen void lock(bool& mustReleaseLock); 153bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 154bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Returns true if we own the lock. 155bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // mustReleaseLock is set to true if we acquired the lock in this method call and caller must unlock(), false if it was previously acquired. 156bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen bool tryLock(bool& mustReleaseLock); 157bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 158bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen void unlock(); 159bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 160bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Returns true if this thread owns the context's lock. 161e14391e94c850b8bd03680c23b38978db68687a8John Reck bool isGraphOwner() const; 162bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 163bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen class AutoLocker { 164bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen public: 165bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen AutoLocker(AudioContext* context) 166bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen : m_context(context) 167bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen { 168bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen ASSERT(context); 169bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen context->lock(m_mustReleaseLock); 170bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen } 171bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 172bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen ~AutoLocker() 173bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen { 174bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (m_mustReleaseLock) 175bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen m_context->unlock(); 176bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen } 177bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen private: 178bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen AudioContext* m_context; 179bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen bool m_mustReleaseLock; 180bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen }; 181bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 182bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // In AudioNode::deref() a tryLock() is used for calling finishDeref(), but if it fails keep track here. 183bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen void addDeferredFinishDeref(AudioNode*, AudioNode::RefType); 184bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 185bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // In the audio thread at the start of each render cycle, we'll call handleDeferredFinishDerefs(). 186bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen void handleDeferredFinishDerefs(); 187e14391e94c850b8bd03680c23b38978db68687a8John Reck 188e14391e94c850b8bd03680c23b38978db68687a8John Reck // Only accessed when the graph lock is held. 189e14391e94c850b8bd03680c23b38978db68687a8John Reck void markAudioNodeInputDirty(AudioNodeInput*); 190e14391e94c850b8bd03680c23b38978db68687a8John Reck void markAudioNodeOutputDirty(AudioNodeOutput*); 1912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // EventTarget 1932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch virtual ScriptExecutionContext* scriptExecutionContext() const; 1942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch virtual AudioContext* toAudioContext(); 1952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch virtual EventTargetData* eventTargetData() { return &m_eventTargetData; } 1962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch virtual EventTargetData* ensureEventTargetData() { return &m_eventTargetData; } 1972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch DEFINE_ATTRIBUTE_EVENT_LISTENER(complete); 1992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 2002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // Reconcile ref/deref which are defined both in AudioNode and EventTarget. 2012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch using RefCounted<AudioContext>::ref; 2022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch using RefCounted<AudioContext>::deref; 2032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 2042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch void startRendering(); 2052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch void fireCompletionEvent(); 206bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 207bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenprivate: 208bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen AudioContext(Document*); 2092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch AudioContext(Document*, unsigned numberOfChannels, size_t numberOfFrames, double sampleRate); 2102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch void constructCommon(); 2112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 212bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen void lazyInitialize(); 213bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen void uninitialize(); 214bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 215bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen bool m_isInitialized; 216bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen bool m_isAudioThreadFinished; 217bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen bool m_isAudioThreadShutdown; 218bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 219bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen Document* m_document; 220bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 221bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // The context itself keeps a reference to all source nodes. The source nodes, then reference all nodes they're connected to. 222bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // In turn, these nodes reference all nodes they're connected to. All nodes are ultimately connected to the AudioDestinationNode. 223bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // When the context dereferences a source node, it will be deactivated from the rendering graph along with all other nodes it is 224bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // uniquely connected to. See the AudioNode::ref() and AudioNode::deref() methods for more details. 225bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen void refNode(AudioNode*); 226bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen void derefNode(AudioNode*); 227bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 228bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // When the context goes away, there might still be some sources which haven't finished playing. 229bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Make sure to dereference them here. 230bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen void derefUnfinishedSourceNodes(); 231bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 232bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen RefPtr<AudioDestinationNode> m_destinationNode; 233bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen RefPtr<AudioListener> m_listener; 234bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 235bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Only accessed in the main thread. 236bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen Vector<RefPtr<AudioBuffer> > m_allocatedBuffers; 237bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 238bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Only accessed in the audio thread. 239bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen Vector<AudioNode*> m_finishedNodes; 240bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 241bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // We don't use RefPtr<AudioNode> here because AudioNode has a more complex ref() / deref() implementation 242bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // with an optional argument for refType. We need to use the special refType: RefTypeConnection 243bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Either accessed when the graph lock is held, or on the main thread when the audio thread has finished. 244bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen Vector<AudioNode*> m_referencedNodes; 245bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 246bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Accumulate nodes which need to be deleted at the end of a render cycle (in realtime thread) here. 247bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen Vector<AudioNode*> m_nodesToDelete; 248bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 249e14391e94c850b8bd03680c23b38978db68687a8John Reck // Only accessed when the graph lock is held. 250e14391e94c850b8bd03680c23b38978db68687a8John Reck HashSet<AudioNodeInput*> m_dirtyAudioNodeInputs; 251e14391e94c850b8bd03680c23b38978db68687a8John Reck HashSet<AudioNodeOutput*> m_dirtyAudioNodeOutputs; 252e14391e94c850b8bd03680c23b38978db68687a8John Reck void handleDirtyAudioNodeInputs(); 253e14391e94c850b8bd03680c23b38978db68687a8John Reck void handleDirtyAudioNodeOutputs(); 254bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 255bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen OwnPtr<AudioBus> m_temporaryMonoBus; 256bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen OwnPtr<AudioBus> m_temporaryStereoBus; 257bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 258bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen unsigned m_connectionCount; 259bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 260bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Graph locking. 261bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen Mutex m_contextGraphMutex; 262bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen volatile ThreadIdentifier m_audioThread; 263bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen volatile ThreadIdentifier m_graphOwnerThread; // if the lock is held then this is the thread which owns it, otherwise == UndefinedThreadIdentifier 264bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 265bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Deferred de-referencing. 266bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen struct RefInfo { 267bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen RefInfo(AudioNode* node, AudioNode::RefType refType) 268bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen : m_node(node) 269bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen , m_refType(refType) 270bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen { 271bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen } 272bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen AudioNode* m_node; 273bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen AudioNode::RefType m_refType; 274bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen }; 275bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 276bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Only accessed in the audio thread. 277bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen Vector<RefInfo> m_deferredFinishDerefList; 278a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 279a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // HRTF Database loader 280a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch RefPtr<HRTFDatabaseLoader> m_hrtfDatabaseLoader; 2812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 2822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // EventTarget 2832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch virtual void refEventTarget() { ref(); } 2842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch virtual void derefEventTarget() { deref(); } 2852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch EventTargetData m_eventTargetData; 2862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 2872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch RefPtr<AudioBuffer> m_renderTarget; 2882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 2892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch bool m_isOfflineContext; 290bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}; 291bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 292bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen} // WebCore 293bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 294bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#endif // AudioContext_h 295