| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2012, Google Inc. All rights reserved. | 2 * Copyright (C) 2012, Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 23 */ | 23 */ |
| 24 | 24 |
| 25 #include "config.h" | 25 #include "config.h" |
| 26 | 26 |
| 27 #if ENABLE(WEB_AUDIO) | 27 #if ENABLE(WEB_AUDIO) |
| 28 | 28 |
| 29 #include "modules/webaudio/AudioScheduledSourceNode.h" | 29 #include "modules/webaudio/AudioScheduledSourceNode.h" |
| 30 | 30 |
| 31 #include "bindings/v8/ExceptionMessages.h" |
| 32 #include "bindings/v8/ExceptionState.h" |
| 33 #include "core/dom/ExceptionCode.h" |
| 31 #include "core/events/Event.h" | 34 #include "core/events/Event.h" |
| 32 #include "platform/audio/AudioUtilities.h" | 35 #include "platform/audio/AudioUtilities.h" |
| 33 #include "modules/webaudio/AudioContext.h" | 36 #include "modules/webaudio/AudioContext.h" |
| 34 #include <algorithm> | 37 #include <algorithm> |
| 35 #include "wtf/MathExtras.h" | 38 #include "wtf/MathExtras.h" |
| 36 | 39 |
| 37 using namespace std; | 40 using namespace std; |
| 38 | 41 |
| 39 namespace WebCore { | 42 namespace WebCore { |
| 40 | 43 |
| 41 const double AudioScheduledSourceNode::UnknownTime = -1; | 44 const double AudioScheduledSourceNode::UnknownTime = -1; |
| 42 | 45 |
| 43 AudioScheduledSourceNode::AudioScheduledSourceNode(AudioContext* context, float
sampleRate) | 46 AudioScheduledSourceNode::AudioScheduledSourceNode(AudioContext* context, float
sampleRate) |
| 44 : AudioSourceNode(context, sampleRate) | 47 : AudioSourceNode(context, sampleRate) |
| 45 , m_playbackState(UNSCHEDULED_STATE) | 48 , m_playbackState(UNSCHEDULED_STATE) |
| 46 , m_startTime(0) | 49 , m_startTime(0) |
| 47 , m_endTime(UnknownTime) | 50 , m_endTime(UnknownTime) |
| 48 , m_hasEndedListener(false) | 51 , m_hasEndedListener(false) |
| 52 , m_stopCalled(false) |
| 49 { | 53 { |
| 50 } | 54 } |
| 51 | 55 |
| 52 void AudioScheduledSourceNode::updateSchedulingInfo(size_t quantumFrameSize, | 56 void AudioScheduledSourceNode::updateSchedulingInfo(size_t quantumFrameSize, |
| 53 AudioBus* outputBus, | 57 AudioBus* outputBus, |
| 54 size_t& quantumFrameOffset, | 58 size_t& quantumFrameOffset, |
| 55 size_t& nonSilentFramesToPro
cess) | 59 size_t& nonSilentFramesToPro
cess) |
| 56 { | 60 { |
| 57 ASSERT(outputBus); | 61 ASSERT(outputBus); |
| 58 if (!outputBus) | 62 if (!outputBus) |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 for (unsigned i = 0; i < outputBus->numberOfChannels(); ++i) | 131 for (unsigned i = 0; i < outputBus->numberOfChannels(); ++i) |
| 128 memset(outputBus->channel(i)->mutableData() + zeroStartFrame, 0,
sizeof(float) * framesToZero); | 132 memset(outputBus->channel(i)->mutableData() + zeroStartFrame, 0,
sizeof(float) * framesToZero); |
| 129 } | 133 } |
| 130 | 134 |
| 131 finish(); | 135 finish(); |
| 132 } | 136 } |
| 133 | 137 |
| 134 return; | 138 return; |
| 135 } | 139 } |
| 136 | 140 |
| 137 void AudioScheduledSourceNode::start(double when) | 141 |
| 142 void AudioScheduledSourceNode::start(double when, ExceptionState& es) |
| 138 { | 143 { |
| 139 ASSERT(isMainThread()); | 144 ASSERT(isMainThread()); |
| 140 if (m_playbackState != UNSCHEDULED_STATE) | 145 |
| 146 if (m_playbackState != UNSCHEDULED_STATE) { |
| 147 es.throwDOMException( |
| 148 InvalidStateError, |
| 149 ExceptionMessages::failedToExecute( |
| 150 "start", |
| 151 "OscillatorNode", |
| 152 "cannot call start more than once.")); |
| 141 return; | 153 return; |
| 154 } |
| 142 | 155 |
| 143 m_startTime = when; | 156 m_startTime = when; |
| 144 m_playbackState = SCHEDULED_STATE; | 157 m_playbackState = SCHEDULED_STATE; |
| 145 } | 158 } |
| 146 | 159 |
| 147 void AudioScheduledSourceNode::stop(double when) | 160 void AudioScheduledSourceNode::stop(double when, ExceptionState& es) |
| 148 { | 161 { |
| 149 ASSERT(isMainThread()); | 162 ASSERT(isMainThread()); |
| 150 if (!(m_playbackState == SCHEDULED_STATE || m_playbackState == PLAYING_STATE
)) | |
| 151 return; | |
| 152 | 163 |
| 153 when = max(0.0, when); | 164 if (m_stopCalled) { |
| 154 m_endTime = when; | 165 es.throwDOMException( |
| 155 } | 166 InvalidStateError, |
| 156 | 167 ExceptionMessages::failedToExecute( |
| 157 void AudioScheduledSourceNode::noteOn(double when) | 168 "stop", |
| 158 { | 169 "OscillatorNode", |
| 159 start(when); | 170 "cannot call stop more than once.")); |
| 160 } | 171 } else if (m_playbackState == UNSCHEDULED_STATE) { |
| 161 | 172 es.throwDOMException( |
| 162 void AudioScheduledSourceNode::noteOff(double when) | 173 InvalidStateError, |
| 163 { | 174 ExceptionMessages::failedToExecute( |
| 164 stop(when); | 175 "stop", |
| 176 "OscillatorNode", |
| 177 "cannot call stop without calling start first.")); |
| 178 } else { |
| 179 // This can only happen from the SCHEDULED_STATE or PLAYING_STATE. The U
NSCHEDULED_STATE is |
| 180 // handled above, and the FINISHED_STATE is only reachable after stop()
has been called, and |
| 181 // hence m_stopCalled is true. But that case is handled above. |
| 182 when = max(0.0, when); |
| 183 m_endTime = when; |
| 184 m_stopCalled = true; |
| 185 } |
| 165 } | 186 } |
| 166 | 187 |
| 167 void AudioScheduledSourceNode::setOnended(PassRefPtr<EventListener> listener, DO
MWrapperWorld* isolatedWorld) | 188 void AudioScheduledSourceNode::setOnended(PassRefPtr<EventListener> listener, DO
MWrapperWorld* isolatedWorld) |
| 168 { | 189 { |
| 169 m_hasEndedListener = listener; | 190 m_hasEndedListener = listener; |
| 170 setAttributeEventListener(EventTypeNames::ended, listener, isolatedWorld); | 191 setAttributeEventListener(EventTypeNames::ended, listener, isolatedWorld); |
| 171 } | 192 } |
| 172 | 193 |
| 173 void AudioScheduledSourceNode::finish() | 194 void AudioScheduledSourceNode::finish() |
| 174 { | 195 { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 201 void AudioScheduledSourceNode::NotifyEndedTask::notifyEnded() | 222 void AudioScheduledSourceNode::NotifyEndedTask::notifyEnded() |
| 202 { | 223 { |
| 203 RefPtr<Event> event = Event::create(EventTypeNames::ended); | 224 RefPtr<Event> event = Event::create(EventTypeNames::ended); |
| 204 event->setTarget(m_scheduledNode); | 225 event->setTarget(m_scheduledNode); |
| 205 m_scheduledNode->dispatchEvent(event.get()); | 226 m_scheduledNode->dispatchEvent(event.get()); |
| 206 } | 227 } |
| 207 | 228 |
| 208 } // namespace WebCore | 229 } // namespace WebCore |
| 209 | 230 |
| 210 #endif // ENABLE(WEB_AUDIO) | 231 #endif // ENABLE(WEB_AUDIO) |
| OLD | NEW |