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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "config.h"
6 #include "modules/webaudio/OnlineAudioContext.h"
7
8 #include "bindings/core/v8/ExceptionMessages.h"
9 #include "bindings/core/v8/ExceptionState.h"
10 #include "bindings/core/v8/ScriptPromiseResolver.h"
11 #include "core/dom/DOMException.h"
12 #include "core/dom/ExceptionCode.h"
13
14 #if DEBUG_AUDIONODE_REFERENCES
15 #include <stdio.h>
16 #endif
17
18 #if ENABLE(WEB_AUDIO)
19
20 namespace blink {
21
22 // Don't allow more than this number of simultaneous AudioContexts
23 // talking to hardware.
24 const unsigned MaxHardwareContexts = 6;
25 static unsigned s_hardwareContextCount = 0;
26 static unsigned s_contextId = 0;
27
28 AudioContext* OnlineAudioContext::create(Document& document, ExceptionState& exc eptionState)
29 {
30 ASSERT(isMainThread());
31 if (s_hardwareContextCount >= MaxHardwareContexts) {
32 exceptionState.throwDOMException(
33 NotSupportedError,
34 ExceptionMessages::indexExceedsMaximumBound(
35 "number of hardware contexts",
36 s_hardwareContextCount,
37 MaxHardwareContexts));
38 return nullptr;
39 }
40
41 OnlineAudioContext* audioContext = new OnlineAudioContext(document);
42 audioContext->suspendIfNeeded();
43
44 // This starts the audio thread. The destination node's
45 // provideInput() method will now be called repeatedly to render
46 // audio. Each time provideInput() is called, a portion of the
47 // audio stream is rendered. Let's call this time period a "render
48 // quantum". NOTE: for now default AudioContext does not need an
49 // explicit startRendering() call from JavaScript. We may want to
50 // consider requiring it for symmetry with OfflineAudioContext.
51 audioContext->startRendering();
52 ++s_hardwareContextCount;
53 #if DEBUG_AUDIONODE_REFERENCES
54 fprintf(stderr, "%p: OnlineAudioContext::OnlineAudioContext(): %u #%u\n",
55 audioContext, audioContext->m_contextId, s_hardwareContextCount);
56 #endif
57
58 return audioContext;
59 }
60
61 OnlineAudioContext::OnlineAudioContext(Document& document)
62 : AudioContext(&document)
63 , m_contextId(s_contextId++)
64 {
65 }
66
67 OnlineAudioContext::~OnlineAudioContext()
68 {
69 #if DEBUG_AUDIONODE_REFERENCES
70 fprintf(stderr, "%p: OnlineAudioContext::~OnlineAudioContext(): %u\n", this, m_contextId);
71 #endif
72 }
73
74 DEFINE_TRACE(OnlineAudioContext)
75 {
76 visitor->trace(m_closeResolver);
77 AudioContext::trace(visitor);
78 }
79
80 ScriptPromise OnlineAudioContext::suspendContext(ScriptState* scriptState)
81 {
82 ASSERT(isMainThread());
83 AutoLocker locker(this);
84
85 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver:: create(scriptState);
86 ScriptPromise promise = resolver->promise();
87
88 if (contextState() == Closed) {
89 resolver->reject(
90 DOMException::create(InvalidStateError, "Cannot suspend a context th at has been closed"));
91 } else {
92 // Stop rendering now.
93 if (destination())
94 stopRendering();
95
96 // Since we don't have any way of knowing when the hardware actually sto ps, we'll just
97 // resolve the promise now.
98 resolver->resolve();
99 }
100
101 return promise;
102 }
103
104 ScriptPromise OnlineAudioContext::resumeContext(ScriptState* scriptState)
105 {
106 ASSERT(isMainThread());
107
108 if (isContextClosed()) {
109 return ScriptPromise::rejectWithDOMException(
110 scriptState,
111 DOMException::create(
112 InvalidAccessError,
113 "cannot resume a closed AudioContext"));
114 }
115
116 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver:: create(scriptState);
117 ScriptPromise promise = resolver->promise();
118
119 // Restart the destination node to pull on the audio graph.
120 if (destination())
121 startRendering();
122
123 // Save the resolver which will get resolved when the destination node start s pulling on the
124 // graph again.
125 {
126 AutoLocker locker(this);
127 m_resumeResolvers.append(resolver);
128 }
129
130 return promise;
131 }
132
133 ScriptPromise OnlineAudioContext::closeContext(ScriptState* scriptState)
134 {
135 if (isContextClosed()) {
136 // We've already closed the context previously, but it hasn't yet been r esolved, so just
137 // create a new promise and reject it.
138 return ScriptPromise::rejectWithDOMException(
139 scriptState,
140 DOMException::create(InvalidStateError,
141 "Cannot close a context that is being closed or has already been closed."));
142 }
143
144 m_closeResolver = ScriptPromiseResolver::create(scriptState);
145 ScriptPromise promise = m_closeResolver->promise();
146
147 // Stop the audio context. This will stop the destination node from pulling audio anymore. And
148 // since we have disconnected the destination from the audio graph, and thus has no references,
149 // the destination node can GCed if JS has no references. stop() will also r esolve the Promise
150 // created here.
151 stop();
152
153 return promise;
154 }
155
156 void OnlineAudioContext::didClose()
157 {
158 // This is specific to OnlineAudioContexts. OfflineAudioContexts
159 // are closed in their completion event.
160 setContextState(Closed);
161
162 ASSERT(s_hardwareContextCount);
163 --s_hardwareContextCount;
164
165 if (m_closeResolver)
166 m_closeResolver->resolve();
167 }
168
169 bool OnlineAudioContext::isContextClosed() const
170 {
171 return m_closeResolver || AudioContext::isContextClosed();
172 }
173
174 void OnlineAudioContext::stopRendering()
175 {
176 ASSERT(isMainThread());
177 ASSERT(destination());
178
179 if (contextState() == Running) {
180 destination()->audioDestinationHandler().stopRendering();
181 setContextState(Suspended);
182 deferredTaskHandler().clearHandlersToBeDeleted();
183 }
184 }
185
186 } // namespace blink
187
188 #endif // ENABLE(WEB_AUDIO)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698