| Index: Source/modules/webaudio/AudioScheduledSourceNode.cpp
|
| diff --git a/Source/modules/webaudio/AudioScheduledSourceNode.cpp b/Source/modules/webaudio/AudioScheduledSourceNode.cpp
|
| index 876da2a1b6c24a6d556685a9ac5a5e17fda89519..7aa6439f9edddb5db49fdfafa14d7f1e4bd2c49a 100644
|
| --- a/Source/modules/webaudio/AudioScheduledSourceNode.cpp
|
| +++ b/Source/modules/webaudio/AudioScheduledSourceNode.cpp
|
| @@ -28,6 +28,9 @@
|
|
|
| #include "modules/webaudio/AudioScheduledSourceNode.h"
|
|
|
| +#include "bindings/v8/ExceptionMessages.h"
|
| +#include "bindings/v8/ExceptionState.h"
|
| +#include "core/dom/ExceptionCode.h"
|
| #include "core/events/Event.h"
|
| #include "platform/audio/AudioUtilities.h"
|
| #include "modules/webaudio/AudioContext.h"
|
| @@ -46,6 +49,7 @@ AudioScheduledSourceNode::AudioScheduledSourceNode(AudioContext* context, float
|
| , m_startTime(0)
|
| , m_endTime(UnknownTime)
|
| , m_hasEndedListener(false)
|
| + , m_stopCalled(false)
|
| {
|
| }
|
|
|
| @@ -134,34 +138,51 @@ void AudioScheduledSourceNode::updateSchedulingInfo(size_t quantumFrameSize,
|
| return;
|
| }
|
|
|
| -void AudioScheduledSourceNode::start(double when)
|
| +
|
| +void AudioScheduledSourceNode::start(double when, ExceptionState& es)
|
| {
|
| ASSERT(isMainThread());
|
| - if (m_playbackState != UNSCHEDULED_STATE)
|
| +
|
| + if (m_playbackState != UNSCHEDULED_STATE) {
|
| + es.throwDOMException(
|
| + InvalidStateError,
|
| + ExceptionMessages::failedToExecute(
|
| + "start",
|
| + "OscillatorNode",
|
| + "cannot call start more than once."));
|
| return;
|
| + }
|
|
|
| m_startTime = when;
|
| m_playbackState = SCHEDULED_STATE;
|
| }
|
|
|
| -void AudioScheduledSourceNode::stop(double when)
|
| +void AudioScheduledSourceNode::stop(double when, ExceptionState& es)
|
| {
|
| ASSERT(isMainThread());
|
| - if (!(m_playbackState == SCHEDULED_STATE || m_playbackState == PLAYING_STATE))
|
| - return;
|
| -
|
| - when = max(0.0, when);
|
| - m_endTime = when;
|
| -}
|
|
|
| -void AudioScheduledSourceNode::noteOn(double when)
|
| -{
|
| - start(when);
|
| -}
|
| -
|
| -void AudioScheduledSourceNode::noteOff(double when)
|
| -{
|
| - stop(when);
|
| + if (m_stopCalled) {
|
| + es.throwDOMException(
|
| + InvalidStateError,
|
| + ExceptionMessages::failedToExecute(
|
| + "stop",
|
| + "OscillatorNode",
|
| + "cannot call stop more than once."));
|
| + } else if (m_playbackState == UNSCHEDULED_STATE) {
|
| + es.throwDOMException(
|
| + InvalidStateError,
|
| + ExceptionMessages::failedToExecute(
|
| + "stop",
|
| + "OscillatorNode",
|
| + "cannot call stop without calling start first."));
|
| + } else {
|
| + // This can only happen from the SCHEDULED_STATE or PLAYING_STATE. The UNSCHEDULED_STATE is
|
| + // handled above, and the FINISHED_STATE is only reachable after stop() has been called, and
|
| + // hence m_stopCalled is true. But that case is handled above.
|
| + when = max(0.0, when);
|
| + m_endTime = when;
|
| + m_stopCalled = true;
|
| + }
|
| }
|
|
|
| void AudioScheduledSourceNode::setOnended(PassRefPtr<EventListener> listener, DOMWrapperWorld* isolatedWorld)
|
|
|