#include "modules/webaudio/AudioScheduledSourceNode.h"
-#include "bindings/v8/ExceptionMessages.h"
-#include "bindings/v8/ExceptionState.h"
+#include "bindings/core/v8/ExceptionState.h"
+#include "core/dom/CrossThreadTask.h"
#include "core/dom/ExceptionCode.h"
-#include "core/events/Event.h"
-#include "platform/audio/AudioUtilities.h"
+#include "modules/EventModules.h"
#include "modules/webaudio/AudioContext.h"
-#include <algorithm>
+#include "platform/audio/AudioUtilities.h"
#include "wtf/MathExtras.h"
+#include <algorithm>
-using namespace std;
+namespace blink {
-namespace WebCore {
+#if !ENABLE(OILPAN)
+// We need a dedicated specialization for AudioScheduledSourceNode because it
+// doesn't inherit from RefCounted.
+template<> struct CrossThreadCopierBase<false, false, false, PassRefPtr<AudioScheduledSourceNode> > : public CrossThreadCopierPassThrough<PassRefPtr<AudioScheduledSourceNode> > {
+};
+#endif
const double AudioScheduledSourceNode::UnknownTime = -1;
, m_startTime(0)
, m_endTime(UnknownTime)
, m_hasEndedListener(false)
- , m_stopCalled(false)
{
}
if (m_playbackState == SCHEDULED_STATE) {
// Increment the active source count only if we're transitioning from SCHEDULED_STATE to PLAYING_STATE.
m_playbackState = PLAYING_STATE;
- context()->incrementActiveSourceCount();
}
quantumFrameOffset = startFrame > quantumStartFrame ? startFrame - quantumStartFrame : 0;
- quantumFrameOffset = min(quantumFrameOffset, quantumFrameSize); // clamp to valid range
+ quantumFrameOffset = std::min(quantumFrameOffset, quantumFrameSize); // clamp to valid range
nonSilentFramesToProcess = quantumFrameSize - quantumFrameOffset;
if (!nonSilentFramesToProcess) {
return;
}
-
-void AudioScheduledSourceNode::start(double when, ExceptionState& es)
+void AudioScheduledSourceNode::start(double when, ExceptionState& exceptionState)
{
ASSERT(isMainThread());
if (m_playbackState != UNSCHEDULED_STATE) {
- es.throwDOMException(
+ exceptionState.throwDOMException(
InvalidStateError,
- ExceptionMessages::failedToExecute(
- "start",
- "OscillatorNode",
- "cannot call start more than once."));
+ "cannot call start more than once.");
return;
}
m_playbackState = SCHEDULED_STATE;
}
-void AudioScheduledSourceNode::stop(double when, ExceptionState& es)
+void AudioScheduledSourceNode::stop(double when, ExceptionState& exceptionState)
{
ASSERT(isMainThread());
- if (m_stopCalled) {
- es.throwDOMException(
- InvalidStateError,
- ExceptionMessages::failedToExecute(
- "stop",
- "OscillatorNode",
- "cannot call stop more than once."));
- } else if (m_playbackState == UNSCHEDULED_STATE) {
- es.throwDOMException(
+ if (m_playbackState == UNSCHEDULED_STATE) {
+ exceptionState.throwDOMException(
InvalidStateError,
- ExceptionMessages::failedToExecute(
- "stop",
- "OscillatorNode",
- "cannot call stop without calling start first."));
+ "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);
+ // stop() can be called more than once, with the last call to stop taking effect, unless the
+ // source has already stopped due to earlier calls to stop. No exceptions are thrown in any
+ // case.
+ when = std::max(0.0, when);
m_endTime = when;
- m_stopCalled = true;
}
}
-void AudioScheduledSourceNode::setOnended(PassRefPtr<EventListener> listener, DOMWrapperWorld* isolatedWorld)
+void AudioScheduledSourceNode::setOnended(PassRefPtr<EventListener> listener)
{
m_hasEndedListener = listener;
- setAttributeEventListener(EventTypeNames::ended, listener, isolatedWorld);
+ setAttributeEventListener(EventTypeNames::ended, listener);
}
void AudioScheduledSourceNode::finish()
// Let the context dereference this AudioNode.
context()->notifyNodeFinishedProcessing(this);
m_playbackState = FINISHED_STATE;
- context()->decrementActiveSourceCount();
}
- if (m_hasEndedListener) {
- // |task| will keep the AudioScheduledSourceNode alive until the listener has been handled.
- OwnPtr<NotifyEndedTask> task = adoptPtr(new NotifyEndedTask(this));
- callOnMainThread(&AudioScheduledSourceNode::notifyEndedDispatch, task.leakPtr());
+ if (m_hasEndedListener && context()->executionContext()) {
+ context()->executionContext()->postTask(createCrossThreadTask(&AudioScheduledSourceNode::notifyEnded, PassRefPtrWillBeRawPtr<AudioScheduledSourceNode>(this)));
}
}
-void AudioScheduledSourceNode::notifyEndedDispatch(void* userData)
-{
- OwnPtr<NotifyEndedTask> task = adoptPtr(static_cast<NotifyEndedTask*>(userData));
-
- task->notifyEnded();
-}
-
-AudioScheduledSourceNode::NotifyEndedTask::NotifyEndedTask(PassRefPtr<AudioScheduledSourceNode> sourceNode)
- : m_scheduledNode(sourceNode)
-{
-}
-
-void AudioScheduledSourceNode::NotifyEndedTask::notifyEnded()
+void AudioScheduledSourceNode::notifyEnded()
{
- RefPtr<Event> event = Event::create(EventTypeNames::ended);
- event->setTarget(m_scheduledNode);
- m_scheduledNode->dispatchEvent(event.get());
+ dispatchEvent(Event::create(EventTypeNames::ended));
}
-} // namespace WebCore
+} // namespace blink
#endif // ENABLE(WEB_AUDIO)