1bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen/* 2e14391e94c850b8bd03680c23b38978db68687a8John Reck * 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 8e14391e94c850b8bd03680c23b38978db68687a8John Reck * notice, this list of conditions and the following disclaimer. 9bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * 2. Redistributions in binary form must reproduce the above copyright 10e14391e94c850b8bd03680c23b38978db68687a8John Reck * notice, this list of conditions and the following disclaimer in the 11e14391e94c850b8bd03680c23b38978db68687a8John Reck * documentation and/or other materials provided with the distribution. 12bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * 13e14391e94c850b8bd03680c23b38978db68687a8John Reck * 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 16e14391e94c850b8bd03680c23b38978db68687a8John Reck * 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; 19e14391e94c850b8bd03680c23b38978db68687a8John Reck * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20e14391e94c850b8bd03680c23b38978db68687a8John Reck * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21e14391e94c850b8bd03680c23b38978db68687a8John Reck * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22e14391e94c850b8bd03680c23b38978db68687a8John Reck * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen */ 24bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 25bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "config.h" 26bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 27bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#if ENABLE(WEB_AUDIO) 28bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 29bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "AudioNode.h" 30bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 31bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "AudioContext.h" 32bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "AudioNodeInput.h" 33bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "AudioNodeOutput.h" 34bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include <wtf/Atomics.h> 35bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 36bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsennamespace WebCore { 37bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 38bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian MonsenAudioNode::AudioNode(AudioContext* context, double sampleRate) 39bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen : m_isInitialized(false) 40bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen , m_type(NodeTypeUnknown) 41bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen , m_context(context) 42bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen , m_sampleRate(sampleRate) 43bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen , m_lastProcessingTime(-1.0) 44bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen , m_normalRefCount(1) // start out with normal refCount == 1 (like WTF::RefCounted class) 45bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen , m_connectionRefCount(0) 46bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen , m_disabledRefCount(0) 47bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen , m_isMarkedForDeletion(false) 48bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen , m_isDisabled(false) 49bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{ 50bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#if DEBUG_AUDIONODE_REFERENCES 51bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (!s_isNodeCountInitialized) { 52bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen s_isNodeCountInitialized = true; 53bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen atexit(AudioNode::printNodeCounts); 54bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen } 55bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#endif 56bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen} 57bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 58bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian MonsenAudioNode::~AudioNode() 59bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{ 60bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#if DEBUG_AUDIONODE_REFERENCES 61bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen --s_nodeCount[type()]; 62bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen printf("%p: %d: AudioNode::~AudioNode() %d %d %d\n", this, type(), m_normalRefCount, m_connectionRefCount, m_disabledRefCount); 63bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#endif 64bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen} 65bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 66a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid AudioNode::initialize() 67a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 68a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_isInitialized = true; 69a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 70a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 71a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid AudioNode::uninitialize() 72a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 73a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_isInitialized = false; 74a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 75a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 76bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioNode::setType(NodeType type) 77bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{ 78bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen m_type = type; 79bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 80bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#if DEBUG_AUDIONODE_REFERENCES 81bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen ++s_nodeCount[type]; 82bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#endif 83bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen} 84bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 85bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioNode::lazyInitialize() 86bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{ 87bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (!isInitialized()) 88bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen initialize(); 89bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen} 90bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 91bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioNode::addInput(PassOwnPtr<AudioNodeInput> input) 92bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{ 93bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen m_inputs.append(input); 94bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen} 95bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 96bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioNode::addOutput(PassOwnPtr<AudioNodeOutput> output) 97bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{ 98bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen m_outputs.append(output); 99bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen} 100bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 101bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian MonsenAudioNodeInput* AudioNode::input(unsigned i) 102bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{ 103bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen return m_inputs[i].get(); 104bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen} 105bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 106bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian MonsenAudioNodeOutput* AudioNode::output(unsigned i) 107bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{ 108bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen return m_outputs[i].get(); 109bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen} 110bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 111bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenbool AudioNode::connect(AudioNode* destination, unsigned outputIndex, unsigned inputIndex) 112bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{ 113bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen ASSERT(isMainThread()); 114bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen AudioContext::AutoLocker locker(context()); 115bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 116bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Sanity check input and output indices. 117bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (outputIndex >= numberOfOutputs()) 118bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen return false; 119bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (destination && inputIndex >= destination->numberOfInputs()) 120bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen return false; 121bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 122bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen AudioNodeOutput* output = this->output(outputIndex); 123bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (!destination) { 124bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Disconnect output from any inputs it may be currently connected to. 125bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen output->disconnectAllInputs(); 126bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen return true; 127bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen } 128bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 129bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen AudioNodeInput* input = destination->input(inputIndex); 130bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen input->connect(output); 131bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 132bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Let context know that a connection has been made. 133bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen context()->incrementConnectionCount(); 134bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 135bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen return true; 136bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen} 137bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 138bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenbool AudioNode::disconnect(unsigned outputIndex) 139bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{ 140bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen ASSERT(isMainThread()); 141bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen AudioContext::AutoLocker locker(context()); 142bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 143bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen return connect(0, outputIndex); 144bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen} 145bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 146bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioNode::processIfNecessary(size_t framesToProcess) 147bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{ 148bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen ASSERT(context()->isAudioThread()); 149bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 150bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (!isInitialized()) 151bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen return; 152bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 153bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Ensure that we only process once per rendering quantum. 154bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // This handles the "fanout" problem where an output is connected to multiple inputs. 155bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // The first time we're called during this time slice we process, but after that we don't want to re-process, 156bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // instead our output(s) will already have the results cached in their bus; 157bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen double currentTime = context()->currentTime(); 158bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (m_lastProcessingTime != currentTime) { 159bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen m_lastProcessingTime = currentTime; // important to first update this time because of feedback loops in the rendering graph 160bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen pullInputs(framesToProcess); 161bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen process(framesToProcess); 162bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen } 163bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen} 164bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 165bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioNode::pullInputs(size_t framesToProcess) 166bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{ 167bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen ASSERT(context()->isAudioThread()); 168bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 169bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Process all of the AudioNodes connected to our inputs. 170bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen for (unsigned i = 0; i < m_inputs.size(); ++i) 171bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen input(i)->pull(0, framesToProcess); 172bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen} 173bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 174bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioNode::ref(RefType refType) 175bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{ 176bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen switch (refType) { 177bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen case RefTypeNormal: 178bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen atomicIncrement(&m_normalRefCount); 179bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen break; 180bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen case RefTypeConnection: 181bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen atomicIncrement(&m_connectionRefCount); 182bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen break; 183bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen case RefTypeDisabled: 184bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen atomicIncrement(&m_disabledRefCount); 185bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen break; 186bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen default: 187bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen ASSERT_NOT_REACHED(); 188bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen } 189bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 190bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#if DEBUG_AUDIONODE_REFERENCES 191bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen printf("%p: %d: AudioNode::ref(%d) %d %d %d\n", this, type(), refType, m_normalRefCount, m_connectionRefCount, m_disabledRefCount); 192bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#endif 193bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 194bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (m_connectionRefCount == 1 && refType == RefTypeConnection) { 195bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // FIXME: implement wake-up - this is an advanced feature and is not necessary in a simple implementation. 196bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // We should not be "actively" connected to anything, but now we're "waking up" 197bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // For example, a note which has finished playing, but is now being played again. 198bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Note that if this is considered a worthwhile feature to add, then an evaluation of the locking considerations must be made. 199bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen } 200bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen} 201bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 202bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioNode::deref(RefType refType) 203bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{ 204bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // The actually work for deref happens completely within the audio context's graph lock. 205bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // In the case of the audio thread, we must use a tryLock to avoid glitches. 206bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen bool hasLock = false; 207bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen bool mustReleaseLock = false; 208bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 209bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (context()->isAudioThread()) { 210bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Real-time audio thread must not contend lock (to avoid glitches). 211bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen hasLock = context()->tryLock(mustReleaseLock); 212bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen } else { 213bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen context()->lock(mustReleaseLock); 214bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen hasLock = true; 215bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen } 216bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 217bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (hasLock) { 218bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // This is where the real deref work happens. 219bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen finishDeref(refType); 220bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 221bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (mustReleaseLock) 222bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen context()->unlock(); 223bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen } else { 224bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // We were unable to get the lock, so put this in a list to finish up later. 225bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen ASSERT(context()->isAudioThread()); 226bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen context()->addDeferredFinishDeref(this, refType); 227bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen } 228bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 229bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Once AudioContext::uninitialize() is called there's no more chances for deleteMarkedNodes() to get called, so we call here. 230bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // We can't call in AudioContext::~AudioContext() since it will never be called as long as any AudioNode is alive 231bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // because AudioNodes keep a reference to the context. 232bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (context()->isAudioThreadFinished()) 233bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen context()->deleteMarkedNodes(); 234bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen} 235bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 236bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioNode::finishDeref(RefType refType) 237bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{ 238bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen ASSERT(context()->isGraphOwner()); 239bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 240bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen switch (refType) { 241bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen case RefTypeNormal: 242bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen ASSERT(m_normalRefCount > 0); 243bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen atomicDecrement(&m_normalRefCount); 244bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen break; 245bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen case RefTypeConnection: 246bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen ASSERT(m_connectionRefCount > 0); 247bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen atomicDecrement(&m_connectionRefCount); 248bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen break; 249bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen case RefTypeDisabled: 250bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen ASSERT(m_disabledRefCount > 0); 251bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen atomicDecrement(&m_disabledRefCount); 252bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen break; 253bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen default: 254bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen ASSERT_NOT_REACHED(); 255bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen } 256bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 257bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#if DEBUG_AUDIONODE_REFERENCES 258bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen printf("%p: %d: AudioNode::deref(%d) %d %d %d\n", this, type(), refType, m_normalRefCount, m_connectionRefCount, m_disabledRefCount); 259bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#endif 260bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 261bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (!m_connectionRefCount) { 262bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (!m_normalRefCount && !m_disabledRefCount) { 263bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (!m_isMarkedForDeletion) { 264bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // All references are gone - we need to go away. 265bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen for (unsigned i = 0; i < m_outputs.size(); ++i) 266bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen output(i)->disconnectAllInputs(); // this will deref() nodes we're connected to... 267bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 268bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Mark for deletion at end of each render quantum or when context shuts down. 269bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen context()->markForDeletion(this); 270bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen m_isMarkedForDeletion = true; 271bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen } 272bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen } else if (refType == RefTypeConnection) { 273bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (!m_isDisabled) { 274bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Still may have JavaScript references, but no more "active" connection references, so put all of our outputs in a "dormant" disabled state. 275bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // Garbage collection may take a very long time after this time, so the "dormant" disabled nodes should not bog down the rendering... 276bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 277bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // As far as JavaScript is concerned, our outputs must still appear to be connected. 278bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // But internally our outputs should be disabled from the inputs they're connected to. 279bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // disable() can recursively deref connections (and call disable()) down a whole chain of connected nodes. 280bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 281bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // FIXME: we special case the convolver and delay since they have a significant tail-time and shouldn't be disconnected simply 282bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // because they no longer have any input connections. This needs to be handled more generally where AudioNodes have 283bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // a tailTime attribute. Then the AudioNode only needs to remain "active" for tailTime seconds after there are no 284bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen // longer any active connections. 285bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen if (type() != NodeTypeConvolver && type() != NodeTypeDelay) { 286bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen m_isDisabled = true; 287bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen for (unsigned i = 0; i < m_outputs.size(); ++i) 288bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen output(i)->disable(); 289bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen } 290bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen } 291bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen } 292bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen } 293bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen} 294bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 295bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#if DEBUG_AUDIONODE_REFERENCES 296bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 297bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenbool AudioNode::s_isNodeCountInitialized = false; 298bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenint AudioNode::s_nodeCount[NodeTypeEnd]; 299bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 300bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioNode::printNodeCounts() 301bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{ 302bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen printf("\n\n"); 303bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen printf("===========================\n"); 304bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen printf("AudioNode: reference counts\n"); 305bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen printf("===========================\n"); 306bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 307bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen for (unsigned i = 0; i < NodeTypeEnd; ++i) 308bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen printf("%d: %d\n", i, s_nodeCount[i]); 309bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 310bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen printf("===========================\n\n\n"); 311bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen} 312bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 313bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#endif // DEBUG_AUDIONODE_REFERENCES 314bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 315bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen} // namespace WebCore 316bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 317bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#endif // ENABLE(WEB_AUDIO) 318