| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "modules/webaudio/AudioContext.h" | 5 #include "modules/webaudio/AudioContext.h" |
| 6 | 6 |
| 7 #include "bindings/core/v8/ExceptionMessages.h" | 7 #include "bindings/core/v8/ExceptionMessages.h" |
| 8 #include "bindings/core/v8/ExceptionState.h" | 8 #include "bindings/core/v8/ExceptionState.h" |
| 9 #include "bindings/core/v8/ScriptPromiseResolver.h" | 9 #include "bindings/core/v8/ScriptPromiseResolver.h" |
| 10 #include "core/dom/DOMException.h" | 10 #include "core/dom/DOMException.h" |
| 11 #include "core/dom/ExceptionCode.h" | 11 #include "core/dom/ExceptionCode.h" |
| 12 #include "core/frame/LocalDOMWindow.h" |
| 13 #include "core/timing/DOMWindowPerformance.h" |
| 14 #include "core/timing/Performance.h" |
| 12 #include "modules/webaudio/AudioBufferCallback.h" | 15 #include "modules/webaudio/AudioBufferCallback.h" |
| 16 #include "modules/webaudio/AudioTimestamp.h" |
| 13 #include "platform/Histogram.h" | 17 #include "platform/Histogram.h" |
| 14 #include "platform/audio/AudioUtilities.h" | 18 #include "platform/audio/AudioUtilities.h" |
| 15 | 19 |
| 16 #if DEBUG_AUDIONODE_REFERENCES | 20 #if DEBUG_AUDIONODE_REFERENCES |
| 17 #include <stdio.h> | 21 #include <stdio.h> |
| 18 #endif | 22 #endif |
| 19 | 23 |
| 20 namespace blink { | 24 namespace blink { |
| 21 | 25 |
| 22 // Don't allow more than this number of simultaneous AudioContexts | 26 // Don't allow more than this number of simultaneous AudioContexts |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 ("WebAudio.AudioContext.HardwareSampleRate")); | 77 ("WebAudio.AudioContext.HardwareSampleRate")); |
| 74 maxChannelCountHistogram.sample(audioContext->destination()->maxChannelCount
()); | 78 maxChannelCountHistogram.sample(audioContext->destination()->maxChannelCount
()); |
| 75 sampleRateHistogram.sample(audioContext->sampleRate()); | 79 sampleRateHistogram.sample(audioContext->sampleRate()); |
| 76 | 80 |
| 77 return audioContext; | 81 return audioContext; |
| 78 } | 82 } |
| 79 | 83 |
| 80 AudioContext::AudioContext(Document& document) | 84 AudioContext::AudioContext(Document& document) |
| 81 : AbstractAudioContext(&document) | 85 : AbstractAudioContext(&document) |
| 82 , m_contextId(s_contextId++) | 86 , m_contextId(s_contextId++) |
| 87 , m_outputTimestampFramesOrigin(0) |
| 83 { | 88 { |
| 84 } | 89 } |
| 85 | 90 |
| 86 AudioContext::~AudioContext() | 91 AudioContext::~AudioContext() |
| 87 { | 92 { |
| 88 #if DEBUG_AUDIONODE_REFERENCES | 93 #if DEBUG_AUDIONODE_REFERENCES |
| 89 fprintf(stderr, "%p: AudioContext::~AudioContext(): %u\n", this, m_contextId
); | 94 fprintf(stderr, "%p: AudioContext::~AudioContext(): %u\n", this, m_contextId
); |
| 90 #endif | 95 #endif |
| 91 } | 96 } |
| 92 | 97 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 InvalidAccessError, | 136 InvalidAccessError, |
| 132 "cannot resume a closed AudioContext")); | 137 "cannot resume a closed AudioContext")); |
| 133 } | 138 } |
| 134 | 139 |
| 135 recordUserGestureState(); | 140 recordUserGestureState(); |
| 136 | 141 |
| 137 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 142 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 138 ScriptPromise promise = resolver->promise(); | 143 ScriptPromise promise = resolver->promise(); |
| 139 | 144 |
| 140 // Restart the destination node to pull on the audio graph. | 145 // Restart the destination node to pull on the audio graph. |
| 141 if (destination()) | 146 if (destination()) { |
| 147 m_outputTimestampFramesOrigin = currentSampleFrame(); |
| 142 startRendering(); | 148 startRendering(); |
| 149 } |
| 143 | 150 |
| 144 // Save the resolver which will get resolved when the destination node start
s pulling on the | 151 // Save the resolver which will get resolved when the destination node start
s pulling on the |
| 145 // graph again. | 152 // graph again. |
| 146 { | 153 { |
| 147 AutoLocker locker(this); | 154 AutoLocker locker(this); |
| 148 m_resumeResolvers.append(resolver); | 155 m_resumeResolvers.append(resolver); |
| 149 } | 156 } |
| 150 | 157 |
| 151 return promise; | 158 return promise; |
| 152 } | 159 } |
| 153 | 160 |
| 161 static double toPerformanceTime(ExecutionContext* context, double seconds) |
| 162 { |
| 163 if (!context) |
| 164 return 0.0; |
| 165 |
| 166 LocalDOMWindow* window = context->executingWindow(); |
| 167 if (!window) |
| 168 return 0.0; |
| 169 |
| 170 Performance* performance = DOMWindowPerformance::performance(*window); |
| 171 if (!performance) |
| 172 return 0.0; |
| 173 |
| 174 return performance->monotonicTimeToDOMHighResTimeStamp(seconds); |
| 175 } |
| 176 |
| 177 void AudioContext::getOutputTimestamp(AudioTimestamp& result) |
| 178 { |
| 179 DCHECK(isMainThread()); |
| 180 if (!destination()) { |
| 181 result.setContextTime(0.0); |
| 182 result.setPerformanceTime(0.0); |
| 183 return; |
| 184 } |
| 185 |
| 186 WebAudioTimestamp timestamp = outputTimestamp(); |
| 187 double sampleRate = destination()->audioDestinationHandler().sampleRate(); |
| 188 double contextTime = (m_outputTimestampFramesOrigin + timestamp.frames) / sa
mpleRate; |
| 189 double performanceTime = timestamp.seconds ? toPerformanceTime(getExecutionC
ontext(), timestamp.seconds) : 0.0; |
| 190 |
| 191 result.setContextTime(contextTime); |
| 192 result.setPerformanceTime(performanceTime); |
| 193 } |
| 194 |
| 154 ScriptPromise AudioContext::closeContext(ScriptState* scriptState) | 195 ScriptPromise AudioContext::closeContext(ScriptState* scriptState) |
| 155 { | 196 { |
| 156 if (isContextClosed()) { | 197 if (isContextClosed()) { |
| 157 // We've already closed the context previously, but it hasn't yet been r
esolved, so just | 198 // We've already closed the context previously, but it hasn't yet been r
esolved, so just |
| 158 // create a new promise and reject it. | 199 // create a new promise and reject it. |
| 159 return ScriptPromise::rejectWithDOMException( | 200 return ScriptPromise::rejectWithDOMException( |
| 160 scriptState, | 201 scriptState, |
| 161 DOMException::create(InvalidStateError, | 202 DOMException::create(InvalidStateError, |
| 162 "Cannot close a context that is being closed or has already been
closed.")); | 203 "Cannot close a context that is being closed or has already been
closed.")); |
| 163 } | 204 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 ASSERT(destination()); | 242 ASSERT(destination()); |
| 202 | 243 |
| 203 if (contextState() == Running) { | 244 if (contextState() == Running) { |
| 204 destination()->audioDestinationHandler().stopRendering(); | 245 destination()->audioDestinationHandler().stopRendering(); |
| 205 setContextState(Suspended); | 246 setContextState(Suspended); |
| 206 deferredTaskHandler().clearHandlersToBeDeleted(); | 247 deferredTaskHandler().clearHandlersToBeDeleted(); |
| 207 } | 248 } |
| 208 } | 249 } |
| 209 | 250 |
| 210 } // namespace blink | 251 } // namespace blink |
| OLD | NEW |