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 |