Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(139)

Side by Side Diff: Source/modules/webaudio/AudioContext.cpp

Issue 1097873003: Revert of AudioContext.decodeAudioData returns a Promise (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/modules/webaudio/AudioContext.h ('k') | Source/modules/webaudio/AudioContext.idl » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 , m_isCleared(false) 108 , m_isCleared(false)
109 , m_isInitialized(false) 109 , m_isInitialized(false)
110 , m_destinationNode(nullptr) 110 , m_destinationNode(nullptr)
111 , m_isResolvingResumePromises(false) 111 , m_isResolvingResumePromises(false)
112 , m_connectionCount(0) 112 , m_connectionCount(0)
113 , m_didInitializeContextGraphMutex(false) 113 , m_didInitializeContextGraphMutex(false)
114 , m_deferredTaskHandler(DeferredTaskHandler::create()) 114 , m_deferredTaskHandler(DeferredTaskHandler::create())
115 , m_isOfflineContext(false) 115 , m_isOfflineContext(false)
116 , m_contextState(Suspended) 116 , m_contextState(Suspended)
117 , m_cachedSampleFrame(0) 117 , m_cachedSampleFrame(0)
118 , m_closedContextSampleRate(-1)
119 { 118 {
120 m_didInitializeContextGraphMutex = true; 119 m_didInitializeContextGraphMutex = true;
121 m_destinationNode = DefaultAudioDestinationNode::create(this); 120 m_destinationNode = DefaultAudioDestinationNode::create(this);
122 121
123 initialize(); 122 initialize();
124 } 123 }
125 124
126 // Constructor for offline (non-realtime) rendering. 125 // Constructor for offline (non-realtime) rendering.
127 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate) 126 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate)
128 : ActiveDOMObject(document) 127 : ActiveDOMObject(document)
129 , m_isStopScheduled(false) 128 , m_isStopScheduled(false)
130 , m_isCleared(false) 129 , m_isCleared(false)
131 , m_isInitialized(false) 130 , m_isInitialized(false)
132 , m_destinationNode(nullptr) 131 , m_destinationNode(nullptr)
133 , m_isResolvingResumePromises(false) 132 , m_isResolvingResumePromises(false)
134 , m_connectionCount(0) 133 , m_connectionCount(0)
135 , m_didInitializeContextGraphMutex(false) 134 , m_didInitializeContextGraphMutex(false)
136 , m_deferredTaskHandler(DeferredTaskHandler::create()) 135 , m_deferredTaskHandler(DeferredTaskHandler::create())
137 , m_isOfflineContext(true) 136 , m_isOfflineContext(true)
138 , m_contextState(Suspended) 137 , m_contextState(Suspended)
139 , m_cachedSampleFrame(0) 138 , m_cachedSampleFrame(0)
140 , m_closedContextSampleRate(-1)
141 { 139 {
142 m_didInitializeContextGraphMutex = true; 140 m_didInitializeContextGraphMutex = true;
143 // Create a new destination for offline rendering. 141 // Create a new destination for offline rendering.
144 m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampl eRate); 142 m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampl eRate);
145 if (m_renderTarget.get()) 143 if (m_renderTarget.get())
146 m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTa rget.get()); 144 m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTa rget.get());
147 145
148 initialize(); 146 initialize();
149 } 147 }
150 148
151 AudioContext::~AudioContext() 149 AudioContext::~AudioContext()
152 { 150 {
153 #if DEBUG_AUDIONODE_REFERENCES 151 #if DEBUG_AUDIONODE_REFERENCES
154 fprintf(stderr, "%p: AudioContext::~AudioContext(): %u\n", this, m_contextId ); 152 fprintf(stderr, "%p: AudioContext::~AudioContext(): %u\n", this, m_contextId );
155 #endif 153 #endif
156 // 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. 154 // 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.
157
158 ASSERT(!m_isInitialized); 155 ASSERT(!m_isInitialized);
159 ASSERT(!m_referencedNodes.size()); 156 ASSERT(!m_referencedNodes.size());
160 ASSERT(!m_finishedNodes.size()); 157 ASSERT(!m_finishedNodes.size());
161 ASSERT(!m_suspendResolvers.size()); 158 ASSERT(!m_suspendResolvers.size());
162 ASSERT(!m_isResolvingResumePromises); 159 ASSERT(!m_isResolvingResumePromises);
163 ASSERT(!m_resumeResolvers.size()); 160 ASSERT(!m_resumeResolvers.size());
164 ASSERT(!m_audioDecoderResolvers.size());
165 } 161 }
166 162
167 void AudioContext::initialize() 163 void AudioContext::initialize()
168 { 164 {
169 if (isInitialized()) 165 if (isInitialized())
170 return; 166 return;
171 167
172 FFTFrame::initialize(); 168 FFTFrame::initialize();
173 m_listener = AudioListener::create(); 169 m_listener = AudioListener::create();
174 170
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 if (!isOfflineContext()) 226 if (!isOfflineContext())
231 setContextState(Closed); 227 setContextState(Closed);
232 228
233 // Resolve the promise now, if any 229 // Resolve the promise now, if any
234 if (m_closeResolver) 230 if (m_closeResolver)
235 m_closeResolver->resolve(); 231 m_closeResolver->resolve();
236 232
237 ASSERT(m_listener); 233 ASSERT(m_listener);
238 m_listener->waitForHRTFDatabaseLoaderThreadCompletion(); 234 m_listener->waitForHRTFDatabaseLoaderThreadCompletion();
239 235
240 // Reject any decodeAudioData promises that haven't been fulfilled yet.
241 for (auto& resolver : m_audioDecoderResolvers) {
242 resolver->reject(DOMException::create(InvalidStateError, "Audio context is going away"));
243 }
244 m_audioDecoderResolvers.clear();
245
246 // Uninitialization done, so clear flags to indicate that the AudioContext h as no pending
247 // activity anymore.
248 clear(); 236 clear();
249 } 237 }
250 238
251 void AudioContext::stop() 239 void AudioContext::stop()
252 { 240 {
253 // Usually ExecutionContext calls stop twice. 241 // Usually ExecutionContext calls stop twice.
254 if (m_isStopScheduled) 242 if (m_isStopScheduled)
255 return; 243 return;
256 m_isStopScheduled = true; 244 m_isStopScheduled = true;
257 245
(...skipping 16 matching lines...) Expand all
274 } 262 }
275 263
276 AudioBuffer* AudioContext::createBuffer(unsigned numberOfChannels, size_t number OfFrames, float sampleRate, ExceptionState& exceptionState) 264 AudioBuffer* AudioContext::createBuffer(unsigned numberOfChannels, size_t number OfFrames, float sampleRate, ExceptionState& exceptionState)
277 { 265 {
278 // It's ok to call createBuffer, even if the context is closed because the A udioBuffer doesn't 266 // It's ok to call createBuffer, even if the context is closed because the A udioBuffer doesn't
279 // really "belong" to any particular context. 267 // really "belong" to any particular context.
280 268
281 return AudioBuffer::create(numberOfChannels, numberOfFrames, sampleRate, exc eptionState); 269 return AudioBuffer::create(numberOfChannels, numberOfFrames, sampleRate, exc eptionState);
282 } 270 }
283 271
284 ScriptPromise AudioContext::decodeAudioData(ScriptState* scriptState, DOMArrayBu ffer* audioData, AudioBufferCallback* successCallback, AudioBufferCallback* erro rCallback, ExceptionState& exceptionState) 272 void AudioContext::decodeAudioData(DOMArrayBuffer* audioData, AudioBufferCallbac k* successCallback, AudioBufferCallback* errorCallback, ExceptionState& exceptio nState)
285 { 273 {
286 if (!audioData) { 274 if (isContextClosed()) {
287 RefPtrWillBeRawPtr<DOMException> error = DOMException::create( 275 throwExceptionForClosedState(exceptionState);
288 NotSupportedError, 276 return;
289 "invalid ArrayBuffer for audioData.");
290 if (errorCallback) {
291 errorCallback->handleEvent(error.get());
292 }
293 return ScriptPromise::rejectWithDOMException(scriptState, error);
294 } 277 }
295 278
296 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver:: create(scriptState); 279 if (!audioData) {
297 ScriptPromise promise = resolver->promise(); 280 exceptionState.throwDOMException(
298 281 SyntaxError,
299 m_audioDecoderResolvers.append(resolver); 282 "invalid ArrayBuffer for audioData.");
300 283 return;
301 float rate = isContextClosed() ? m_closedContextSampleRate : sampleRate(); 284 }
302 285 m_audioDecoder.decodeAsync(audioData, sampleRate(), successCallback, errorCa llback);
303 ASSERT(rate > 0);
304
305 m_audioDecoder.decodeAsync(audioData, rate, successCallback, errorCallback, resolver.get(), this);
306
307 return promise;
308 } 286 }
309 287
310 AudioBufferSourceNode* AudioContext::createBufferSource(ExceptionState& exceptio nState) 288 AudioBufferSourceNode* AudioContext::createBufferSource(ExceptionState& exceptio nState)
311 { 289 {
312 ASSERT(isMainThread()); 290 ASSERT(isMainThread());
313 291
314 if (isContextClosed()) { 292 if (isContextClosed()) {
315 throwExceptionForClosedState(exceptionState); 293 throwExceptionForClosedState(exceptionState);
316 return nullptr; 294 return nullptr;
317 } 295 }
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after
927 // Find AudioBufferSourceNodes to see if we can stop playing them. 905 // Find AudioBufferSourceNodes to see if we can stop playing them.
928 for (unsigned i = 0; i < m_referencedNodes.size(); ++i) { 906 for (unsigned i = 0; i < m_referencedNodes.size(); ++i) {
929 AudioNode* node = m_referencedNodes.at(i).get(); 907 AudioNode* node = m_referencedNodes.at(i).get();
930 908
931 if (node->handler().nodeType() == AudioHandler::NodeTypeAudioBufferSourc e) { 909 if (node->handler().nodeType() == AudioHandler::NodeTypeAudioBufferSourc e) {
932 AudioBufferSourceNode* sourceNode = static_cast<AudioBufferSourceNod e*>(node); 910 AudioBufferSourceNode* sourceNode = static_cast<AudioBufferSourceNod e*>(node);
933 sourceNode->audioBufferSourceHandler().handleStoppableSourceNode(); 911 sourceNode->audioBufferSourceHandler().handleStoppableSourceNode();
934 } 912 }
935 } 913 }
936 } 914 }
937
938 void AudioContext::removeAudioDecoderResolver(ScriptPromiseResolver* resolver)
939 {
940 ASSERT(isMainThread());
941
942 for (size_t k = 0; k < m_audioDecoderResolvers.size(); ++k) {
943 if (resolver == m_audioDecoderResolvers.at(k)) {
944 m_audioDecoderResolvers.remove(k);
945 break;
946 }
947 }
948 }
949
950 void AudioContext::handlePreRenderTasks() 915 void AudioContext::handlePreRenderTasks()
951 { 916 {
952 ASSERT(isAudioThread()); 917 ASSERT(isAudioThread());
953 918
954 // At the beginning of every render quantum, try to update the internal rend ering graph state (from main thread changes). 919 // At the beginning of every render quantum, try to update the internal rend ering graph state (from main thread changes).
955 // It's OK if the tryLock() fails, we'll just take slightly longer to pick u p the changes. 920 // It's OK if the tryLock() fails, we'll just take slightly longer to pick u p the changes.
956 if (tryLock()) { 921 if (tryLock()) {
957 handler().handleDeferredTasks(); 922 handler().handleDeferredTasks();
958 923
959 resolvePromisesForResume(); 924 resolvePromisesForResume();
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
1157 1122
1158 // Resolve any pending promises created by suspend() 1123 // Resolve any pending promises created by suspend()
1159 if (m_suspendResolvers.size() > 0) 1124 if (m_suspendResolvers.size() > 0)
1160 Platform::current()->mainThread()->postTask(FROM_HERE, bind(&AudioContex t::resolvePromisesForSuspendOnMainThread, this)); 1125 Platform::current()->mainThread()->postTask(FROM_HERE, bind(&AudioContex t::resolvePromisesForSuspendOnMainThread, this));
1161 } 1126 }
1162 1127
1163 void AudioContext::rejectPendingResolvers() 1128 void AudioContext::rejectPendingResolvers()
1164 { 1129 {
1165 ASSERT(isMainThread()); 1130 ASSERT(isMainThread());
1166 1131
1167 // Audio context is closing down so reject any promises that are still pendi ng. 1132 // Audio context is closing down so reject any suspend or resume promises th at are still
1133 // pending.
1168 1134
1169 for (auto& resolver : m_suspendResolvers) { 1135 for (auto& resolver : m_suspendResolvers) {
1170 resolver->reject(DOMException::create(InvalidStateError, "Audio context is going away")); 1136 resolver->reject(DOMException::create(InvalidStateError, "Audio context is going away"));
1171 } 1137 }
1172 m_suspendResolvers.clear(); 1138 m_suspendResolvers.clear();
1173 1139
1174 for (auto& resolver : m_resumeResolvers) { 1140 for (auto& resolver : m_resumeResolvers) {
1175 resolver->reject(DOMException::create(InvalidStateError, "Audio context is going away")); 1141 resolver->reject(DOMException::create(InvalidStateError, "Audio context is going away"));
1176 } 1142 }
1177 m_resumeResolvers.clear(); 1143 m_resumeResolvers.clear();
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1231 // Avoid firing the event if the document has already gone away. 1197 // Avoid firing the event if the document has already gone away.
1232 if (executionContext()) { 1198 if (executionContext()) {
1233 // Call the offline rendering completion event listener and resolve the promise too. 1199 // Call the offline rendering completion event listener and resolve the promise too.
1234 dispatchEvent(OfflineAudioCompletionEvent::create(renderedBuffer)); 1200 dispatchEvent(OfflineAudioCompletionEvent::create(renderedBuffer));
1235 m_offlineResolver->resolve(renderedBuffer); 1201 m_offlineResolver->resolve(renderedBuffer);
1236 } 1202 }
1237 } 1203 }
1238 1204
1239 DEFINE_TRACE(AudioContext) 1205 DEFINE_TRACE(AudioContext)
1240 { 1206 {
1241 visitor->trace(m_audioDecoderResolvers);
1242 visitor->trace(m_closeResolver); 1207 visitor->trace(m_closeResolver);
1243 visitor->trace(m_offlineResolver); 1208 visitor->trace(m_offlineResolver);
1244 visitor->trace(m_renderTarget); 1209 visitor->trace(m_renderTarget);
1245 visitor->trace(m_destinationNode); 1210 visitor->trace(m_destinationNode);
1246 visitor->trace(m_listener); 1211 visitor->trace(m_listener);
1247 // trace() can be called in AudioContext constructor, and 1212 // trace() can be called in AudioContext constructor, and
1248 // m_contextGraphMutex might be unavailable. 1213 // m_contextGraphMutex might be unavailable.
1249 if (m_didInitializeContextGraphMutex) { 1214 if (m_didInitializeContextGraphMutex) {
1250 AutoLocker lock(this); 1215 AutoLocker lock(this);
1251 visitor->trace(m_referencedNodes); 1216 visitor->trace(m_referencedNodes);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1299 1264
1300 if (isContextClosed()) { 1265 if (isContextClosed()) {
1301 // We've already closed the context previously, but it hasn't yet been r esolved, so just 1266 // We've already closed the context previously, but it hasn't yet been r esolved, so just
1302 // create a new promise and reject it. 1267 // create a new promise and reject it.
1303 return ScriptPromise::rejectWithDOMException( 1268 return ScriptPromise::rejectWithDOMException(
1304 scriptState, 1269 scriptState,
1305 DOMException::create(InvalidStateError, 1270 DOMException::create(InvalidStateError,
1306 "Cannot close a context that is being closed or has already been closed.")); 1271 "Cannot close a context that is being closed or has already been closed."));
1307 } 1272 }
1308 1273
1309 // Save the current sample rate for any subsequent decodeAudioData calls.
1310 m_closedContextSampleRate = sampleRate();
1311
1312 m_closeResolver = ScriptPromiseResolver::create(scriptState); 1274 m_closeResolver = ScriptPromiseResolver::create(scriptState);
1313 ScriptPromise promise = m_closeResolver->promise(); 1275 ScriptPromise promise = m_closeResolver->promise();
1314 1276
1315 // Before closing the context go and disconnect all nodes, allowing them to be collected. This 1277 // Before closing the context go and disconnect all nodes, allowing them to be collected. This
1316 // will also break any connections to the destination node. Any unfinished s ourced nodes will 1278 // will also break any connections to the destination node. Any unfinished s ourced nodes will
1317 // get stopped when the context is unitialized. 1279 // get stopped when the context is unitialized.
1318 for (auto& node : m_liveNodes) { 1280 for (auto& node : m_liveNodes) {
1319 if (node) { 1281 if (node) {
1320 for (unsigned k = 0; k < node->numberOfOutputs(); ++k) 1282 for (unsigned k = 0; k < node->numberOfOutputs(); ++k)
1321 node->disconnectWithoutException(k); 1283 node->disconnectWithoutException(k);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1361 DeferredTaskHandler::AutoLocker::AutoLocker(AudioContext* context) 1323 DeferredTaskHandler::AutoLocker::AutoLocker(AudioContext* context)
1362 : m_handler(context->handler()) 1324 : m_handler(context->handler())
1363 { 1325 {
1364 m_handler.lock(); 1326 m_handler.lock();
1365 } 1327 }
1366 1328
1367 1329
1368 } // namespace blink 1330 } // namespace blink
1369 1331
1370 #endif // ENABLE(WEB_AUDIO) 1332 #endif // ENABLE(WEB_AUDIO)
OLDNEW
« no previous file with comments | « Source/modules/webaudio/AudioContext.h ('k') | Source/modules/webaudio/AudioContext.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698