Index: Source/modules/webaudio/AudioContext.cpp |
diff --git a/Source/modules/webaudio/AudioContext.cpp b/Source/modules/webaudio/AudioContext.cpp |
index a6e0aebbeeab2c4dc1278d17ec43f392fd25f5df..7f42f5b6b8a09a2d9f659d7c442f2824ab84c974 100644 |
--- a/Source/modules/webaudio/AudioContext.cpp |
+++ b/Source/modules/webaudio/AudioContext.cpp |
@@ -57,6 +57,7 @@ |
#include "modules/webaudio/OfflineAudioCompletionEvent.h" |
#include "modules/webaudio/OfflineAudioContext.h" |
#include "modules/webaudio/OfflineAudioDestinationNode.h" |
+#include "modules/webaudio/OnlineAudioContext.h" |
#include "modules/webaudio/OscillatorNode.h" |
#include "modules/webaudio/PannerNode.h" |
#include "modules/webaudio/PeriodicWave.h" |
@@ -67,35 +68,16 @@ |
#include "public/platform/Platform.h" |
#include "wtf/text/WTFString.h" |
-#if DEBUG_AUDIONODE_REFERENCES |
-#include <stdio.h> |
-#endif |
- |
namespace blink { |
-// Don't allow more than this number of simultaneous AudioContexts talking to hardware. |
-const unsigned MaxHardwareContexts = 6; |
-unsigned AudioContext::s_hardwareContextCount = 0; |
-unsigned AudioContext::s_contextId = 0; |
- |
AudioContext* AudioContext::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; |
- } |
- |
- AudioContext* audioContext = new AudioContext(&document); |
- audioContext->suspendIfNeeded(); |
- return audioContext; |
+ return OnlineAudioContext::create(document, exceptionState); |
} |
+// FIXME(dominicc): Devolve these constructors to OnlineAudioContext |
+// and OfflineAudioContext respectively. |
+ |
// Constructor for rendering to the audio hardware. |
AudioContext::AudioContext(Document* document) |
: ActiveDOMObject(document) |
@@ -107,7 +89,6 @@ AudioContext::AudioContext(Document* document) |
, m_connectionCount(0) |
, m_didInitializeContextGraphMutex(false) |
, m_deferredTaskHandler(DeferredTaskHandler::create()) |
- , m_isOfflineContext(false) |
, m_contextState(Suspended) |
{ |
m_didInitializeContextGraphMutex = true; |
@@ -127,7 +108,6 @@ AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t |
, m_connectionCount(0) |
, m_didInitializeContextGraphMutex(false) |
, m_deferredTaskHandler(DeferredTaskHandler::create()) |
- , m_isOfflineContext(true) |
, m_contextState(Suspended) |
{ |
m_didInitializeContextGraphMutex = true; |
@@ -141,9 +121,6 @@ AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t |
AudioContext::~AudioContext() |
{ |
-#if DEBUG_AUDIONODE_REFERENCES |
- fprintf(stderr, "%p: AudioContext::~AudioContext(): %u\n", this, m_contextId); |
-#endif |
deferredTaskHandler().contextWillBeDestroyed(); |
// AudioNodes keep a reference to their context, so there should be no way to be in the destructor if there are still AudioNodes around. |
ASSERT(!m_isInitialized); |
@@ -163,22 +140,7 @@ void AudioContext::initialize() |
if (m_destinationNode.get()) { |
m_destinationNode->handler().initialize(); |
- |
- if (!isOfflineContext()) { |
- // 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. |
- startRendering(); |
- ++s_hardwareContextCount; |
- } |
- |
- m_contextId = s_contextId++; |
m_isInitialized = true; |
-#if DEBUG_AUDIONODE_REFERENCES |
- fprintf(stderr, "%p: AudioContext::AudioContext(): %u #%u\n", |
- this, m_contextId, AudioContext::s_hardwareContextCount); |
-#endif |
} |
} |
@@ -204,25 +166,12 @@ void AudioContext::uninitialize() |
if (m_destinationNode) |
m_destinationNode->handler().uninitialize(); |
- if (!isOfflineContext()) { |
- ASSERT(s_hardwareContextCount); |
- --s_hardwareContextCount; |
- } |
- |
// Get rid of the sources which may still be playing. |
releaseActiveSourceNodes(); |
// Reject any pending resolvers before we go away. |
rejectPendingResolvers(); |
- |
- // For an offline audio context, the completion event will set the state to closed. For an |
- // online context, we need to do it here. We only want to set the closed state once. |
- if (!isOfflineContext()) |
- setContextState(Closed); |
- |
- // Resolve the promise now, if any |
- if (m_closeResolver) |
- m_closeResolver->resolve(); |
+ didClose(); |
ASSERT(m_listener); |
m_listener->waitForHRTFDatabaseLoaderThreadCompletion(); |
@@ -727,73 +676,6 @@ void AudioContext::notifyStateChange() |
dispatchEvent(Event::create(EventTypeNames::statechange)); |
} |
-ScriptPromise AudioContext::suspendContext(ScriptState* scriptState) |
-{ |
- ASSERT(isMainThread()); |
- AutoLocker locker(this); |
- |
- if (isOfflineContext()) { |
- return ScriptPromise::rejectWithDOMException( |
- scriptState, |
- DOMException::create( |
- InvalidAccessError, |
- "cannot suspend an OfflineAudioContext")); |
- } |
- |
- RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState); |
- ScriptPromise promise = resolver->promise(); |
- |
- if (m_contextState == Closed) { |
- resolver->reject( |
- DOMException::create(InvalidStateError, "Cannot suspend a context that has been closed")); |
- } else { |
- // Stop rendering now. |
- if (m_destinationNode) |
- 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 AudioContext::resumeContext(ScriptState* scriptState) |
-{ |
- ASSERT(isMainThread()); |
- AutoLocker locker(this); |
- |
- if (isOfflineContext()) { |
- return ScriptPromise::rejectWithDOMException( |
- scriptState, |
- DOMException::create( |
- InvalidAccessError, |
- "cannot resume an OfflineAudioContext")); |
- } |
- |
- 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 (m_destinationNode) |
- startRendering(); |
- |
- // Save the resolver which will get resolved when the destination node starts pulling on the |
- // graph again. |
- m_resumeResolvers.append(resolver); |
- |
- return promise; |
-} |
- |
void AudioContext::notifySourceNodeFinishedProcessing(AudioHandler* handler) |
{ |
ASSERT(isAudioThread()); |
@@ -955,19 +837,6 @@ void AudioContext::startRendering() |
} |
} |
-void AudioContext::stopRendering() |
-{ |
- ASSERT(isMainThread()); |
- ASSERT(m_destinationNode); |
- ASSERT(!isOfflineContext()); |
- |
- if (m_contextState == Running) { |
- destination()->audioDestinationHandler().stopRendering(); |
- setContextState(Suspended); |
- deferredTaskHandler().clearHandlersToBeDeleted(); |
- } |
-} |
- |
void AudioContext::fireCompletionEvent() |
{ |
ASSERT(isMainThread()); |
@@ -994,7 +863,6 @@ void AudioContext::fireCompletionEvent() |
DEFINE_TRACE(AudioContext) |
{ |
- visitor->trace(m_closeResolver); |
visitor->trace(m_offlineResolver); |
visitor->trace(m_renderTarget); |
visitor->trace(m_destinationNode); |
@@ -1020,35 +888,6 @@ SecurityOrigin* AudioContext::securityOrigin() const |
return nullptr; |
} |
-ScriptPromise AudioContext::closeContext(ScriptState* scriptState) |
-{ |
- if (isOfflineContext()) { |
- return ScriptPromise::rejectWithDOMException( |
- scriptState, |
- DOMException::create(InvalidAccessError, "cannot close an OfflineAudioContext.")); |
- } |
- |
- 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; |
-} |
- |
} // namespace blink |
#endif // ENABLE(WEB_AUDIO) |