1 /*
2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 * Copyright (C) 2011 Ericsson AB. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "modules/mediastream/MediaStreamTrack.h"
28
29 #include "bindings/v8/ExceptionMessages.h"
30 #include "core/dom/ExceptionCode.h"
31 #include "core/dom/ExecutionContext.h"
32 #include "modules/mediastream/MediaStream.h"
33 #include "modules/mediastream/MediaStreamTrackSourcesCallback.h"
34 #include "modules/mediastream/MediaStreamTrackSourcesRequestImpl.h"
35 #include "platform/mediastream/MediaStreamCenter.h"
36 #include "platform/mediastream/MediaStreamComponent.h"
37 #include "public/platform/WebSourceInfo.h"
38
39 namespace WebCore {
40
create(ExecutionContext * context,MediaStreamComponent * component)41 PassRefPtrWillBeRawPtr<MediaStreamTrack> MediaStreamTrack::create(ExecutionContext* context, MediaStreamComponent* component)
42 {
43 RefPtrWillBeRawPtr<MediaStreamTrack> track = adoptRefWillBeRefCountedGarbageCollected(new MediaStreamTrack(context, component));
44 track->suspendIfNeeded();
45 return track.release();
46 }
47
MediaStreamTrack(ExecutionContext * context,MediaStreamComponent * component)48 MediaStreamTrack::MediaStreamTrack(ExecutionContext* context, MediaStreamComponent* component)
49 : ActiveDOMObject(context)
50 , m_readyState(MediaStreamSource::ReadyStateLive)
51 , m_isIteratingRegisteredMediaStreams(false)
52 , m_stopped(false)
53 , m_component(component)
54 {
55 ScriptWrappable::init(this);
56 m_component->source()->addObserver(this);
57 }
58
~MediaStreamTrack()59 MediaStreamTrack::~MediaStreamTrack()
60 {
61 m_component->source()->removeObserver(this);
62 }
63
kind() const64 String MediaStreamTrack::kind() const
65 {
66 DEFINE_STATIC_LOCAL(String, audioKind, ("audio"));
67 DEFINE_STATIC_LOCAL(String, videoKind, ("video"));
68
69 switch (m_component->source()->type()) {
70 case MediaStreamSource::TypeAudio:
71 return audioKind;
72 case MediaStreamSource::TypeVideo:
73 return videoKind;
74 }
75
76 ASSERT_NOT_REACHED();
77 return audioKind;
78 }
79
id() const80 String MediaStreamTrack::id() const
81 {
82 return m_component->id();
83 }
84
label() const85 String MediaStreamTrack::label() const
86 {
87 return m_component->source()->name();
88 }
89
enabled() const90 bool MediaStreamTrack::enabled() const
91 {
92 return m_component->enabled();
93 }
94
setEnabled(bool enabled)95 void MediaStreamTrack::setEnabled(bool enabled)
96 {
97 if (enabled == m_component->enabled())
98 return;
99
100 m_component->setEnabled(enabled);
101
102 if (!ended())
103 MediaStreamCenter::instance().didSetMediaStreamTrackEnabled(m_component.get());
104 }
105
readyState() const106 String MediaStreamTrack::readyState() const
107 {
108 if (ended())
109 return "ended";
110
111 switch (m_readyState) {
112 case MediaStreamSource::ReadyStateLive:
113 return "live";
114 case MediaStreamSource::ReadyStateMuted:
115 return "muted";
116 case MediaStreamSource::ReadyStateEnded:
117 return "ended";
118 }
119
120 ASSERT_NOT_REACHED();
121 return String();
122 }
123
getSources(ExecutionContext * context,PassOwnPtr<MediaStreamTrackSourcesCallback> callback,ExceptionState & exceptionState)124 void MediaStreamTrack::getSources(ExecutionContext* context, PassOwnPtr<MediaStreamTrackSourcesCallback> callback, ExceptionState& exceptionState)
125 {
126 RefPtrWillBeRawPtr<MediaStreamTrackSourcesRequest> request = MediaStreamTrackSourcesRequestImpl::create(context->securityOrigin()->toString(), callback);
127 if (!MediaStreamCenter::instance().getMediaStreamTrackSources(request.release()))
128 exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::failedToExecute("getSources", "MediaStreamTrack", "Functionality not implemented yet"));
129 }
130
stopTrack(ExceptionState & exceptionState)131 void MediaStreamTrack::stopTrack(ExceptionState& exceptionState)
132 {
133 if (ended())
134 return;
135
136 m_readyState = MediaStreamSource::ReadyStateEnded;
137 MediaStreamCenter::instance().didStopMediaStreamTrack(component());
138 dispatchEvent(Event::create(EventTypeNames::ended));
139 propagateTrackEnded();
140 }
141
clone(ExecutionContext * context)142 PassRefPtrWillBeRawPtr<MediaStreamTrack> MediaStreamTrack::clone(ExecutionContext* context)
143 {
144 RefPtr<MediaStreamComponent> clonedComponent = MediaStreamComponent::create(component()->source());
145 RefPtrWillBeRawPtr<MediaStreamTrack> clonedTrack = MediaStreamTrack::create(context, clonedComponent.get());
146 MediaStreamCenter::instance().didCreateMediaStreamTrack(clonedComponent.get());
147 return clonedTrack.release();
148 }
149
ended() const150 bool MediaStreamTrack::ended() const
151 {
152 return m_stopped || (m_readyState == MediaStreamSource::ReadyStateEnded);
153 }
154
sourceChangedState()155 void MediaStreamTrack::sourceChangedState()
156 {
157 if (ended())
158 return;
159
160 m_readyState = m_component->source()->readyState();
161 switch (m_readyState) {
162 case MediaStreamSource::ReadyStateLive:
163 dispatchEvent(Event::create(EventTypeNames::unmute));
164 break;
165 case MediaStreamSource::ReadyStateMuted:
166 dispatchEvent(Event::create(EventTypeNames::mute));
167 break;
168 case MediaStreamSource::ReadyStateEnded:
169 dispatchEvent(Event::create(EventTypeNames::ended));
170 propagateTrackEnded();
171 break;
172 }
173 }
174
propagateTrackEnded()175 void MediaStreamTrack::propagateTrackEnded()
176 {
177 RELEASE_ASSERT(!m_isIteratingRegisteredMediaStreams);
178 m_isIteratingRegisteredMediaStreams = true;
179 for (WillBeHeapHashSet<RawPtrWillBeMember<MediaStream> >::iterator iter = m_registeredMediaStreams.begin(); iter != m_registeredMediaStreams.end(); ++iter)
180 (*iter)->trackEnded();
181 m_isIteratingRegisteredMediaStreams = false;
182 }
183
component()184 MediaStreamComponent* MediaStreamTrack::component()
185 {
186 return m_component.get();
187 }
188
stop()189 void MediaStreamTrack::stop()
190 {
191 m_stopped = true;
192 }
193
createWebAudioSource()194 PassOwnPtr<AudioSourceProvider> MediaStreamTrack::createWebAudioSource()
195 {
196 return MediaStreamCenter::instance().createWebAudioSourceFromMediaStreamTrack(component());
197 }
198
registerMediaStream(MediaStream * mediaStream)199 void MediaStreamTrack::registerMediaStream(MediaStream* mediaStream)
200 {
201 RELEASE_ASSERT(!m_isIteratingRegisteredMediaStreams);
202 RELEASE_ASSERT(!m_registeredMediaStreams.contains(mediaStream));
203 m_registeredMediaStreams.add(mediaStream);
204 }
205
unregisterMediaStream(MediaStream * mediaStream)206 void MediaStreamTrack::unregisterMediaStream(MediaStream* mediaStream)
207 {
208 RELEASE_ASSERT(!m_isIteratingRegisteredMediaStreams);
209 WillBeHeapHashSet<RawPtrWillBeMember<MediaStream> >::iterator iter = m_registeredMediaStreams.find(mediaStream);
210 RELEASE_ASSERT(iter != m_registeredMediaStreams.end());
211 m_registeredMediaStreams.remove(iter);
212 }
213
interfaceName() const214 const AtomicString& MediaStreamTrack::interfaceName() const
215 {
216 return EventTargetNames::MediaStreamTrack;
217 }
218
executionContext() const219 ExecutionContext* MediaStreamTrack::executionContext() const
220 {
221 return ActiveDOMObject::executionContext();
222 }
223
trace(Visitor * visitor)224 void MediaStreamTrack::trace(Visitor* visitor)
225 {
226 visitor->trace(m_registeredMediaStreams);
227 EventTargetWithInlineData::trace(visitor);
228 }
229
230 } // namespace WebCore
231