| Index: Source/modules/webaudio/AudioContext.cpp
|
| diff --git a/Source/modules/webaudio/AudioContext.cpp b/Source/modules/webaudio/AudioContext.cpp
|
| index a6e0aebbeeab2c4dc1278d17ec43f392fd25f5df..099432faf44f8a419214f959cd69b4ec37a3d6e6 100644
|
| --- a/Source/modules/webaudio/AudioContext.cpp
|
| +++ b/Source/modules/webaudio/AudioContext.cpp
|
| @@ -730,15 +730,9 @@ void AudioContext::notifyStateChange()
|
| ScriptPromise AudioContext::suspendContext(ScriptState* scriptState)
|
| {
|
| ASSERT(isMainThread());
|
| - AutoLocker locker(this);
|
| + ASSERT(!isOfflineContext());
|
|
|
| - if (isOfflineContext()) {
|
| - return ScriptPromise::rejectWithDOMException(
|
| - scriptState,
|
| - DOMException::create(
|
| - InvalidAccessError,
|
| - "cannot suspend an OfflineAudioContext"));
|
| - }
|
| + AutoLocker locker(this);
|
|
|
| RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState);
|
| ScriptPromise promise = resolver->promise();
|
| @@ -848,10 +842,34 @@ void AudioContext::handleStoppableSourceNodes()
|
| }
|
| }
|
|
|
| +void AudioContext::performPostRenderTasks()
|
| +{
|
| + // Take care of AudioNode tasks where the tryLock() failed previously.
|
| + deferredTaskHandler().breakConnections();
|
| +
|
| + // Dynamically clean up nodes which are no longer needed.
|
| + releaseFinishedSourceNodes();
|
| +
|
| + deferredTaskHandler().handleDeferredTasks();
|
| + deferredTaskHandler().requestToDeleteHandlersOnMainThread();
|
| +}
|
| +
|
| void AudioContext::handlePreRenderTasks()
|
| {
|
| ASSERT(isAudioThread());
|
|
|
| + // For the precise offline audio rendering, we need these tasks to be
|
| + // performed every render quantum. Thus, we wait for the graph lock (rather
|
| + // than tryLock()) so we can run the pre-render tasks without deferring
|
| + // them.
|
| + if (isOfflineContext()) {
|
| + deferredTaskHandler().forceLock();
|
| + deferredTaskHandler().handleDeferredTasks();
|
| + handleStoppableSourceNodes();
|
| + unlock();
|
| + return;
|
| + }
|
| +
|
| // At the beginning of every render quantum, try to update the internal rendering graph state (from main thread changes).
|
| // It's OK if the tryLock() fails, we'll just take slightly longer to pick up the changes.
|
| if (tryLock()) {
|
| @@ -870,19 +888,20 @@ void AudioContext::handlePostRenderTasks()
|
| {
|
| ASSERT(isAudioThread());
|
|
|
| + // Same as |handlePreRenderTasks()|. We force to perform the post-render
|
| + // tasks for the offline rendering.
|
| + if (isOfflineContext()) {
|
| + deferredTaskHandler().forceLock();
|
| + performPostRenderTasks();
|
| + unlock();
|
| + return;
|
| + }
|
| +
|
| // Must use a tryLock() here too. Don't worry, the lock will very rarely be contended and this method is called frequently.
|
| // The worst that can happen is that there will be some nodes which will take slightly longer than usual to be deleted or removed
|
| // from the render graph (in which case they'll render silence).
|
| if (tryLock()) {
|
| - // Take care of AudioNode tasks where the tryLock() failed previously.
|
| - deferredTaskHandler().breakConnections();
|
| -
|
| - // Dynamically clean up nodes which are no longer needed.
|
| - releaseFinishedSourceNodes();
|
| -
|
| - deferredTaskHandler().handleDeferredTasks();
|
| - deferredTaskHandler().requestToDeleteHandlersOnMainThread();
|
| -
|
| + performPostRenderTasks();
|
| unlock();
|
| }
|
| }
|
| @@ -945,9 +964,10 @@ ExecutionContext* AudioContext::executionContext() const
|
|
|
| void AudioContext::startRendering()
|
| {
|
| - // This is called for both online and offline contexts.
|
| + // This is only for the real-time context.
|
| ASSERT(isMainThread());
|
| ASSERT(m_destinationNode);
|
| + ASSERT(!isOfflineContext());
|
|
|
| if (m_contextState == Suspended) {
|
| destination()->audioDestinationHandler().startRendering();
|
| @@ -970,32 +990,23 @@ void AudioContext::stopRendering()
|
|
|
| void AudioContext::fireCompletionEvent()
|
| {
|
| - ASSERT(isMainThread());
|
| - if (!isMainThread())
|
| - return;
|
| -
|
| - AudioBuffer* renderedBuffer = m_renderTarget.get();
|
| -
|
| - // For an offline context, we set the state to closed here so that the oncomplete handler sees
|
| - // that the context has been closed.
|
| - setContextState(Closed);
|
| + ASSERT_WITH_MESSAGE(1, "fireCompletionEvent() only valid for offline audio context");
|
| +}
|
|
|
| - ASSERT(renderedBuffer);
|
| - if (!renderedBuffer)
|
| - return;
|
| +bool AudioContext::shouldSuspendNow()
|
| +{
|
| + ASSERT_WITH_MESSAGE(1, "shouldSuspendNow() only valid for offline audio context");
|
| + return false;
|
| +}
|
|
|
| - // Avoid firing the event if the document has already gone away.
|
| - if (executionContext()) {
|
| - // Call the offline rendering completion event listener and resolve the promise too.
|
| - dispatchEvent(OfflineAudioCompletionEvent::create(renderedBuffer));
|
| - m_offlineResolver->resolve(renderedBuffer);
|
| - }
|
| +void AudioContext::resolvePendingSuspendPromises()
|
| +{
|
| + ASSERT_WITH_MESSAGE(1, "clearResolvedSuspend() only valid for offline audio context");
|
| }
|
|
|
| DEFINE_TRACE(AudioContext)
|
| {
|
| visitor->trace(m_closeResolver);
|
| - visitor->trace(m_offlineResolver);
|
| visitor->trace(m_renderTarget);
|
| visitor->trace(m_destinationNode);
|
| visitor->trace(m_listener);
|
|
|