void DeferredTaskHandler::handleDirtyAudioSummingJunctions() { ASSERT(isGraphOwner()); for (AudioSummingJunction* junction : m_dirtySummingJunctions) junction->updateRenderingState(); m_dirtySummingJunctions.clear(); }
void DeferredTaskHandler::disposeOutputs(AudioHandler& node) { ASSERT(isGraphOwner()); ASSERT(isMainThread()); for (unsigned i = 0; i < node.numberOfOutputs(); ++i) node.output(i)->dispose(); }
void AudioContext::removeAutomaticPullNode(AudioNode* node) { ASSERT(isGraphOwner()); if (m_automaticPullNodes.remove(node)) m_automaticPullNodesNeedUpdating = true; }
void DeferredTaskHandler::updateChangedChannelInterpretation() { ASSERT(isGraphOwner()); for (AudioHandler* node : m_deferredChannelInterpretationChange) node->updateChannelInterpretation(); m_deferredChannelInterpretationChange.clear(); }
void AudioContext::addAutomaticPullNode(AudioNode* node) { ASSERT(isGraphOwner()); if (m_automaticPullNodes.add(node).isNewEntry) m_automaticPullNodesNeedUpdating = true; }
void DeferredTaskHandler::updateChangedChannelCountMode() { ASSERT(isGraphOwner()); for (AudioHandler* node : m_deferredCountModeChange) node->updateChannelCountMode(); m_deferredCountModeChange.clear(); }
void AudioContext::deleteMarkedNodes() { ASSERT(isGraphOwner() || isAudioThreadFinished()); // Note: deleting an AudioNode can cause m_nodesToDelete to grow. size_t nodesDeleted = 0; while (size_t n = m_nodesToDelete.size()) { AudioNode* node = m_nodesToDelete[n - 1]; m_nodesToDelete.removeLast(); // Before deleting the node, clear out any AudioNodeInputs from m_dirtyAudioNodeInputs. unsigned numberOfInputs = node->numberOfInputs(); for (unsigned i = 0; i < numberOfInputs; ++i) m_dirtyAudioNodeInputs.remove(node->input(i)); // Before deleting the node, clear out any AudioNodeOutputs from m_dirtyAudioNodeOutputs. unsigned numberOfOutputs = node->numberOfOutputs(); for (unsigned i = 0; i < numberOfOutputs; ++i) m_dirtyAudioNodeOutputs.remove(node->output(i)); // Finally, delete it. delete node; // Don't delete too many nodes per render quantum since we don't want to do too much work in the realtime audio thread. if (++nodesDeleted > MaxNodesToDeletePerQuantum) break; } }
void DeferredTaskHandler::removeAutomaticPullNode(AudioHandler* node) { ASSERT(isGraphOwner()); if (m_automaticPullNodes.contains(node)) { m_automaticPullNodes.remove(node); m_automaticPullNodesNeedUpdating = true; } }
void AudioContext::handleDeferredFinishDerefs() { ASSERT(isAudioThread() && isGraphOwner()); for (auto& node : m_deferredFinishDerefList) node->finishDeref(AudioNode::RefTypeConnection); m_deferredFinishDerefList.clear(); }
void DeferredTaskHandler::breakConnections() { DCHECK(isAudioThread()); ASSERT(isGraphOwner()); for (unsigned i = 0; i < m_deferredBreakConnectionList.size(); ++i) m_deferredBreakConnectionList[i]->breakConnectionWithLock(); m_deferredBreakConnectionList.clear(); }
void DeferredTaskHandler::updateAutomaticPullNodes() { ASSERT(isGraphOwner()); if (m_automaticPullNodesNeedUpdating) { copyToVector(m_automaticPullNodes, m_renderingAutomaticPullNodes); m_automaticPullNodesNeedUpdating = false; } }
void DeferredTaskHandler::handleDirtyAudioNodeOutputs() { ASSERT(isGraphOwner()); for (AudioNodeOutput* output : m_dirtyAudioNodeOutputs) output->updateRenderingState(); m_dirtyAudioNodeOutputs.clear(); }
void AudioContext::handleDirtyAudioNodeOutputs() { ASSERT(isGraphOwner()); for (auto& output : m_dirtyAudioNodeOutputs) output->updateRenderingState(); m_dirtyAudioNodeOutputs.clear(); }
void AudioContext::derefNode(AudioNode* node) { ASSERT(isGraphOwner()); node->deref(AudioNode::RefTypeConnection); ASSERT(m_referencedNodes.contains(node)); m_referencedNodes.removeFirst(node); }
void AudioContext::derefFinishedSourceNodes() { ASSERT(isGraphOwner()); ASSERT(isAudioThread() || isAudioThreadFinished()); for (auto& node : m_finishedNodes) derefNode(node); m_finishedNodes.clear(); }
void AudioContext::handleDirtyAudioSummingJunctions() { ASSERT(isGraphOwner()); for (HashSet<AudioSummingJunction*>::iterator i = m_dirtySummingJunctions.begin(); i != m_dirtySummingJunctions.end(); ++i) (*i)->updateRenderingState(); m_dirtySummingJunctions.clear(); }
void AudioContext::handleDirtyAudioSummingJunctions() { ASSERT(isGraphOwner()); for (auto& junction : m_dirtySummingJunctions) junction->updateRenderingState(); m_dirtySummingJunctions.clear(); }
void AudioContext::addAutomaticPullNode(AudioNode* node) { ASSERT(isGraphOwner()); if (!m_automaticPullNodes.contains(node)) { m_automaticPullNodes.add(node); m_automaticPullNodesNeedUpdating = true; } }
void AudioContext::derefFinishedSourceNodes() { ASSERT(isGraphOwner()); ASSERT(isAudioThread() || isAudioThreadFinished()); for (unsigned i = 0; i < m_finishedNodes.size(); i++) derefNode(m_finishedNodes[i]); m_finishedNodes.clear(); }
void AudioContext::handleDirtyAudioNodeOutputs() { ASSERT(isGraphOwner()); for (HashSet<AudioNodeOutput*>::iterator i = m_dirtyAudioNodeOutputs.begin(); i != m_dirtyAudioNodeOutputs.end(); ++i) (*i)->updateRenderingState(); m_dirtyAudioNodeOutputs.clear(); }
void AudioContext::resolvePromisesForSuspend() { // This runs inside the AudioContext's lock when handling pre-render tasks. ASSERT(isAudioThread()); ASSERT(isGraphOwner()); // Resolve any pending promises created by suspend() if (m_suspendResolvers.size() > 0) Platform::current()->mainThread()->postTask(FROM_HERE, bind(&AudioContext::resolvePromisesForSuspendOnMainThread, this)); }
void DeferredTaskHandler::requestToDeleteHandlersOnMainThread() { ASSERT(isGraphOwner()); ASSERT(isAudioThread()); if (m_renderingOrphanHandlers.isEmpty()) return; m_deletableOrphanHandlers.appendVector(m_renderingOrphanHandlers); m_renderingOrphanHandlers.clear(); Platform::current()->mainThread()->taskRunner()->postTask(BLINK_FROM_HERE, threadSafeBind(&DeferredTaskHandler::deleteHandlersOnMainThread, PassRefPtr<DeferredTaskHandler>(this))); }
void AudioContext::handleDeferredFinishDerefs() { ASSERT(isAudioThread() && isGraphOwner()); for (unsigned i = 0; i < m_deferredFinishDerefList.size(); ++i) { AudioNode* node = m_deferredFinishDerefList[i]; node->finishDeref(AudioNode::RefTypeConnection); } m_deferredFinishDerefList.clear(); }
void AudioContext::derefNode(AudioNode* node) { ASSERT(isGraphOwner()); for (unsigned i = 0; i < m_referencedNodes.size(); ++i) { if (node == m_referencedNodes.at(i).get()) { node->handler().breakConnection(); m_referencedNodes.remove(i); break; } } }
void AbstractAudioContext::handleStoppableSourceNodes() { ASSERT(isGraphOwner()); // Find AudioBufferSourceNodes to see if we can stop playing them. for (AudioNode* node : m_activeSourceNodes) { if (node->handler().nodeType() == AudioHandler::NodeTypeAudioBufferSource) { AudioBufferSourceNode* sourceNode = static_cast<AudioBufferSourceNode*>(node); sourceNode->audioBufferSourceHandler().handleStoppableSourceNode(); } } }
void DeferredTaskHandler::handleDirtyAudioNodeOutputs() { ASSERT(isGraphOwner()); HashSet<AudioNodeOutput*> dirtyOutputs; m_dirtyAudioNodeOutputs.swap(dirtyOutputs); // Note: the updating of rendering state may cause output nodes // further down the chain to be marked as dirty. These will not // be processed in this render quantum. for (AudioNodeOutput* output : dirtyOutputs) output->updateRenderingState(); }
void AudioContext::derefNode(AudioNode* node) { ASSERT(isGraphOwner()); node->deref(AudioNode::RefTypeConnection); for (unsigned i = 0; i < m_referencedNodes.size(); ++i) { if (node == m_referencedNodes[i]) { m_referencedNodes.remove(i); break; } } }
void AudioContext::resolvePromisesForResume() { // This runs inside the AudioContext's lock when handling pre-render tasks. ASSERT(isAudioThread()); ASSERT(isGraphOwner()); // Resolve any pending promises created by resume(). Only do this if we haven't already started // resolving these promises. This gets called very often and it takes some time to resolve the // promises in the main thread. if (!m_isResolvingResumePromises && m_resumeResolvers.size() > 0) { m_isResolvingResumePromises = true; Platform::current()->mainThread()->postTask(FROM_HERE, bind(&AudioContext::resolvePromisesForResumeOnMainThread, this)); } }
void AudioContext::handleStoppableSourceNodes() { ASSERT(isGraphOwner()); // Find AudioBufferSourceNodes to see if we can stop playing them. for (unsigned i = 0; i < m_referencedNodes.size(); ++i) { AudioNode* node = m_referencedNodes.at(i).get(); if (node->handler().nodeType() == AudioHandler::NodeTypeAudioBufferSource) { AudioBufferSourceNode* sourceNode = static_cast<AudioBufferSourceNode*>(node); sourceNode->audioBufferSourceHandler().handleStoppableSourceNode(); } } }
void AudioContext::markForDeletion(AudioNode* node) { ASSERT(isGraphOwner()); if (isAudioThreadFinished()) m_nodesToDelete.append(node); else m_nodesMarkedForDeletion.append(node); // This is probably the best time for us to remove the node from automatic pull list, // since all connections are gone and we hold the graph lock. Then when handlePostRenderTasks() // gets a chance to schedule the deletion work, updateAutomaticPullNodes() also gets a chance to // modify m_renderingAutomaticPullNodes. removeAutomaticPullNode(node); }