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

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

Issue 1140723003: Implement suspend() and resume() for OfflineAudioContext (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Promise Resolution Created 5 years, 7 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2012, Google Inc. All rights reserved. 2 * Copyright (C) 2012, 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 13 matching lines...) Expand all
24 24
25 #include "config.h" 25 #include "config.h"
26 #if ENABLE(WEB_AUDIO) 26 #if ENABLE(WEB_AUDIO)
27 #include "modules/webaudio/OfflineAudioContext.h" 27 #include "modules/webaudio/OfflineAudioContext.h"
28 28
29 #include "bindings/core/v8/ExceptionMessages.h" 29 #include "bindings/core/v8/ExceptionMessages.h"
30 #include "bindings/core/v8/ExceptionState.h" 30 #include "bindings/core/v8/ExceptionState.h"
31 #include "core/dom/Document.h" 31 #include "core/dom/Document.h"
32 #include "core/dom/ExceptionCode.h" 32 #include "core/dom/ExceptionCode.h"
33 #include "core/dom/ExecutionContext.h" 33 #include "core/dom/ExecutionContext.h"
34 #include "modules/webaudio/OfflineAudioDestinationNode.h"
35 #include "platform/ThreadSafeFunctional.h"
34 #include "platform/audio/AudioUtilities.h" 36 #include "platform/audio/AudioUtilities.h"
37 #include "public/platform/Platform.h"
35 38
36 namespace blink { 39 namespace blink {
37 40
38 OfflineAudioContext* OfflineAudioContext::create(ExecutionContext* context, unsi gned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState& exceptionState) 41 OfflineAudioContext* OfflineAudioContext::create(ExecutionContext* context, unsi gned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState& exceptionState)
39 { 42 {
40 // FIXME: add support for workers. 43 // FIXME: add support for workers.
41 if (!context || !context->isDocument()) { 44 if (!context || !context->isDocument()) {
42 exceptionState.throwDOMException( 45 exceptionState.throwDOMException(
43 NotSupportedError, 46 NotSupportedError,
44 "Workers are not supported."); 47 "Workers are not supported.");
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 95
93 OfflineAudioContext::OfflineAudioContext(Document* document, unsigned numberOfCh annels, size_t numberOfFrames, float sampleRate) 96 OfflineAudioContext::OfflineAudioContext(Document* document, unsigned numberOfCh annels, size_t numberOfFrames, float sampleRate)
94 : AudioContext(document, numberOfChannels, numberOfFrames, sampleRate) 97 : AudioContext(document, numberOfChannels, numberOfFrames, sampleRate)
95 { 98 {
96 } 99 }
97 100
98 OfflineAudioContext::~OfflineAudioContext() 101 OfflineAudioContext::~OfflineAudioContext()
99 { 102 {
100 } 103 }
101 104
105 OfflineAudioContext::ScheduledSuspendContainer::ScheduledSuspendContainer(
106 double when, PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver)
107 : m_when(when)
Raymond Toy 2015/05/19 22:04:45 Shouldn't this quantize the time to the rendering
108 , m_resolver(resolver)
109 {
110 }
111
112 OfflineAudioContext::ScheduledSuspendContainer::~ScheduledSuspendContainer()
113 {
114 }
115
116 DEFINE_TRACE(OfflineAudioContext::ScheduledSuspendContainer)
117 {
118 visitor->trace(m_resolver);
119 }
120
121 PassOwnPtr<OfflineAudioContext::ScheduledSuspendContainer>
122 OfflineAudioContext::ScheduledSuspendContainer::create(
123 double when, PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver)
124 {
125 return adoptPtr(new ScheduledSuspendContainer(when, resolver));
126 }
127
128 bool OfflineAudioContext::ScheduledSuspendContainer::shouldBeSuspendedNow(double currentTime) const
129 {
130 return m_when <= currentTime;
131 }
132
133 bool OfflineAudioContext::suspendIfNecessary()
134 {
135 ASSERT(!isMainThread());
136
137 // Suspend if necessary and resolve the associated promise.
138 for (unsigned index = 0; index < m_scheduledSuspends.size(); ++index) {
139 if (m_scheduledSuspends.at(index)->shouldBeSuspendedNow(currentTime())) {
140 // Resolve scheduled suspend on the main thread.
141 Platform::current()->mainThread()->postTask(FROM_HERE,
142 threadSafeBind(
143 &OfflineAudioContext::suspendAndResolveOnMainThread,
144 this,
145 index));
146 return true;
147 }
148 }
149
150 return false;
151 }
152
153 bool OfflineAudioContext::isSuspendScheduled() const
154 {
155 return m_scheduledSuspends.size() > 0;
156 }
157
102 ScriptPromise OfflineAudioContext::startOfflineRendering(ScriptState* scriptStat e) 158 ScriptPromise OfflineAudioContext::startOfflineRendering(ScriptState* scriptStat e)
103 { 159 {
160 ASSERT(isMainThread());
161 AutoLocker locker(this);
162
104 // Calling close() on an OfflineAudioContext is not supported/allowed, 163 // Calling close() on an OfflineAudioContext is not supported/allowed,
105 // but it might well have been stopped by its execution context. 164 // but it might well have been stopped by its execution context.
106 if (isContextClosed()) { 165 if (isContextClosed()) {
107 return ScriptPromise::rejectWithDOMException( 166 return ScriptPromise::rejectWithDOMException(
108 scriptState, 167 scriptState,
109 DOMException::create( 168 DOMException::create(
110 InvalidStateError, 169 InvalidStateError,
111 "cannot call startRendering on an OfflineAudioContext in a stopp ed state.")); 170 "cannot call startRendering on an OfflineAudioContext in a stopp ed state."));
112 } 171 }
113 172
114 if (m_offlineResolver) { 173 if (m_offlineResolver) {
115 // Can't call startRendering more than once. Return a rejected promise now. 174 // Can't call startRendering more than once. Return a rejected promise now.
116 return ScriptPromise::rejectWithDOMException( 175 return ScriptPromise::rejectWithDOMException(
117 scriptState, 176 scriptState,
118 DOMException::create( 177 DOMException::create(
119 InvalidStateError, 178 InvalidStateError,
120 "cannot call startRendering more than once")); 179 "cannot call startRendering more than once"));
121 } 180 }
122 181
123 m_offlineResolver = ScriptPromiseResolver::create(scriptState); 182 m_offlineResolver = ScriptPromiseResolver::create(scriptState);
124 startRendering(); 183
184 // This calls AudioContext.startRendering(). It seems to be odd to go up the
185 // chain and call the parent's method, but the current OAC is basically a
186 // thin wrapper on AudioContext. (a container-like object.)
187 //
188 // If we decide to fix this structural issue completely, we have to touch
189 // AudioContext and AudioNode.
190 // startRendering();
191
192 destination()->audioDestinationHandler().startRendering();
193 setContextState(Running);
194
125 return m_offlineResolver->promise(); 195 return m_offlineResolver->promise();
126 } 196 }
127 197
198 ScriptPromise OfflineAudioContext::suspendOfflineRendering(ScriptState* scriptSt ate, double when)
199 {
200 ASSERT(isMainThread());
201 AutoLocker locker(this);
202
203 // suspendTime should be greater than currentTime. Note that this is called
204 // from the main thread, so the currentTime will be one rendering quantum
205 // behind the actual current time.
206 if (currentTime() < when) {
207 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolv er::create(scriptState);
208 ScriptPromise promise = resolver->promise();
209 m_scheduledSuspends.append(ScheduledSuspendContainer::create(when, resol ver));
210 return promise;
211 }
212
213 // If suspendTime is already passed, throw an exception.
214 return ScriptPromise::rejectWithDOMException(
215 scriptState,
216 DOMException::create(
217 InvalidStateError,
218 "cannot schedule a suspend in the past"));
219 }
220
221 ScriptPromise OfflineAudioContext::resumeOfflineRendering(ScriptState* scriptSta te)
222 {
223 ASSERT(isMainThread());
224 AutoLocker locker(this);
225
226 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver:: create(scriptState);
227 ScriptPromise promise = resolver->promise();
228 m_resumeResolvers.append(resolver);
Raymond Toy 2015/05/19 22:04:45 Not sure, but I think you can resolve the promise
hongchan 2015/05/20 22:09:40 I agree. This was just to make the structure symme
229
230 // Calling startRendering() in OfflineAudioDestinationHandler.
231 destination()->audioDestinationHandler().startRendering();
232 setContextState(Running);
233
234 return promise;
235 }
236
237 void OfflineAudioContext::suspendAndResolveOnMainThread(unsigned index)
238 {
239 ASSERT(isMainThread());
240 AutoLocker locker(this);
241
242 setContextState(Suspended);
243
244 m_scheduledSuspends.at(index)->resolver()->resolve();
245
246 // TO FIX: does this automatically re-arrange the rest of vector?
247 m_scheduledSuspends.remove(index);
248 }
249
128 } // namespace blink 250 } // namespace blink
129 251
130 #endif // ENABLE(WEB_AUDIO) 252 #endif // ENABLE(WEB_AUDIO)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698