| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "config.h" | 5 #include "config.h" |
| 6 #include "modules/webaudio/AudioContext.h" | 6 #include "modules/webaudio/AudioContext.h" |
| 7 | 7 |
| 8 #include "bindings/core/v8/ExceptionMessages.h" | 8 #include "bindings/core/v8/ExceptionMessages.h" |
| 9 #include "bindings/core/v8/ExceptionState.h" | 9 #include "bindings/core/v8/ExceptionState.h" |
| 10 #include "bindings/core/v8/ScriptPromiseResolver.h" | 10 #include "bindings/core/v8/ScriptPromiseResolver.h" |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 fprintf(stderr, "%p: AudioContext::~AudioContext(): %u\n", this, m_contextId
); | 70 fprintf(stderr, "%p: AudioContext::~AudioContext(): %u\n", this, m_contextId
); |
| 71 #endif | 71 #endif |
| 72 } | 72 } |
| 73 | 73 |
| 74 DEFINE_TRACE(AudioContext) | 74 DEFINE_TRACE(AudioContext) |
| 75 { | 75 { |
| 76 visitor->trace(m_closeResolver); | 76 visitor->trace(m_closeResolver); |
| 77 AbstractAudioContext::trace(visitor); | 77 AbstractAudioContext::trace(visitor); |
| 78 } | 78 } |
| 79 | 79 |
| 80 ScriptPromise AudioContext::closeContext(ScriptState* scriptState) |
| 81 { |
| 82 if (isContextClosed()) { |
| 83 // We've already closed the context previously, but it hasn't yet been r
esolved, so just |
| 84 // create a new promise and reject it. |
| 85 return ScriptPromise::rejectWithDOMException( |
| 86 scriptState, |
| 87 DOMException::create(InvalidStateError, |
| 88 "Cannot close a context that is being closed or has already been
closed.")); |
| 89 } |
| 90 |
| 91 m_closeResolver = ScriptPromiseResolver::create(scriptState); |
| 92 ScriptPromise promise = m_closeResolver->promise(); |
| 93 |
| 94 // Stop the audio context. This will stop the destination node from pulling
audio anymore. And |
| 95 // since we have disconnected the destination from the audio graph, and thus
has no references, |
| 96 // the destination node can GCed if JS has no references. uninitialize() wil
l also resolve the Promise |
| 97 // created here. |
| 98 uninitialize(); |
| 99 |
| 100 return promise; |
| 101 } |
| 102 |
| 80 ScriptPromise AudioContext::suspendContext(ScriptState* scriptState) | 103 ScriptPromise AudioContext::suspendContext(ScriptState* scriptState) |
| 81 { | 104 { |
| 82 ASSERT(isMainThread()); | 105 ASSERT(isMainThread()); |
| 83 AutoLocker locker(this); | 106 AutoLocker locker(this); |
| 84 | 107 |
| 85 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::
create(scriptState); | 108 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::
create(scriptState); |
| 86 ScriptPromise promise = resolver->promise(); | 109 ScriptPromise promise = resolver->promise(); |
| 87 | 110 |
| 88 if (contextState() == Closed) { | 111 if (contextState() == Closed) { |
| 89 resolver->reject( | 112 resolver->reject( |
| 90 DOMException::create(InvalidStateError, "Cannot suspend a context th
at has been closed")); | 113 DOMException::create(InvalidStateError, "Cannot suspend a context th
at has been closed")); |
| 91 } else { | 114 } else { |
| 92 // Stop rendering now. | 115 // Stop rendering now. |
| 93 if (destination()) | 116 if (destination()) |
| 94 stopRendering(); | 117 stopRendering(); |
| 95 | 118 |
| 96 // Since we don't have any way of knowing when the hardware actually sto
ps, we'll just | 119 // Since we don't have any way of knowing when the hardware actually sto
ps, we'll just |
| 97 // resolve the promise now. | 120 // resolve the promise now. |
| 98 resolver->resolve(); | 121 resolver->resolve(); |
| 99 } | 122 } |
| 100 | 123 |
| 101 return promise; | 124 return promise; |
| 102 } | 125 } |
| 103 | 126 |
| 127 ScriptPromise AudioContext::suspendContext(ScriptState* scriptState, double susp
endTime) |
| 128 { |
| 129 // This CANNOT be called on AudioContext; it is to implement the pure |
| 130 // virtual interface from AbstractAudioContext. |
| 131 RELEASE_ASSERT_NOT_REACHED(); |
| 132 |
| 133 return ScriptPromise(); |
| 134 } |
| 135 |
| 104 ScriptPromise AudioContext::resumeContext(ScriptState* scriptState) | 136 ScriptPromise AudioContext::resumeContext(ScriptState* scriptState) |
| 105 { | 137 { |
| 106 ASSERT(isMainThread()); | 138 ASSERT(isMainThread()); |
| 107 | 139 |
| 108 if (isContextClosed()) { | 140 if (isContextClosed()) { |
| 109 return ScriptPromise::rejectWithDOMException( | 141 return ScriptPromise::rejectWithDOMException( |
| 110 scriptState, | 142 scriptState, |
| 111 DOMException::create( | 143 DOMException::create( |
| 112 InvalidAccessError, | 144 InvalidAccessError, |
| 113 "cannot resume a closed AudioContext")); | 145 "cannot resume a closed AudioContext")); |
| 114 } | 146 } |
| 115 | 147 |
| 116 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::
create(scriptState); | 148 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::
create(scriptState); |
| 117 ScriptPromise promise = resolver->promise(); | 149 ScriptPromise promise = resolver->promise(); |
| 118 | 150 |
| 119 // Restart the destination node to pull on the audio graph. | 151 // Restart the destination node to pull on the audio graph. |
| 120 if (destination()) | 152 if (destination()) |
| 121 startRendering(); | 153 startRendering(); |
| 122 | 154 |
| 123 // Save the resolver which will get resolved when the destination node start
s pulling on the | 155 // Save the resolver which will get resolved when the destination node start
s pulling on the |
| 124 // graph again. | 156 // graph again. |
| 125 { | 157 { |
| 126 AutoLocker locker(this); | 158 AutoLocker(this); |
| 127 m_resumeResolvers.append(resolver); | 159 m_resumeResolvers.append(resolver); |
| 128 } | 160 } |
| 129 | 161 |
| 130 return promise; | 162 return promise; |
| 131 } | 163 } |
| 132 | 164 |
| 133 ScriptPromise AudioContext::closeContext(ScriptState* scriptState) | |
| 134 { | |
| 135 if (isContextClosed()) { | |
| 136 // We've already closed the context previously, but it hasn't yet been r
esolved, so just | |
| 137 // create a new promise and reject it. | |
| 138 return ScriptPromise::rejectWithDOMException( | |
| 139 scriptState, | |
| 140 DOMException::create(InvalidStateError, | |
| 141 "Cannot close a context that is being closed or has already been
closed.")); | |
| 142 } | |
| 143 | |
| 144 m_closeResolver = ScriptPromiseResolver::create(scriptState); | |
| 145 ScriptPromise promise = m_closeResolver->promise(); | |
| 146 | |
| 147 // Stop the audio context. This will stop the destination node from pulling
audio anymore. And | |
| 148 // since we have disconnected the destination from the audio graph, and thus
has no references, | |
| 149 // the destination node can GCed if JS has no references. uninitialize() wil
l also resolve the Promise | |
| 150 // created here. | |
| 151 uninitialize(); | |
| 152 | |
| 153 return promise; | |
| 154 } | |
| 155 | |
| 156 void AudioContext::didClose() | 165 void AudioContext::didClose() |
| 157 { | 166 { |
| 158 // This is specific to AudioContexts. OfflineAudioContexts | 167 // This is specific to AudioContexts. OfflineAudioContexts |
| 159 // are closed in their completion event. | 168 // are closed in their completion event. |
| 160 setContextState(Closed); | 169 setContextState(Closed); |
| 161 | 170 |
| 162 ASSERT(s_hardwareContextCount); | 171 ASSERT(s_hardwareContextCount); |
| 163 --s_hardwareContextCount; | 172 --s_hardwareContextCount; |
| 164 | 173 |
| 165 if (m_closeResolver) | 174 if (m_closeResolver) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 179 if (contextState() == Running) { | 188 if (contextState() == Running) { |
| 180 destination()->audioDestinationHandler().stopRendering(); | 189 destination()->audioDestinationHandler().stopRendering(); |
| 181 setContextState(Suspended); | 190 setContextState(Suspended); |
| 182 deferredTaskHandler().clearHandlersToBeDeleted(); | 191 deferredTaskHandler().clearHandlersToBeDeleted(); |
| 183 } | 192 } |
| 184 } | 193 } |
| 185 | 194 |
| 186 } // namespace blink | 195 } // namespace blink |
| 187 | 196 |
| 188 #endif // ENABLE(WEB_AUDIO) | 197 #endif // ENABLE(WEB_AUDIO) |
| OLD | NEW |