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

Unified Diff: Source/modules/webaudio/OnlineAudioContext.cpp

Issue 1214463003: Split "Online" and "Offline" AudioContext processing (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 6 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 side-by-side diff with in-line comments
Download patch
Index: Source/modules/webaudio/OnlineAudioContext.cpp
diff --git a/Source/modules/webaudio/OnlineAudioContext.cpp b/Source/modules/webaudio/OnlineAudioContext.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7bc59e37621224684fd83ea603b5786f35ed683c
--- /dev/null
+++ b/Source/modules/webaudio/OnlineAudioContext.cpp
@@ -0,0 +1,188 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "modules/webaudio/OnlineAudioContext.h"
+
+#include "bindings/core/v8/ExceptionMessages.h"
+#include "bindings/core/v8/ExceptionState.h"
+#include "bindings/core/v8/ScriptPromiseResolver.h"
+#include "core/dom/DOMException.h"
+#include "core/dom/ExceptionCode.h"
+
+#if DEBUG_AUDIONODE_REFERENCES
+#include <stdio.h>
+#endif
+
+#if ENABLE(WEB_AUDIO)
+
+namespace blink {
+
+// Don't allow more than this number of simultaneous AudioContexts
+// talking to hardware.
+const unsigned MaxHardwareContexts = 6;
+static unsigned s_hardwareContextCount = 0;
+static unsigned s_contextId = 0;
+
+AudioContext* OnlineAudioContext::create(Document& document, ExceptionState& exceptionState)
+{
+ ASSERT(isMainThread());
+ if (s_hardwareContextCount >= MaxHardwareContexts) {
+ exceptionState.throwDOMException(
+ NotSupportedError,
+ ExceptionMessages::indexExceedsMaximumBound(
+ "number of hardware contexts",
+ s_hardwareContextCount,
+ MaxHardwareContexts));
+ return nullptr;
+ }
+
+ OnlineAudioContext* audioContext = new OnlineAudioContext(document);
+ audioContext->suspendIfNeeded();
+
+ // This starts the audio thread. The destination node's
+ // provideInput() method will now be called repeatedly to render
+ // audio. Each time provideInput() is called, a portion of the
+ // audio stream is rendered. Let's call this time period a "render
+ // quantum". NOTE: for now default AudioContext does not need an
+ // explicit startRendering() call from JavaScript. We may want to
+ // consider requiring it for symmetry with OfflineAudioContext.
+ audioContext->startRendering();
+ ++s_hardwareContextCount;
+#if DEBUG_AUDIONODE_REFERENCES
+ fprintf(stderr, "%p: OnlineAudioContext::OnlineAudioContext(): %u #%u\n",
+ audioContext, audioContext->m_contextId, s_hardwareContextCount);
+#endif
+
+ return audioContext;
+}
+
+OnlineAudioContext::OnlineAudioContext(Document& document)
+ : AudioContext(&document)
+ , m_contextId(s_contextId++)
+{
+}
+
+OnlineAudioContext::~OnlineAudioContext()
+{
+#if DEBUG_AUDIONODE_REFERENCES
+ fprintf(stderr, "%p: OnlineAudioContext::~OnlineAudioContext(): %u\n", this, m_contextId);
+#endif
+}
+
+DEFINE_TRACE(OnlineAudioContext)
+{
+ visitor->trace(m_closeResolver);
+ AudioContext::trace(visitor);
+}
+
+ScriptPromise OnlineAudioContext::suspendContext(ScriptState* scriptState)
+{
+ ASSERT(isMainThread());
+ AutoLocker locker(this);
+
+ RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState);
+ ScriptPromise promise = resolver->promise();
+
+ if (contextState() == Closed) {
+ resolver->reject(
+ DOMException::create(InvalidStateError, "Cannot suspend a context that has been closed"));
+ } else {
+ // Stop rendering now.
+ if (destination())
+ stopRendering();
+
+ // Since we don't have any way of knowing when the hardware actually stops, we'll just
+ // resolve the promise now.
+ resolver->resolve();
+ }
+
+ return promise;
+}
+
+ScriptPromise OnlineAudioContext::resumeContext(ScriptState* scriptState)
+{
+ ASSERT(isMainThread());
+
+ if (isContextClosed()) {
+ return ScriptPromise::rejectWithDOMException(
+ scriptState,
+ DOMException::create(
+ InvalidAccessError,
+ "cannot resume a closed AudioContext"));
+ }
+
+ RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState);
+ ScriptPromise promise = resolver->promise();
+
+ // Restart the destination node to pull on the audio graph.
+ if (destination())
+ startRendering();
+
+ // Save the resolver which will get resolved when the destination node starts pulling on the
+ // graph again.
+ {
+ AutoLocker locker(this);
+ m_resumeResolvers.append(resolver);
+ }
+
+ return promise;
+}
+
+ScriptPromise OnlineAudioContext::closeContext(ScriptState* scriptState)
+{
+ if (isContextClosed()) {
+ // We've already closed the context previously, but it hasn't yet been resolved, so just
+ // create a new promise and reject it.
+ return ScriptPromise::rejectWithDOMException(
+ scriptState,
+ DOMException::create(InvalidStateError,
+ "Cannot close a context that is being closed or has already been closed."));
+ }
+
+ m_closeResolver = ScriptPromiseResolver::create(scriptState);
+ ScriptPromise promise = m_closeResolver->promise();
+
+ // Stop the audio context. This will stop the destination node from pulling audio anymore. And
+ // since we have disconnected the destination from the audio graph, and thus has no references,
+ // the destination node can GCed if JS has no references. stop() will also resolve the Promise
+ // created here.
+ stop();
+
+ return promise;
+}
+
+void OnlineAudioContext::didClose()
+{
+ // This is specific to OnlineAudioContexts. OfflineAudioContexts
+ // are closed in their completion event.
+ setContextState(Closed);
+
+ ASSERT(s_hardwareContextCount);
+ --s_hardwareContextCount;
+
+ if (m_closeResolver)
+ m_closeResolver->resolve();
+}
+
+bool OnlineAudioContext::isContextClosed() const
+{
+ return m_closeResolver || AudioContext::isContextClosed();
+}
+
+void OnlineAudioContext::stopRendering()
+{
+ ASSERT(isMainThread());
+ ASSERT(destination());
+
+ if (contextState() == Running) {
+ destination()->audioDestinationHandler().stopRendering();
+ setContextState(Suspended);
+ deferredTaskHandler().clearHandlersToBeDeleted();
+ }
+}
+
+} // namespace blink
+
+#endif // ENABLE(WEB_AUDIO)

Powered by Google App Engine
This is Rietveld 408576698