Chromium Code Reviews| 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 712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 723 } | 723 } |
| 724 | 724 |
| 725 void AudioContext::notifyStateChange() | 725 void AudioContext::notifyStateChange() |
| 726 { | 726 { |
| 727 dispatchEvent(Event::create(EventTypeNames::statechange)); | 727 dispatchEvent(Event::create(EventTypeNames::statechange)); |
| 728 } | 728 } |
| 729 | 729 |
| 730 ScriptPromise AudioContext::suspendContext(ScriptState* scriptState) | 730 ScriptPromise AudioContext::suspendContext(ScriptState* scriptState) |
| 731 { | 731 { |
| 732 ASSERT(isMainThread()); | 732 ASSERT(isMainThread()); |
| 733 ASSERT(!isOfflineContext()); | |
| 734 | |
| 733 AutoLocker locker(this); | 735 AutoLocker locker(this); |
| 734 | 736 |
| 735 if (isOfflineContext()) { | |
| 736 return ScriptPromise::rejectWithDOMException( | |
| 737 scriptState, | |
| 738 DOMException::create( | |
| 739 InvalidAccessError, | |
| 740 "cannot suspend an OfflineAudioContext")); | |
| 741 } | |
| 742 | |
| 743 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver:: create(scriptState); | 737 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver:: create(scriptState); |
| 744 ScriptPromise promise = resolver->promise(); | 738 ScriptPromise promise = resolver->promise(); |
| 745 | 739 |
| 746 if (m_contextState == Closed) { | 740 if (m_contextState == Closed) { |
| 747 resolver->reject( | 741 resolver->reject( |
| 748 DOMException::create(InvalidStateError, "Cannot suspend a context th at has been closed")); | 742 DOMException::create(InvalidStateError, "Cannot suspend a context th at has been closed")); |
| 749 } else { | 743 } else { |
| 750 // Stop rendering now. | 744 // Stop rendering now. |
| 751 if (m_destinationNode) | 745 if (m_destinationNode) |
| 752 stopRendering(); | 746 stopRendering(); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 847 } | 841 } |
| 848 } | 842 } |
| 849 } | 843 } |
| 850 | 844 |
| 851 void AudioContext::handlePreRenderTasks() | 845 void AudioContext::handlePreRenderTasks() |
| 852 { | 846 { |
| 853 ASSERT(isAudioThread()); | 847 ASSERT(isAudioThread()); |
| 854 | 848 |
| 855 // At the beginning of every render quantum, try to update the internal rend ering graph state (from main thread changes). | 849 // At the beginning of every render quantum, try to update the internal rend ering graph state (from main thread changes). |
| 856 // It's OK if the tryLock() fails, we'll just take slightly longer to pick u p the changes. | 850 // It's OK if the tryLock() fails, we'll just take slightly longer to pick u p the changes. |
| 857 if (tryLock()) { | 851 if (!isOfflineContext() && tryLock()) { |
|
Raymond Toy
2015/06/12 21:11:36
Add comment on why we have this test now for isOff
hongchan
2015/06/15 18:40:46
Done.
| |
| 858 deferredTaskHandler().handleDeferredTasks(); | 852 deferredTaskHandler().handleDeferredTasks(); |
| 859 | 853 |
| 860 resolvePromisesForResume(); | 854 resolvePromisesForResume(); |
| 861 | 855 |
| 862 // Check to see if source nodes can be stopped because the end time has passed. | 856 // Check to see if source nodes can be stopped because the end time has passed. |
| 863 handleStoppableSourceNodes(); | 857 handleStoppableSourceNodes(); |
| 864 | 858 |
| 865 unlock(); | 859 unlock(); |
| 860 | |
| 861 return; | |
| 866 } | 862 } |
| 863 | |
| 864 // If this is Offline Audio Context, simply lock the graph and do the tasks. | |
|
Raymond Toy
2015/06/12 21:11:36
I think this is wrong. If we're running online, a
hongchan
2015/06/15 18:40:46
Done.
| |
| 865 deferredTaskHandler().forceLock(); | |
| 866 | |
| 867 deferredTaskHandler().handleDeferredTasks(); | |
| 868 resolvePromisesForResume(); | |
| 869 handleStoppableSourceNodes(); | |
| 870 | |
| 871 unlock(); | |
| 867 } | 872 } |
| 868 | 873 |
| 869 void AudioContext::handlePostRenderTasks() | 874 void AudioContext::handlePostRenderTasks() |
| 870 { | 875 { |
| 871 ASSERT(isAudioThread()); | 876 ASSERT(isAudioThread()); |
| 872 | 877 |
| 873 // Must use a tryLock() here too. Don't worry, the lock will very rarely be contended and this method is called frequently. | 878 // Must use a tryLock() here too. Don't worry, the lock will very rarely be contended and this method is called frequently. |
| 874 // 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 | 879 // 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 |
| 875 // from the render graph (in which case they'll render silence). | 880 // from the render graph (in which case they'll render silence). |
| 876 if (tryLock()) { | 881 if (!isOfflineContext() && tryLock()) { |
|
Raymond Toy
2015/06/12 21:11:36
Same comment as for handlePreRenderTasks(). And f
hongchan
2015/06/15 18:40:46
Done.
| |
| 877 // Take care of AudioNode tasks where the tryLock() failed previously. | 882 // Take care of AudioNode tasks where the tryLock() failed previously. |
| 878 deferredTaskHandler().breakConnections(); | 883 deferredTaskHandler().breakConnections(); |
| 879 | 884 |
| 880 // Dynamically clean up nodes which are no longer needed. | 885 // Dynamically clean up nodes which are no longer needed. |
| 881 releaseFinishedSourceNodes(); | 886 releaseFinishedSourceNodes(); |
| 882 | 887 |
| 883 deferredTaskHandler().handleDeferredTasks(); | 888 deferredTaskHandler().handleDeferredTasks(); |
| 884 deferredTaskHandler().requestToDeleteHandlersOnMainThread(); | 889 deferredTaskHandler().requestToDeleteHandlersOnMainThread(); |
| 885 | 890 |
| 886 unlock(); | 891 unlock(); |
| 892 | |
| 893 return; | |
| 887 } | 894 } |
| 895 | |
| 896 // If this is Offline Audio Context, simply lock the graph and do the tasks. | |
| 897 deferredTaskHandler().forceLock(); | |
| 898 | |
| 899 deferredTaskHandler().breakConnections(); | |
| 900 releaseFinishedSourceNodes(); | |
| 901 deferredTaskHandler().handleDeferredTasks(); | |
| 902 deferredTaskHandler().requestToDeleteHandlersOnMainThread(); | |
| 903 | |
| 904 unlock(); | |
| 888 } | 905 } |
| 889 | 906 |
| 890 void AudioContext::resolvePromisesForResumeOnMainThread() | 907 void AudioContext::resolvePromisesForResumeOnMainThread() |
| 891 { | 908 { |
| 892 ASSERT(isMainThread()); | 909 ASSERT(isMainThread()); |
| 893 AutoLocker locker(this); | 910 AutoLocker locker(this); |
| 894 | 911 |
| 895 for (auto& resolver : m_resumeResolvers) { | 912 for (auto& resolver : m_resumeResolvers) { |
| 896 if (m_contextState == Closed) { | 913 if (m_contextState == Closed) { |
| 897 resolver->reject( | 914 resolver->reject( |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 938 return EventTargetNames::AudioContext; | 955 return EventTargetNames::AudioContext; |
| 939 } | 956 } |
| 940 | 957 |
| 941 ExecutionContext* AudioContext::executionContext() const | 958 ExecutionContext* AudioContext::executionContext() const |
| 942 { | 959 { |
| 943 return m_isStopScheduled ? 0 : ActiveDOMObject::executionContext(); | 960 return m_isStopScheduled ? 0 : ActiveDOMObject::executionContext(); |
| 944 } | 961 } |
| 945 | 962 |
| 946 void AudioContext::startRendering() | 963 void AudioContext::startRendering() |
| 947 { | 964 { |
| 948 // This is called for both online and offline contexts. | 965 // This is only for the real-time context. |
| 949 ASSERT(isMainThread()); | 966 ASSERT(isMainThread()); |
| 950 ASSERT(m_destinationNode); | 967 ASSERT(m_destinationNode); |
| 968 ASSERT(!isOfflineContext()); | |
| 951 | 969 |
| 952 if (m_contextState == Suspended) { | 970 if (m_contextState == Suspended) { |
| 953 destination()->audioDestinationHandler().startRendering(); | 971 destination()->audioDestinationHandler().startRendering(); |
| 954 setContextState(Running); | 972 setContextState(Running); |
| 955 } | 973 } |
| 956 } | 974 } |
| 957 | 975 |
| 958 void AudioContext::stopRendering() | 976 void AudioContext::stopRendering() |
| 959 { | 977 { |
| 960 ASSERT(isMainThread()); | 978 ASSERT(isMainThread()); |
| 961 ASSERT(m_destinationNode); | 979 ASSERT(m_destinationNode); |
| 962 ASSERT(!isOfflineContext()); | 980 ASSERT(!isOfflineContext()); |
| 963 | 981 |
| 964 if (m_contextState == Running) { | 982 if (m_contextState == Running) { |
| 965 destination()->audioDestinationHandler().stopRendering(); | 983 destination()->audioDestinationHandler().stopRendering(); |
| 966 setContextState(Suspended); | 984 setContextState(Suspended); |
| 967 deferredTaskHandler().clearHandlersToBeDeleted(); | 985 deferredTaskHandler().clearHandlersToBeDeleted(); |
| 968 } | 986 } |
| 969 } | 987 } |
| 970 | 988 |
| 971 void AudioContext::fireCompletionEvent() | 989 void AudioContext::fireCompletionEvent() |
| 972 { | 990 { |
| 973 ASSERT(isMainThread()); | 991 ASSERT_WITH_MESSAGE(1, "fireCompletionEvent() only valid for offline audio c ontext"); |
| 974 if (!isMainThread()) | 992 } |
| 975 return; | |
| 976 | 993 |
| 977 AudioBuffer* renderedBuffer = m_renderTarget.get(); | 994 bool AudioContext::shouldSuspendNow() |
| 995 { | |
| 996 ASSERT_WITH_MESSAGE(1, "shouldSuspendNow() only valid for offline audio cont ext"); | |
| 997 return false; | |
| 998 } | |
| 978 | 999 |
| 979 // For an offline context, we set the state to closed here so that the oncom plete handler sees | 1000 void AudioContext::resolvePendingSuspendPromises() |
| 980 // that the context has been closed. | 1001 { |
| 981 setContextState(Closed); | 1002 ASSERT_WITH_MESSAGE(1, "clearResolvedSuspend() only valid for offline audio context"); |
| 982 | |
| 983 ASSERT(renderedBuffer); | |
| 984 if (!renderedBuffer) | |
| 985 return; | |
| 986 | |
| 987 // Avoid firing the event if the document has already gone away. | |
| 988 if (executionContext()) { | |
| 989 // Call the offline rendering completion event listener and resolve the promise too. | |
| 990 dispatchEvent(OfflineAudioCompletionEvent::create(renderedBuffer)); | |
| 991 m_offlineResolver->resolve(renderedBuffer); | |
| 992 } | |
| 993 } | 1003 } |
| 994 | 1004 |
| 995 DEFINE_TRACE(AudioContext) | 1005 DEFINE_TRACE(AudioContext) |
| 996 { | 1006 { |
| 997 visitor->trace(m_closeResolver); | 1007 visitor->trace(m_closeResolver); |
| 998 visitor->trace(m_offlineResolver); | |
| 999 visitor->trace(m_renderTarget); | 1008 visitor->trace(m_renderTarget); |
| 1000 visitor->trace(m_destinationNode); | 1009 visitor->trace(m_destinationNode); |
| 1001 visitor->trace(m_listener); | 1010 visitor->trace(m_listener); |
| 1002 // trace() can be called in AudioContext constructor, and | 1011 // trace() can be called in AudioContext constructor, and |
| 1003 // m_contextGraphMutex might be unavailable. | 1012 // m_contextGraphMutex might be unavailable. |
| 1004 if (m_didInitializeContextGraphMutex) { | 1013 if (m_didInitializeContextGraphMutex) { |
| 1005 AutoLocker lock(this); | 1014 AutoLocker lock(this); |
| 1006 visitor->trace(m_activeSourceNodes); | 1015 visitor->trace(m_activeSourceNodes); |
| 1007 } else { | 1016 } else { |
| 1008 visitor->trace(m_activeSourceNodes); | 1017 visitor->trace(m_activeSourceNodes); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1045 // the destination node can GCed if JS has no references. stop() will also r esolve the Promise | 1054 // the destination node can GCed if JS has no references. stop() will also r esolve the Promise |
| 1046 // created here. | 1055 // created here. |
| 1047 stop(); | 1056 stop(); |
| 1048 | 1057 |
| 1049 return promise; | 1058 return promise; |
| 1050 } | 1059 } |
| 1051 | 1060 |
| 1052 } // namespace blink | 1061 } // namespace blink |
| 1053 | 1062 |
| 1054 #endif // ENABLE(WEB_AUDIO) | 1063 #endif // ENABLE(WEB_AUDIO) |
| OLD | NEW |