| 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 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 AudioContext::~AudioContext() | 144 AudioContext::~AudioContext() |
| 145 { | 145 { |
| 146 #if DEBUG_AUDIONODE_REFERENCES | 146 #if DEBUG_AUDIONODE_REFERENCES |
| 147 fprintf(stderr, "%p: AudioContext::~AudioContext(): %u\n", this, m_contextId
); | 147 fprintf(stderr, "%p: AudioContext::~AudioContext(): %u\n", this, m_contextId
); |
| 148 #endif | 148 #endif |
| 149 deferredTaskHandler().contextWillBeDestroyed(); | 149 deferredTaskHandler().contextWillBeDestroyed(); |
| 150 // AudioNodes keep a reference to their context, so there should be no way t
o be in the destructor if there are still AudioNodes around. | 150 // AudioNodes keep a reference to their context, so there should be no way t
o be in the destructor if there are still AudioNodes around. |
| 151 ASSERT(!m_isInitialized); | 151 ASSERT(!m_isInitialized); |
| 152 ASSERT(!m_activeSourceNodes.size()); | 152 ASSERT(!m_activeSourceNodes.size()); |
| 153 ASSERT(!m_finishedSourceHandlers.size()); | 153 ASSERT(!m_finishedSourceHandlers.size()); |
| 154 ASSERT(!m_suspendResolvers.size()); | |
| 155 ASSERT(!m_isResolvingResumePromises); | 154 ASSERT(!m_isResolvingResumePromises); |
| 156 ASSERT(!m_resumeResolvers.size()); | 155 ASSERT(!m_resumeResolvers.size()); |
| 157 } | 156 } |
| 158 | 157 |
| 159 void AudioContext::initialize() | 158 void AudioContext::initialize() |
| 160 { | 159 { |
| 161 if (isInitialized()) | 160 if (isInitialized()) |
| 162 return; | 161 return; |
| 163 | 162 |
| 164 FFTFrame::initialize(); | 163 FFTFrame::initialize(); |
| (...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 755 return ScriptPromise::rejectWithDOMException( | 754 return ScriptPromise::rejectWithDOMException( |
| 756 scriptState, | 755 scriptState, |
| 757 DOMException::create( | 756 DOMException::create( |
| 758 InvalidAccessError, | 757 InvalidAccessError, |
| 759 "cannot suspend an OfflineAudioContext")); | 758 "cannot suspend an OfflineAudioContext")); |
| 760 } | 759 } |
| 761 | 760 |
| 762 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::
create(scriptState); | 761 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::
create(scriptState); |
| 763 ScriptPromise promise = resolver->promise(); | 762 ScriptPromise promise = resolver->promise(); |
| 764 | 763 |
| 765 // Save the resolver. If the context is running, it will get resolved at th
e end of a rendering | 764 if (m_contextState == Closed) { |
| 766 // quantum. Otherwise, resolve it now. | 765 resolver->reject( |
| 767 m_suspendResolvers.append(resolver); | 766 DOMException::create(InvalidStateError, "Cannot suspend a context th
at has been closed")); |
| 767 } else { |
| 768 // Stop rendering now. |
| 769 if (m_destinationNode) |
| 770 stopRendering(); |
| 768 | 771 |
| 769 if (m_contextState != Running) { | 772 // Since we don't have any way of knowing when the hardware actually sto
ps, we'll just |
| 770 // Context is not running so we can't wait for a rendering quantum to re
solve the | 773 // resolve the promise now. |
| 771 // promise. Just resolve it now (along with any other pending suspend pr
omises). | 774 resolver->resolve(); |
| 772 resolvePromisesForSuspendOnMainThread(); | |
| 773 } | 775 } |
| 774 | 776 |
| 775 return promise; | 777 return promise; |
| 776 } | 778 } |
| 777 | 779 |
| 778 ScriptPromise AudioContext::resumeContext(ScriptState* scriptState) | 780 ScriptPromise AudioContext::resumeContext(ScriptState* scriptState) |
| 779 { | 781 { |
| 780 ASSERT(isMainThread()); | 782 ASSERT(isMainThread()); |
| 781 AutoLocker locker(this); | 783 AutoLocker locker(this); |
| 782 | 784 |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 895 if (tryLock()) { | 897 if (tryLock()) { |
| 896 // Take care of AudioNode tasks where the tryLock() failed previously. | 898 // Take care of AudioNode tasks where the tryLock() failed previously. |
| 897 deferredTaskHandler().breakConnections(); | 899 deferredTaskHandler().breakConnections(); |
| 898 | 900 |
| 899 // Dynamically clean up nodes which are no longer needed. | 901 // Dynamically clean up nodes which are no longer needed. |
| 900 releaseFinishedSourceNodes(); | 902 releaseFinishedSourceNodes(); |
| 901 | 903 |
| 902 deferredTaskHandler().handleDeferredTasks(); | 904 deferredTaskHandler().handleDeferredTasks(); |
| 903 deferredTaskHandler().requestToDeleteHandlersOnMainThread(); | 905 deferredTaskHandler().requestToDeleteHandlersOnMainThread(); |
| 904 | 906 |
| 905 resolvePromisesForSuspend(); | |
| 906 | |
| 907 unlock(); | 907 unlock(); |
| 908 } | 908 } |
| 909 } | 909 } |
| 910 | 910 |
| 911 void AudioContext::resolvePromisesForResumeOnMainThread() | 911 void AudioContext::resolvePromisesForResumeOnMainThread() |
| 912 { | 912 { |
| 913 ASSERT(isMainThread()); | 913 ASSERT(isMainThread()); |
| 914 AutoLocker locker(this); | 914 AutoLocker locker(this); |
| 915 | 915 |
| 916 for (auto& resolver : m_resumeResolvers) { | 916 for (auto& resolver : m_resumeResolvers) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 934 | 934 |
| 935 // Resolve any pending promises created by resume(). Only do this if we have
n't already started | 935 // Resolve any pending promises created by resume(). Only do this if we have
n't already started |
| 936 // resolving these promises. This gets called very often and it takes some t
ime to resolve the | 936 // resolving these promises. This gets called very often and it takes some t
ime to resolve the |
| 937 // promises in the main thread. | 937 // promises in the main thread. |
| 938 if (!m_isResolvingResumePromises && m_resumeResolvers.size() > 0) { | 938 if (!m_isResolvingResumePromises && m_resumeResolvers.size() > 0) { |
| 939 m_isResolvingResumePromises = true; | 939 m_isResolvingResumePromises = true; |
| 940 Platform::current()->mainThread()->postTask(FROM_HERE, threadSafeBind(&A
udioContext::resolvePromisesForResumeOnMainThread, this)); | 940 Platform::current()->mainThread()->postTask(FROM_HERE, threadSafeBind(&A
udioContext::resolvePromisesForResumeOnMainThread, this)); |
| 941 } | 941 } |
| 942 } | 942 } |
| 943 | 943 |
| 944 void AudioContext::resolvePromisesForSuspendOnMainThread() | |
| 945 { | |
| 946 ASSERT(isMainThread()); | |
| 947 AutoLocker locker(this); | |
| 948 | |
| 949 // We can stop rendering now. | |
| 950 if (m_destinationNode) | |
| 951 stopRendering(); | |
| 952 | |
| 953 for (auto& resolver : m_suspendResolvers) { | |
| 954 if (m_contextState == Closed) { | |
| 955 resolver->reject( | |
| 956 DOMException::create(InvalidStateError, "Cannot suspend a contex
t that has been closed")); | |
| 957 } else { | |
| 958 resolver->resolve(); | |
| 959 } | |
| 960 } | |
| 961 | |
| 962 m_suspendResolvers.clear(); | |
| 963 } | |
| 964 | |
| 965 void AudioContext::resolvePromisesForSuspend() | |
| 966 { | |
| 967 // This runs inside the AudioContext's lock when handling pre-render tasks. | |
| 968 ASSERT(isAudioThread()); | |
| 969 ASSERT(isGraphOwner()); | |
| 970 | |
| 971 // Resolve any pending promises created by suspend() | |
| 972 if (m_suspendResolvers.size() > 0) | |
| 973 Platform::current()->mainThread()->postTask(FROM_HERE, threadSafeBind(&A
udioContext::resolvePromisesForSuspendOnMainThread, this)); | |
| 974 } | |
| 975 | |
| 976 void AudioContext::rejectPendingResolvers() | 944 void AudioContext::rejectPendingResolvers() |
| 977 { | 945 { |
| 978 ASSERT(isMainThread()); | 946 ASSERT(isMainThread()); |
| 979 | 947 |
| 980 // Audio context is closing down so reject any suspend or resume promises th
at are still | 948 // Audio context is closing down so reject any resume promises that are stil
l pending. |
| 981 // pending. | |
| 982 | |
| 983 for (auto& resolver : m_suspendResolvers) { | |
| 984 resolver->reject(DOMException::create(InvalidStateError, "Audio context
is going away")); | |
| 985 } | |
| 986 m_suspendResolvers.clear(); | |
| 987 | 949 |
| 988 for (auto& resolver : m_resumeResolvers) { | 950 for (auto& resolver : m_resumeResolvers) { |
| 989 resolver->reject(DOMException::create(InvalidStateError, "Audio context
is going away")); | 951 resolver->reject(DOMException::create(InvalidStateError, "Audio context
is going away")); |
| 990 } | 952 } |
| 991 m_resumeResolvers.clear(); | 953 m_resumeResolvers.clear(); |
| 992 m_isResolvingResumePromises = false; | 954 m_isResolvingResumePromises = false; |
| 993 } | 955 } |
| 994 | 956 |
| 995 const AtomicString& AudioContext::interfaceName() const | 957 const AtomicString& AudioContext::interfaceName() const |
| 996 { | 958 { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1060 visitor->trace(m_listener); | 1022 visitor->trace(m_listener); |
| 1061 // trace() can be called in AudioContext constructor, and | 1023 // trace() can be called in AudioContext constructor, and |
| 1062 // m_contextGraphMutex might be unavailable. | 1024 // m_contextGraphMutex might be unavailable. |
| 1063 if (m_didInitializeContextGraphMutex) { | 1025 if (m_didInitializeContextGraphMutex) { |
| 1064 AutoLocker lock(this); | 1026 AutoLocker lock(this); |
| 1065 visitor->trace(m_activeSourceNodes); | 1027 visitor->trace(m_activeSourceNodes); |
| 1066 } else { | 1028 } else { |
| 1067 visitor->trace(m_activeSourceNodes); | 1029 visitor->trace(m_activeSourceNodes); |
| 1068 } | 1030 } |
| 1069 visitor->trace(m_resumeResolvers); | 1031 visitor->trace(m_resumeResolvers); |
| 1070 visitor->trace(m_suspendResolvers); | |
| 1071 RefCountedGarbageCollectedEventTargetWithInlineData<AudioContext>::trace(vis
itor); | 1032 RefCountedGarbageCollectedEventTargetWithInlineData<AudioContext>::trace(vis
itor); |
| 1072 ActiveDOMObject::trace(visitor); | 1033 ActiveDOMObject::trace(visitor); |
| 1073 } | 1034 } |
| 1074 | 1035 |
| 1075 SecurityOrigin* AudioContext::securityOrigin() const | 1036 SecurityOrigin* AudioContext::securityOrigin() const |
| 1076 { | 1037 { |
| 1077 if (executionContext()) | 1038 if (executionContext()) |
| 1078 return executionContext()->securityOrigin(); | 1039 return executionContext()->securityOrigin(); |
| 1079 | 1040 |
| 1080 return nullptr; | 1041 return nullptr; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1105 // the destination node can GCed if JS has no references. stop() will also r
esolve the Promise | 1066 // the destination node can GCed if JS has no references. stop() will also r
esolve the Promise |
| 1106 // created here. | 1067 // created here. |
| 1107 stop(); | 1068 stop(); |
| 1108 | 1069 |
| 1109 return promise; | 1070 return promise; |
| 1110 } | 1071 } |
| 1111 | 1072 |
| 1112 } // namespace blink | 1073 } // namespace blink |
| 1113 | 1074 |
| 1114 #endif // ENABLE(WEB_AUDIO) | 1075 #endif // ENABLE(WEB_AUDIO) |
| OLD | NEW |