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