Support the 'onended' EventListener property for AudioBufferSourceNode and Oscillator...
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 29 May 2013 17:11:53 +0000 (17:11 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 29 May 2013 17:11:53 +0000 (17:11 +0000)
https://bugs.webkit.org/show_bug.cgi?id=116798

Reviewed by Eric Carlson.

Source/WebCore:

Tests: webaudio/audiobuffersource-ended.html
       webaudio/oscillator-ended.html

* Modules/webaudio/AudioScheduledSourceNode.cpp:
(WebCore::AudioScheduledSourceNode::AudioScheduledSourceNode):
(WebCore::AudioScheduledSourceNode::setOnended): Set m_hasEndedListener.
(WebCore::AudioScheduledSourceNode::finish): Call notifyEndedDispatch on the main thread.
(WebCore::AudioScheduledSourceNode::notifyEndedDispatch): Call notifyEnded().
(WebCore::AudioScheduledSourceNode::notifyEnded): Call the onended event listener.
* Modules/webaudio/AudioScheduledSourceNode.h:
(WebCore::AudioScheduledSourceNode::onended): Added boilerplate.
* Modules/webaudio/AudioBufferSourceNode.idl: Added the onerror attribute.
* Modules/webaudio/OscillatorNode.idl: Ditto.

LayoutTests:

* webaudio/audiobuffersource-ended-expected.txt: Added.
* webaudio/audiobuffersource-ended.html: Added.
* webaudio/oscillator-ended-expected.txt: Added.
* webaudio/oscillator-ended.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@150905 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/webaudio/audiobuffersource-ended-expected.txt [new file with mode: 0644]
LayoutTests/webaudio/audiobuffersource-ended.html [new file with mode: 0644]
LayoutTests/webaudio/oscillator-ended-expected.txt [new file with mode: 0644]
LayoutTests/webaudio/oscillator-ended.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Modules/webaudio/AudioBufferSourceNode.idl
Source/WebCore/Modules/webaudio/AudioScheduledSourceNode.cpp
Source/WebCore/Modules/webaudio/AudioScheduledSourceNode.h
Source/WebCore/Modules/webaudio/OscillatorNode.idl

index 3192482..1fa3433 100644 (file)
@@ -1,3 +1,15 @@
+2013-05-26  Jer Noble  <jer.noble@apple.com>
+
+        Support the 'onended' EventListener property for AudioBufferSourceNode and OscillatorNode.
+        https://bugs.webkit.org/show_bug.cgi?id=116798
+
+        Reviewed by Eric Carlson.
+
+        * webaudio/audiobuffersource-ended-expected.txt: Added.
+        * webaudio/audiobuffersource-ended.html: Added.
+        * webaudio/oscillator-ended-expected.txt: Added.
+        * webaudio/oscillator-ended.html: Added.
+
 2013-05-29  Bem Jones-Bey  <bjonesbe@adobe.com>
 
         [CSS Shapes] Support parsing inset-rectangle shapes
diff --git a/LayoutTests/webaudio/audiobuffersource-ended-expected.txt b/LayoutTests/webaudio/audiobuffersource-ended-expected.txt
new file mode 100644 (file)
index 0000000..eea4615
--- /dev/null
@@ -0,0 +1,3 @@
+Tests that AudioBufferSourceNode calls its onended EventListener.
+PASS source.onended called.
+
diff --git a/LayoutTests/webaudio/audiobuffersource-ended.html b/LayoutTests/webaudio/audiobuffersource-ended.html
new file mode 100644 (file)
index 0000000..794acef
--- /dev/null
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<head>
+    <script src="../fast/js/resources/js-test-pre.js"></script>
+    <script src="resources/audio-testing.js"></script>
+    <script src="resources/audiobuffersource-testing.js"></script>
+    <script>
+        var context;
+        var source;
+
+        function runTest() 
+        {
+            if (window.testRunner) {
+                testRunner.dumpAsText();
+                testRunner.waitUntilDone();
+            }
+
+            var sampleRate = 44100.0;
+            var numberOfFrames = 32;
+            context = new webkitOfflineAudioContext(1, numberOfFrames, sampleRate);
+            source = context.createBufferSource();
+            source.buffer = createTestBuffer(context, numberOfFrames);
+            source.connect(context.destination);
+            source.onended = function() 
+            {
+                testPassed("source.onended called.");
+                if (window.testRunner)
+                    testRunner.notifyDone();
+            }
+            source.start(0);
+            context.startRendering();
+        }
+    </script>
+
+</head>
+<body onload="runTest()">
+    <div>Tests that AudioBufferSourceNode calls its onended EventListener.</div>
+    <div id="console"></div>
+</body>
diff --git a/LayoutTests/webaudio/oscillator-ended-expected.txt b/LayoutTests/webaudio/oscillator-ended-expected.txt
new file mode 100644 (file)
index 0000000..9fa4769
--- /dev/null
@@ -0,0 +1,3 @@
+Tests that OscillatorNode calls its onended EventListener.
+PASS osc.onended called.
+
diff --git a/LayoutTests/webaudio/oscillator-ended.html b/LayoutTests/webaudio/oscillator-ended.html
new file mode 100644 (file)
index 0000000..131ae52
--- /dev/null
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<head>
+    <script src="../fast/js/resources/js-test-pre.js"></script>
+    <script src="resources/audio-testing.js"></script>
+    <script src="resources/audiobuffersource-testing.js"></script>
+    <script>
+        var context;
+        var source;
+
+        function runTest()
+        {
+            if (window.testRunner) {
+                testRunner.dumpAsText();
+                testRunner.waitUntilDone();
+            }
+
+            var sampleRate = 44100.0;
+            var lengthInSeconds = 0.1;
+            context = new webkitOfflineAudioContext(1, sampleRate * lengthInSeconds, sampleRate);
+            osc = context.createOscillator();
+            osc.type = "sine"; 
+            osc.connect(context.destination);
+            osc.onended = function() 
+            {
+                testPassed("osc.onended called.");
+                finishJSTest();
+                if (window.testRunner)
+                    testRunner.notifyDone();
+
+            }
+            osc.start(0);
+            osc.stop(0.1);
+            context.startRendering();
+        }
+    </script>
+</head>
+<body onload="runTest()">
+    <div>Tests that OscillatorNode calls its onended EventListener.</div>
+    <div id="console"></div>
+</body>
index 7f74416..33333bf 100644 (file)
@@ -1,3 +1,24 @@
+2013-05-28  Jer Noble  <jer.noble@apple.com>
+
+        Support the 'onended' EventListener property for AudioBufferSourceNode and OscillatorNode.
+        https://bugs.webkit.org/show_bug.cgi?id=116798
+
+        Reviewed by Eric Carlson.
+
+        Tests: webaudio/audiobuffersource-ended.html
+               webaudio/oscillator-ended.html
+
+        * Modules/webaudio/AudioScheduledSourceNode.cpp:
+        (WebCore::AudioScheduledSourceNode::AudioScheduledSourceNode):
+        (WebCore::AudioScheduledSourceNode::setOnended): Set m_hasEndedListener.
+        (WebCore::AudioScheduledSourceNode::finish): Call notifyEndedDispatch on the main thread.
+        (WebCore::AudioScheduledSourceNode::notifyEndedDispatch): Call notifyEnded().
+        (WebCore::AudioScheduledSourceNode::notifyEnded): Call the onended event listener.
+        * Modules/webaudio/AudioScheduledSourceNode.h:
+        (WebCore::AudioScheduledSourceNode::onended): Added boilerplate.
+        * Modules/webaudio/AudioBufferSourceNode.idl: Added the onerror attribute.
+        * Modules/webaudio/OscillatorNode.idl: Ditto.
+
 2013-05-29  Bem Jones-Bey  <bjonesbe@adobe.com>
 
         [CSS Shapes] Support parsing inset-rectangle shapes
index d73fab0..8f5ff4c 100644 (file)
@@ -55,4 +55,6 @@
     [Conditional=LEGACY_WEB_AUDIO] void noteOn(double when);
     [Conditional=LEGACY_WEB_AUDIO] void noteGrainOn(double when, double grainOffset, double grainDuration);
     [Conditional=LEGACY_WEB_AUDIO] void noteOff(double when);
+    
+    attribute EventListener onended;
 };
index f157fb7..b84f69f 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "AudioContext.h"
 #include "AudioUtilities.h"
+#include "Event.h"
 #include <algorithm>
 #include <wtf/MathExtras.h>
 
@@ -44,6 +45,7 @@ AudioScheduledSourceNode::AudioScheduledSourceNode(AudioContext* context, float
     , m_playbackState(UNSCHEDULED_STATE)
     , m_startTime(0)
     , m_endTime(UnknownTime)
+    , m_hasEndedListener(false)
 {
 }
 
@@ -164,6 +166,12 @@ void AudioScheduledSourceNode::noteOff(double when)
 }
 #endif
 
+void AudioScheduledSourceNode::setOnended(PassRefPtr<EventListener> listener)
+{
+    setAttributeEventListener(eventNames().endedEvent, listener);
+    m_hasEndedListener = listener;
+}
+
 void AudioScheduledSourceNode::finish()
 {
     if (m_playbackState != FINISHED_STATE) {
@@ -172,6 +180,25 @@ void AudioScheduledSourceNode::finish()
         m_playbackState = FINISHED_STATE;
         context()->decrementActiveSourceCount();
     }
+
+    if (m_hasEndedListener);
+        callOnMainThread(&AudioScheduledSourceNode::notifyEndedDispatch, this);
+}
+
+void AudioScheduledSourceNode::notifyEndedDispatch(void* userData)
+{
+    static_cast<AudioScheduledSourceNode*>(userData)->notifyEnded();
+}
+
+void AudioScheduledSourceNode::notifyEnded()
+{
+    EventListener* listener = onended();
+    if (!listener)
+        return;
+
+    RefPtr<Event> event = Event::create(eventNames().endedEvent, FALSE, FALSE);
+    event->setTarget(this);
+    listener->handleEvent(context()->scriptExecutionContext(), event.get());
 }
 
 } // namespace WebCore
index 0a4502e..c4c1e02 100644 (file)
@@ -69,6 +69,9 @@ public:
     bool isPlayingOrScheduled() const { return m_playbackState == PLAYING_STATE || m_playbackState == SCHEDULED_STATE; }
     bool hasFinished() const { return m_playbackState == FINISHED_STATE; }
 
+    EventListener* onended() { return getAttributeEventListener(eventNames().endedEvent); }
+    void setOnended(PassRefPtr<EventListener> listener);
+
 protected:
     // Get frame information for the current time quantum.
     // We handle the transition into PLAYING_STATE and FINISHED_STATE here,
@@ -85,6 +88,9 @@ protected:
     // Called when we have no more sound to play or the noteOff() time has been reached.
     virtual void finish();
 
+    static void notifyEndedDispatch(void*);
+    void notifyEnded();
+
     PlaybackState m_playbackState;
 
     // m_startTime is the time to start playing based on the context's timeline (0 or a time less than the context's current time means "now").
@@ -95,6 +101,8 @@ protected:
     // has been reached.
     double m_endTime; // in seconds
 
+    bool m_hasEndedListener;
+
     static const double UnknownTime;
 };
 
index f3f3eb7..1138bbf 100644 (file)
@@ -56,4 +56,5 @@
 
     void setWaveTable(WaveTable waveTable);
 
+    attribute EventListener onended;
 };