| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010, Google Inc. All rights reserved. | 2 * Copyright (C) 2010, Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 #include "wtf/PassOwnPtr.h" | 75 #include "wtf/PassOwnPtr.h" |
| 76 #include "wtf/RefCounted.h" | 76 #include "wtf/RefCounted.h" |
| 77 #include "wtf/text/WTFString.h" | 77 #include "wtf/text/WTFString.h" |
| 78 | 78 |
| 79 // FIXME: check the proper way to reference an undefined thread ID | 79 // FIXME: check the proper way to reference an undefined thread ID |
| 80 const int UndefinedThreadIdentifier = 0xffffffff; | 80 const int UndefinedThreadIdentifier = 0xffffffff; |
| 81 | 81 |
| 82 const unsigned MaxNodesToDeletePerQuantum = 10; | 82 const unsigned MaxNodesToDeletePerQuantum = 10; |
| 83 | 83 |
| 84 namespace WebCore { | 84 namespace WebCore { |
| 85 | 85 |
| 86 bool AudioContext::isSampleRateRangeGood(float sampleRate) | 86 bool AudioContext::isSampleRateRangeGood(float sampleRate) |
| 87 { | 87 { |
| 88 // FIXME: It would be nice if the minimum sample-rate could be less than 44.
1KHz, | 88 // FIXME: It would be nice if the minimum sample-rate could be less than 44.
1KHz, |
| 89 // but that will require some fixes in HRTFPanner::fftSizeForSampleRate(), a
nd some testing there. | 89 // but that will require some fixes in HRTFPanner::fftSizeForSampleRate(), a
nd some testing there. |
| 90 return sampleRate >= 44100 && sampleRate <= 96000; | 90 return sampleRate >= 44100 && sampleRate <= 96000; |
| 91 } | 91 } |
| 92 | 92 |
| 93 // Don't allow more than this number of simultaneous AudioContexts talking to ha
rdware. | 93 // Don't allow more than this number of simultaneous AudioContexts talking to ha
rdware. |
| 94 const unsigned MaxHardwareContexts = 4; | 94 const unsigned MaxHardwareContexts = 4; |
| 95 unsigned AudioContext::s_hardwareContextCount = 0; | 95 unsigned AudioContext::s_hardwareContextCount = 0; |
| 96 | 96 |
| 97 PassRefPtr<AudioContext> AudioContext::create(Document* document) | 97 PassRefPtr<AudioContext> AudioContext::create(Document* document) |
| 98 { | 98 { |
| 99 ASSERT(document); | 99 ASSERT(document); |
| 100 ASSERT(isMainThread()); | 100 ASSERT(isMainThread()); |
| 101 if (s_hardwareContextCount >= MaxHardwareContexts) | 101 if (s_hardwareContextCount >= MaxHardwareContexts) |
| 102 return 0; | 102 return 0; |
| 103 | 103 |
| 104 RefPtr<AudioContext> audioContext(adoptRef(new AudioContext(document))); | 104 RefPtr<AudioContext> audioContext(adoptRef(new AudioContext(document))); |
| 105 audioContext->suspendIfNeeded(); | 105 audioContext->suspendIfNeeded(); |
| 106 return audioContext.release(); | 106 return audioContext.release(); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 192 ASSERT(!m_isAudioThreadFinished); | 192 ASSERT(!m_isAudioThreadFinished); |
| 193 if (!m_isAudioThreadFinished) { | 193 if (!m_isAudioThreadFinished) { |
| 194 if (m_destinationNode.get()) { | 194 if (m_destinationNode.get()) { |
| 195 m_destinationNode->initialize(); | 195 m_destinationNode->initialize(); |
| 196 | 196 |
| 197 if (!isOfflineContext()) { | 197 if (!isOfflineContext()) { |
| 198 // This starts the audio thread. The destination node's prov
ideInput() method will now be called repeatedly to render audio. | 198 // This starts the audio thread. The destination node's prov
ideInput() method will now be called repeatedly to render audio. |
| 199 // Each time provideInput() is called, a portion of the audi
o stream is rendered. Let's call this time period a "render quantum". | 199 // Each time provideInput() is called, a portion of the audi
o stream is rendered. Let's call this time period a "render quantum". |
| 200 // NOTE: for now default AudioContext does not need an expli
cit startRendering() call from JavaScript. | 200 // NOTE: for now default AudioContext does not need an expli
cit startRendering() call from JavaScript. |
| 201 // We may want to consider requiring it for symmetry with Of
flineAudioContext. | 201 // We may want to consider requiring it for symmetry with Of
flineAudioContext. |
| 202 m_destinationNode->startRendering(); | 202 m_destinationNode->startRendering(); |
| 203 ++s_hardwareContextCount; | 203 ++s_hardwareContextCount; |
| 204 } | 204 } |
| 205 | 205 |
| 206 } | 206 } |
| 207 m_isInitialized = true; | 207 m_isInitialized = true; |
| 208 } | 208 } |
| 209 } | 209 } |
| 210 } | 210 } |
| 211 | 211 |
| 212 void AudioContext::clear() | 212 void AudioContext::clear() |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 | 252 |
| 253 bool AudioContext::isInitialized() const | 253 bool AudioContext::isInitialized() const |
| 254 { | 254 { |
| 255 return m_isInitialized; | 255 return m_isInitialized; |
| 256 } | 256 } |
| 257 | 257 |
| 258 bool AudioContext::isRunnable() const | 258 bool AudioContext::isRunnable() const |
| 259 { | 259 { |
| 260 if (!isInitialized()) | 260 if (!isInitialized()) |
| 261 return false; | 261 return false; |
| 262 | 262 |
| 263 // Check with the HRTF spatialization system to see if it's finished loading
. | 263 // Check with the HRTF spatialization system to see if it's finished loading
. |
| 264 return m_hrtfDatabaseLoader->isLoaded(); | 264 return m_hrtfDatabaseLoader->isLoaded(); |
| 265 } | 265 } |
| 266 | 266 |
| 267 void AudioContext::stopDispatch(void* userData) | 267 void AudioContext::stopDispatch(void* userData) |
| 268 { | 268 { |
| 269 AudioContext* context = reinterpret_cast<AudioContext*>(userData); | 269 AudioContext* context = reinterpret_cast<AudioContext*>(userData); |
| 270 ASSERT(context); | 270 ASSERT(context); |
| 271 if (!context) | 271 if (!context) |
| 272 return; | 272 return; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 return node; | 339 return node; |
| 340 } | 340 } |
| 341 | 341 |
| 342 PassRefPtr<MediaElementAudioSourceNode> AudioContext::createMediaElementSource(H
TMLMediaElement* mediaElement, ExceptionState& es) | 342 PassRefPtr<MediaElementAudioSourceNode> AudioContext::createMediaElementSource(H
TMLMediaElement* mediaElement, ExceptionState& es) |
| 343 { | 343 { |
| 344 ASSERT(mediaElement); | 344 ASSERT(mediaElement); |
| 345 if (!mediaElement) { | 345 if (!mediaElement) { |
| 346 es.throwDOMException(InvalidStateError); | 346 es.throwDOMException(InvalidStateError); |
| 347 return 0; | 347 return 0; |
| 348 } | 348 } |
| 349 | 349 |
| 350 ASSERT(isMainThread()); | 350 ASSERT(isMainThread()); |
| 351 lazyInitialize(); | 351 lazyInitialize(); |
| 352 | 352 |
| 353 // First check if this media element already has a source node. | 353 // First check if this media element already has a source node. |
| 354 if (mediaElement->audioSourceNode()) { | 354 if (mediaElement->audioSourceNode()) { |
| 355 es.throwDOMException(InvalidStateError); | 355 es.throwDOMException(InvalidStateError); |
| 356 return 0; | 356 return 0; |
| 357 } | 357 } |
| 358 | 358 |
| 359 RefPtr<MediaElementAudioSourceNode> node = MediaElementAudioSourceNode::crea
te(this, mediaElement); | 359 RefPtr<MediaElementAudioSourceNode> node = MediaElementAudioSourceNode::crea
te(this, mediaElement); |
| 360 | 360 |
| 361 mediaElement->setAudioSourceNode(node.get()); | 361 mediaElement->setAudioSourceNode(node.get()); |
| 362 | 362 |
| 363 refNode(node.get()); // context keeps reference until node is disconnected | 363 refNode(node.get()); // context keeps reference until node is disconnected |
| 364 return node; | 364 return node; |
| 365 } | 365 } |
| 366 | 366 |
| 367 PassRefPtr<MediaStreamAudioSourceNode> AudioContext::createMediaStreamSource(Med
iaStream* mediaStream, ExceptionState& es) | 367 PassRefPtr<MediaStreamAudioSourceNode> AudioContext::createMediaStreamSource(Med
iaStream* mediaStream, ExceptionState& es) |
| 368 { | 368 { |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 550 // Because this is an AudioScheduledSourceNode, the context keeps a referenc
e until it has finished playing. | 550 // Because this is an AudioScheduledSourceNode, the context keeps a referenc
e until it has finished playing. |
| 551 // When this happens, AudioScheduledSourceNode::finish() calls AudioContext:
:notifyNodeFinishedProcessing(). | 551 // When this happens, AudioScheduledSourceNode::finish() calls AudioContext:
:notifyNodeFinishedProcessing(). |
| 552 refNode(node.get()); | 552 refNode(node.get()); |
| 553 | 553 |
| 554 return node; | 554 return node; |
| 555 } | 555 } |
| 556 | 556 |
| 557 PassRefPtr<PeriodicWave> AudioContext::createPeriodicWave(Float32Array* real, Fl
oat32Array* imag, ExceptionState& es) | 557 PassRefPtr<PeriodicWave> AudioContext::createPeriodicWave(Float32Array* real, Fl
oat32Array* imag, ExceptionState& es) |
| 558 { | 558 { |
| 559 ASSERT(isMainThread()); | 559 ASSERT(isMainThread()); |
| 560 | 560 |
| 561 if (!real || !imag || (real->length() != imag->length())) { | 561 if (!real || !imag || (real->length() != imag->length())) { |
| 562 es.throwDOMException(SyntaxError); | 562 es.throwDOMException(SyntaxError); |
| 563 return 0; | 563 return 0; |
| 564 } | 564 } |
| 565 | 565 |
| 566 lazyInitialize(); | 566 lazyInitialize(); |
| 567 return PeriodicWave::create(sampleRate(), real, imag); | 567 return PeriodicWave::create(sampleRate(), real, imag); |
| 568 } | 568 } |
| 569 | 569 |
| 570 void AudioContext::notifyNodeFinishedProcessing(AudioNode* node) | 570 void AudioContext::notifyNodeFinishedProcessing(AudioNode* node) |
| 571 { | 571 { |
| 572 ASSERT(isAudioThread()); | 572 ASSERT(isAudioThread()); |
| 573 m_finishedNodes.append(node); | 573 m_finishedNodes.append(node); |
| 574 } | 574 } |
| 575 | 575 |
| 576 void AudioContext::derefFinishedSourceNodes() | 576 void AudioContext::derefFinishedSourceNodes() |
| 577 { | 577 { |
| 578 ASSERT(isGraphOwner()); | 578 ASSERT(isGraphOwner()); |
| 579 ASSERT(isAudioThread() || isAudioThreadFinished()); | 579 ASSERT(isAudioThread() || isAudioThreadFinished()); |
| 580 for (unsigned i = 0; i < m_finishedNodes.size(); i++) | 580 for (unsigned i = 0; i < m_finishedNodes.size(); i++) |
| 581 derefNode(m_finishedNodes[i]); | 581 derefNode(m_finishedNodes[i]); |
| 582 | 582 |
| 583 m_finishedNodes.clear(); | 583 m_finishedNodes.clear(); |
| 584 } | 584 } |
| 585 | 585 |
| 586 void AudioContext::refNode(AudioNode* node) | 586 void AudioContext::refNode(AudioNode* node) |
| 587 { | 587 { |
| 588 ASSERT(isMainThread()); | 588 ASSERT(isMainThread()); |
| 589 AutoLocker locker(this); | 589 AutoLocker locker(this); |
| 590 | 590 |
| 591 node->ref(AudioNode::RefTypeConnection); | 591 node->ref(AudioNode::RefTypeConnection); |
| 592 m_referencedNodes.append(node); | 592 m_referencedNodes.append(node); |
| 593 } | 593 } |
| 594 | 594 |
| 595 void AudioContext::derefNode(AudioNode* node) | 595 void AudioContext::derefNode(AudioNode* node) |
| 596 { | 596 { |
| 597 ASSERT(isGraphOwner()); | 597 ASSERT(isGraphOwner()); |
| 598 | 598 |
| 599 node->deref(AudioNode::RefTypeConnection); | 599 node->deref(AudioNode::RefTypeConnection); |
| 600 | 600 |
| 601 for (unsigned i = 0; i < m_referencedNodes.size(); ++i) { | 601 for (unsigned i = 0; i < m_referencedNodes.size(); ++i) { |
| 602 if (node == m_referencedNodes[i]) { | 602 if (node == m_referencedNodes[i]) { |
| 603 m_referencedNodes.remove(i); | 603 m_referencedNodes.remove(i); |
| 604 break; | 604 break; |
| 605 } | 605 } |
| 606 } | 606 } |
| 607 } | 607 } |
| 608 | 608 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 633 } | 633 } |
| 634 } | 634 } |
| 635 | 635 |
| 636 bool AudioContext::tryLock(bool& mustReleaseLock) | 636 bool AudioContext::tryLock(bool& mustReleaseLock) |
| 637 { | 637 { |
| 638 ThreadIdentifier thisThread = currentThread(); | 638 ThreadIdentifier thisThread = currentThread(); |
| 639 bool isAudioThread = thisThread == audioThread(); | 639 bool isAudioThread = thisThread == audioThread(); |
| 640 | 640 |
| 641 // Try to catch cases of using try lock on main thread - it should use regul
ar lock. | 641 // Try to catch cases of using try lock on main thread - it should use regul
ar lock. |
| 642 ASSERT(isAudioThread || isAudioThreadFinished()); | 642 ASSERT(isAudioThread || isAudioThreadFinished()); |
| 643 | 643 |
| 644 if (!isAudioThread) { | 644 if (!isAudioThread) { |
| 645 // In release build treat tryLock() as lock() (since above ASSERT(isAudi
oThread) never fires) - this is the best we can do. | 645 // In release build treat tryLock() as lock() (since above ASSERT(isAudi
oThread) never fires) - this is the best we can do. |
| 646 lock(mustReleaseLock); | 646 lock(mustReleaseLock); |
| 647 return true; | 647 return true; |
| 648 } | 648 } |
| 649 | 649 |
| 650 bool hasLock; | 650 bool hasLock; |
| 651 | 651 |
| 652 if (thisThread == m_graphOwnerThread) { | 652 if (thisThread == m_graphOwnerThread) { |
| 653 // Thread already has the lock. | 653 // Thread already has the lock. |
| 654 hasLock = true; | 654 hasLock = true; |
| 655 mustReleaseLock = false; | 655 mustReleaseLock = false; |
| 656 } else { | 656 } else { |
| 657 // Don't already have the lock - try to acquire it. | 657 // Don't already have the lock - try to acquire it. |
| 658 hasLock = m_contextGraphMutex.tryLock(); | 658 hasLock = m_contextGraphMutex.tryLock(); |
| 659 | 659 |
| 660 if (hasLock) | 660 if (hasLock) |
| 661 m_graphOwnerThread = thisThread; | 661 m_graphOwnerThread = thisThread; |
| 662 | 662 |
| 663 mustReleaseLock = hasLock; | 663 mustReleaseLock = hasLock; |
| 664 } | 664 } |
| 665 | 665 |
| 666 return hasLock; | 666 return hasLock; |
| 667 } | 667 } |
| 668 | 668 |
| 669 void AudioContext::unlock() | 669 void AudioContext::unlock() |
| 670 { | 670 { |
| 671 ASSERT(currentThread() == m_graphOwnerThread); | 671 ASSERT(currentThread() == m_graphOwnerThread); |
| 672 | 672 |
| 673 m_graphOwnerThread = UndefinedThreadIdentifier; | 673 m_graphOwnerThread = UndefinedThreadIdentifier; |
| 674 m_contextGraphMutex.unlock(); | 674 m_contextGraphMutex.unlock(); |
| 675 } | 675 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 686 | 686 |
| 687 void AudioContext::addDeferredFinishDeref(AudioNode* node) | 687 void AudioContext::addDeferredFinishDeref(AudioNode* node) |
| 688 { | 688 { |
| 689 ASSERT(isAudioThread()); | 689 ASSERT(isAudioThread()); |
| 690 m_deferredFinishDerefList.append(node); | 690 m_deferredFinishDerefList.append(node); |
| 691 } | 691 } |
| 692 | 692 |
| 693 void AudioContext::handlePreRenderTasks() | 693 void AudioContext::handlePreRenderTasks() |
| 694 { | 694 { |
| 695 ASSERT(isAudioThread()); | 695 ASSERT(isAudioThread()); |
| 696 | 696 |
| 697 // At the beginning of every render quantum, try to update the internal rend
ering graph state (from main thread changes). | 697 // At the beginning of every render quantum, try to update the internal rend
ering graph state (from main thread changes). |
| 698 // It's OK if the tryLock() fails, we'll just take slightly longer to pick u
p the changes. | 698 // It's OK if the tryLock() fails, we'll just take slightly longer to pick u
p the changes. |
| 699 bool mustReleaseLock; | 699 bool mustReleaseLock; |
| 700 if (tryLock(mustReleaseLock)) { | 700 if (tryLock(mustReleaseLock)) { |
| 701 // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutpu
ts. | 701 // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutpu
ts. |
| 702 handleDirtyAudioSummingJunctions(); | 702 handleDirtyAudioSummingJunctions(); |
| 703 handleDirtyAudioNodeOutputs(); | 703 handleDirtyAudioNodeOutputs(); |
| 704 | 704 |
| 705 updateAutomaticPullNodes(); | 705 updateAutomaticPullNodes(); |
| 706 | 706 |
| 707 if (mustReleaseLock) | 707 if (mustReleaseLock) |
| 708 unlock(); | 708 unlock(); |
| 709 } | 709 } |
| 710 } | 710 } |
| 711 | 711 |
| 712 void AudioContext::handlePostRenderTasks() | 712 void AudioContext::handlePostRenderTasks() |
| 713 { | 713 { |
| 714 ASSERT(isAudioThread()); | 714 ASSERT(isAudioThread()); |
| 715 | 715 |
| 716 // Must use a tryLock() here too. Don't worry, the lock will very rarely be
contended and this method is called frequently. | 716 // Must use a tryLock() here too. Don't worry, the lock will very rarely be
contended and this method is called frequently. |
| 717 // The worst that can happen is that there will be some nodes which will tak
e slightly longer than usual to be deleted or removed | 717 // The worst that can happen is that there will be some nodes which will tak
e slightly longer than usual to be deleted or removed |
| 718 // from the render graph (in which case they'll render silence). | 718 // from the render graph (in which case they'll render silence). |
| 719 bool mustReleaseLock; | 719 bool mustReleaseLock; |
| 720 if (tryLock(mustReleaseLock)) { | 720 if (tryLock(mustReleaseLock)) { |
| 721 // Take care of finishing any derefs where the tryLock() failed previous
ly. | 721 // Take care of finishing any derefs where the tryLock() failed previous
ly. |
| 722 handleDeferredFinishDerefs(); | 722 handleDeferredFinishDerefs(); |
| 723 | 723 |
| 724 // Dynamically clean up nodes which are no longer needed. | 724 // Dynamically clean up nodes which are no longer needed. |
| 725 derefFinishedSourceNodes(); | 725 derefFinishedSourceNodes(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 739 } | 739 } |
| 740 } | 740 } |
| 741 | 741 |
| 742 void AudioContext::handleDeferredFinishDerefs() | 742 void AudioContext::handleDeferredFinishDerefs() |
| 743 { | 743 { |
| 744 ASSERT(isAudioThread() && isGraphOwner()); | 744 ASSERT(isAudioThread() && isGraphOwner()); |
| 745 for (unsigned i = 0; i < m_deferredFinishDerefList.size(); ++i) { | 745 for (unsigned i = 0; i < m_deferredFinishDerefList.size(); ++i) { |
| 746 AudioNode* node = m_deferredFinishDerefList[i]; | 746 AudioNode* node = m_deferredFinishDerefList[i]; |
| 747 node->finishDeref(AudioNode::RefTypeConnection); | 747 node->finishDeref(AudioNode::RefTypeConnection); |
| 748 } | 748 } |
| 749 | 749 |
| 750 m_deferredFinishDerefList.clear(); | 750 m_deferredFinishDerefList.clear(); |
| 751 } | 751 } |
| 752 | 752 |
| 753 void AudioContext::markForDeletion(AudioNode* node) | 753 void AudioContext::markForDeletion(AudioNode* node) |
| 754 { | 754 { |
| 755 ASSERT(isGraphOwner()); | 755 ASSERT(isGraphOwner()); |
| 756 | 756 |
| 757 if (isAudioThreadFinished()) | 757 if (isAudioThreadFinished()) |
| 758 m_nodesToDelete.append(node); | 758 m_nodesToDelete.append(node); |
| 759 else | 759 else |
| 760 m_nodesMarkedForDeletion.append(node); | 760 m_nodesMarkedForDeletion.append(node); |
| 761 | 761 |
| 762 // This is probably the best time for us to remove the node from automatic p
ull list, | 762 // This is probably the best time for us to remove the node from automatic p
ull list, |
| 763 // since all connections are gone and we hold the graph lock. Then when hand
lePostRenderTasks() | 763 // since all connections are gone and we hold the graph lock. Then when hand
lePostRenderTasks() |
| 764 // gets a chance to schedule the deletion work, updateAutomaticPullNodes() a
lso gets a chance to | 764 // gets a chance to schedule the deletion work, updateAutomaticPullNodes() a
lso gets a chance to |
| 765 // modify m_renderingAutomaticPullNodes. | 765 // modify m_renderingAutomaticPullNodes. |
| 766 removeAutomaticPullNode(node); | 766 removeAutomaticPullNode(node); |
| 767 } | 767 } |
| 768 | 768 |
| 769 void AudioContext::scheduleNodeDeletion() | 769 void AudioContext::scheduleNodeDeletion() |
| 770 { | 770 { |
| 771 bool isGood = m_isInitialized && isGraphOwner(); | 771 bool isGood = m_isInitialized && isGraphOwner(); |
| 772 ASSERT(isGood); | 772 ASSERT(isGood); |
| 773 if (!isGood) | 773 if (!isGood) |
| 774 return; | 774 return; |
| 775 | 775 |
| 776 // Make sure to call deleteMarkedNodes() on main thread. | 776 // Make sure to call deleteMarkedNodes() on main thread. |
| 777 if (m_nodesMarkedForDeletion.size() && !m_isDeletionScheduled) { | 777 if (m_nodesMarkedForDeletion.size() && !m_isDeletionScheduled) { |
| 778 m_nodesToDelete.append(m_nodesMarkedForDeletion); | 778 m_nodesToDelete.append(m_nodesMarkedForDeletion); |
| 779 m_nodesMarkedForDeletion.clear(); | 779 m_nodesMarkedForDeletion.clear(); |
| 780 | 780 |
| 781 m_isDeletionScheduled = true; | 781 m_isDeletionScheduled = true; |
| 782 | 782 |
| 783 // Don't let ourself get deleted before the callback. | 783 // Don't let ourself get deleted before the callback. |
| 784 // See matching deref() in deleteMarkedNodesDispatch(). | 784 // See matching deref() in deleteMarkedNodesDispatch(). |
| 785 ref(); | 785 ref(); |
| 786 callOnMainThread(deleteMarkedNodesDispatch, this); | 786 callOnMainThread(deleteMarkedNodesDispatch, this); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 823 | 823 |
| 824 // Finally, delete it. | 824 // Finally, delete it. |
| 825 delete node; | 825 delete node; |
| 826 } | 826 } |
| 827 m_isDeletionScheduled = false; | 827 m_isDeletionScheduled = false; |
| 828 } | 828 } |
| 829 } | 829 } |
| 830 | 830 |
| 831 void AudioContext::markSummingJunctionDirty(AudioSummingJunction* summingJunctio
n) | 831 void AudioContext::markSummingJunctionDirty(AudioSummingJunction* summingJunctio
n) |
| 832 { | 832 { |
| 833 ASSERT(isGraphOwner()); | 833 ASSERT(isGraphOwner()); |
| 834 m_dirtySummingJunctions.add(summingJunction); | 834 m_dirtySummingJunctions.add(summingJunction); |
| 835 } | 835 } |
| 836 | 836 |
| 837 void AudioContext::removeMarkedSummingJunction(AudioSummingJunction* summingJunc
tion) | 837 void AudioContext::removeMarkedSummingJunction(AudioSummingJunction* summingJunc
tion) |
| 838 { | 838 { |
| 839 ASSERT(isMainThread()); | 839 ASSERT(isMainThread()); |
| 840 AutoLocker locker(this); | 840 AutoLocker locker(this); |
| 841 m_dirtySummingJunctions.remove(summingJunction); | 841 m_dirtySummingJunctions.remove(summingJunction); |
| 842 } | 842 } |
| 843 | 843 |
| 844 void AudioContext::markAudioNodeOutputDirty(AudioNodeOutput* output) | 844 void AudioContext::markAudioNodeOutputDirty(AudioNodeOutput* output) |
| 845 { | 845 { |
| 846 ASSERT(isGraphOwner()); | 846 ASSERT(isGraphOwner()); |
| 847 m_dirtyAudioNodeOutputs.add(output); | 847 m_dirtyAudioNodeOutputs.add(output); |
| 848 } | 848 } |
| 849 | 849 |
| 850 void AudioContext::handleDirtyAudioSummingJunctions() | 850 void AudioContext::handleDirtyAudioSummingJunctions() |
| 851 { | 851 { |
| 852 ASSERT(isGraphOwner()); | 852 ASSERT(isGraphOwner()); |
| 853 | 853 |
| 854 for (HashSet<AudioSummingJunction*>::iterator i = m_dirtySummingJunctions.be
gin(); i != m_dirtySummingJunctions.end(); ++i) | 854 for (HashSet<AudioSummingJunction*>::iterator i = m_dirtySummingJunctions.be
gin(); i != m_dirtySummingJunctions.end(); ++i) |
| 855 (*i)->updateRenderingState(); | 855 (*i)->updateRenderingState(); |
| 856 | 856 |
| 857 m_dirtySummingJunctions.clear(); | 857 m_dirtySummingJunctions.clear(); |
| 858 } | 858 } |
| 859 | 859 |
| 860 void AudioContext::handleDirtyAudioNodeOutputs() | 860 void AudioContext::handleDirtyAudioNodeOutputs() |
| 861 { | 861 { |
| 862 ASSERT(isGraphOwner()); | 862 ASSERT(isGraphOwner()); |
| 863 | 863 |
| 864 for (HashSet<AudioNodeOutput*>::iterator i = m_dirtyAudioNodeOutputs.begin()
; i != m_dirtyAudioNodeOutputs.end(); ++i) | 864 for (HashSet<AudioNodeOutput*>::iterator i = m_dirtyAudioNodeOutputs.begin()
; i != m_dirtyAudioNodeOutputs.end(); ++i) |
| 865 (*i)->updateRenderingState(); | 865 (*i)->updateRenderingState(); |
| 866 | 866 |
| 867 m_dirtyAudioNodeOutputs.clear(); | 867 m_dirtyAudioNodeOutputs.clear(); |
| 868 } | 868 } |
| 869 | 869 |
| 870 void AudioContext::addAutomaticPullNode(AudioNode* node) | 870 void AudioContext::addAutomaticPullNode(AudioNode* node) |
| 871 { | 871 { |
| 872 ASSERT(isGraphOwner()); | 872 ASSERT(isGraphOwner()); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 926 void AudioContext::startRendering() | 926 void AudioContext::startRendering() |
| 927 { | 927 { |
| 928 destination()->startRendering(); | 928 destination()->startRendering(); |
| 929 } | 929 } |
| 930 | 930 |
| 931 void AudioContext::fireCompletionEvent() | 931 void AudioContext::fireCompletionEvent() |
| 932 { | 932 { |
| 933 ASSERT(isMainThread()); | 933 ASSERT(isMainThread()); |
| 934 if (!isMainThread()) | 934 if (!isMainThread()) |
| 935 return; | 935 return; |
| 936 | 936 |
| 937 AudioBuffer* renderedBuffer = m_renderTarget.get(); | 937 AudioBuffer* renderedBuffer = m_renderTarget.get(); |
| 938 | 938 |
| 939 ASSERT(renderedBuffer); | 939 ASSERT(renderedBuffer); |
| 940 if (!renderedBuffer) | 940 if (!renderedBuffer) |
| 941 return; | 941 return; |
| 942 | 942 |
| 943 // Avoid firing the event if the document has already gone away. | 943 // Avoid firing the event if the document has already gone away. |
| 944 if (scriptExecutionContext()) { | 944 if (scriptExecutionContext()) { |
| 945 // Call the offline rendering completion event listener. | 945 // Call the offline rendering completion event listener. |
| 946 dispatchEvent(OfflineAudioCompletionEvent::create(renderedBuffer)); | 946 dispatchEvent(OfflineAudioCompletionEvent::create(renderedBuffer)); |
| 947 } | 947 } |
| 948 } | 948 } |
| 949 | 949 |
| 950 void AudioContext::incrementActiveSourceCount() | 950 void AudioContext::incrementActiveSourceCount() |
| 951 { | 951 { |
| 952 atomicIncrement(&m_activeSourceCount); | 952 atomicIncrement(&m_activeSourceCount); |
| 953 } | 953 } |
| 954 | 954 |
| 955 void AudioContext::decrementActiveSourceCount() | 955 void AudioContext::decrementActiveSourceCount() |
| 956 { | 956 { |
| 957 atomicDecrement(&m_activeSourceCount); | 957 atomicDecrement(&m_activeSourceCount); |
| 958 } | 958 } |
| 959 | 959 |
| 960 } // namespace WebCore | 960 } // namespace WebCore |
| 961 | 961 |
| 962 #endif // ENABLE(WEB_AUDIO) | 962 #endif // ENABLE(WEB_AUDIO) |
| OLD | NEW |