[MediaStream] 'get' prefix is missing for capabilities and constraints.
[WebKit-https.git] / Source / WebCore / Modules / mediastream / MediaStreamTrack.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  * Copyright (C) 2011 Ericsson AB. All rights reserved.
4  * Copyright (C) 2013 Apple Inc. All rights reserved.
5  * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1.  Redistributions of source code must retain the above copyright
11  *     notice, this list of conditions and the following disclaimer.
12  * 2.  Redistributions in binary form must reproduce the above copyright
13  *     notice, this list of conditions and the following disclaimer in the
14  *     documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "config.h"
29 #include "MediaStreamTrack.h"
30
31 #if ENABLE(MEDIA_STREAM)
32
33 #include "AllAudioCapabilities.h"
34 #include "AllVideoCapabilities.h"
35 #include "AudioStreamTrack.h"
36 #include "Dictionary.h"
37 #include "Event.h"
38 #include "ExceptionCode.h"
39 #include "ExceptionCodePlaceholder.h"
40 #include "MediaConstraintsImpl.h"
41 #include "MediaSourceStates.h"
42 #include "MediaStream.h"
43 #include "MediaStreamCenter.h"
44 #include "MediaStreamPrivate.h"
45 #include "MediaStreamTrackSourcesCallback.h"
46 #include "MediaStreamTrackSourcesRequest.h"
47 #include "MediaTrackConstraints.h"
48 #include "NotImplemented.h"
49 #include "VideoStreamTrack.h"
50 #include <wtf/Functional.h>
51 #include <wtf/NeverDestroyed.h>
52
53 namespace WebCore {
54
55 MediaStreamTrack::MediaStreamTrack(ScriptExecutionContext& context, MediaStreamTrackPrivate& privateTrack, const Dictionary* constraints)
56     : RefCounted()
57     , ActiveDOMObject(&context)
58     , m_privateTrack(privateTrack)
59     , m_eventDispatchScheduled(false)
60     , m_stoppingTrack(false)
61 {
62     suspendIfNeeded();
63
64     m_privateTrack->setClient(this);
65
66     if (constraints)
67         applyConstraints(*constraints);
68 }
69
70 MediaStreamTrack::MediaStreamTrack(MediaStreamTrack& other)
71     : RefCounted()
72     , ActiveDOMObject(other.scriptExecutionContext())
73     , m_privateTrack(*other.privateTrack().clone())
74     , m_eventDispatchScheduled(false)
75     , m_stoppingTrack(false)
76 {
77     suspendIfNeeded();
78
79     m_privateTrack->setClient(this);
80 }
81
82 MediaStreamTrack::~MediaStreamTrack()
83 {
84     m_privateTrack->setClient(nullptr);
85 }
86
87 void MediaStreamTrack::setSource(PassRefPtr<MediaStreamSource> newSource)
88 {
89     m_privateTrack->setSource(newSource);
90 }
91
92 const String& MediaStreamTrack::id() const
93 {
94     return m_privateTrack->id();
95 }
96
97 const String& MediaStreamTrack::label() const
98 {
99     return m_privateTrack->label();
100 }
101
102 bool MediaStreamTrack::enabled() const
103 {
104     return m_privateTrack->enabled();
105 }
106
107 void MediaStreamTrack::setEnabled(bool enabled)
108 {
109     m_privateTrack->setEnabled(enabled);
110 }
111
112 bool MediaStreamTrack::stopped() const
113 {
114     return m_privateTrack->stopped();
115 }
116
117 bool MediaStreamTrack::muted() const
118 {
119     return m_privateTrack->muted();
120 }
121
122 bool MediaStreamTrack::readonly() const
123 {
124     return m_privateTrack->readonly();
125 }
126
127 bool MediaStreamTrack::remote() const
128 {
129     return m_privateTrack->remote();
130 }
131
132 const AtomicString& MediaStreamTrack::readyState() const
133 {
134     static NeverDestroyed<AtomicString> ended("ended", AtomicString::ConstructFromLiteral);
135     static NeverDestroyed<AtomicString> live("live", AtomicString::ConstructFromLiteral);
136     static NeverDestroyed<AtomicString> newState("new", AtomicString::ConstructFromLiteral);
137
138     switch (m_privateTrack->readyState()) {
139     case MediaStreamSource::Live:
140         return live;
141     case MediaStreamSource::New:
142         return newState;
143     case MediaStreamSource::Ended:
144         return ended;
145     }
146
147     ASSERT_NOT_REACHED();
148     return emptyAtom;
149 }
150
151 void MediaStreamTrack::getSources(ScriptExecutionContext* context, PassRefPtr<MediaStreamTrackSourcesCallback> callback, ExceptionCode& ec)
152 {
153     RefPtr<MediaStreamTrackSourcesRequest> request = MediaStreamTrackSourcesRequest::create(context, callback);
154     if (!MediaStreamCenter::shared().getMediaStreamTrackSources(request.release()))
155         ec = NOT_SUPPORTED_ERR;
156 }
157
158 RefPtr<MediaTrackConstraints> MediaStreamTrack::getConstraints() const
159 {
160     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=122428
161     notImplemented();
162     return 0;
163 }
164
165 RefPtr<MediaSourceStates> MediaStreamTrack::states() const
166 {
167     return MediaSourceStates::create(m_privateTrack->states());
168 }
169
170 RefPtr<MediaStreamCapabilities> MediaStreamTrack::getCapabilities() const
171 {
172     // The source may be shared by multiple tracks, so its states is not necessarily
173     // in sync with the track state. A track that is new or has ended always has a source
174     // type of "none".
175     RefPtr<MediaStreamSourceCapabilities> sourceCapabilities = m_privateTrack->capabilities();
176     MediaStreamSource::ReadyState readyState = m_privateTrack->readyState();
177     if (readyState == MediaStreamSource::New || readyState == MediaStreamSource::Ended)
178         sourceCapabilities->setSourceType(MediaStreamSourceStates::None);
179     
180     return MediaStreamCapabilities::create(sourceCapabilities.release());
181 }
182
183 void MediaStreamTrack::applyConstraints(const Dictionary& constraints)
184 {
185     m_constraints->initialize(constraints);
186     m_privateTrack->applyConstraints(m_constraints);
187 }
188
189 void MediaStreamTrack::applyConstraints(PassRefPtr<MediaConstraints>)
190 {
191     // FIXME: apply the new constraints to the track
192     // https://bugs.webkit.org/show_bug.cgi?id=122428
193 }
194
195 RefPtr<MediaStreamTrack> MediaStreamTrack::clone()
196 {
197     if (m_privateTrack->type() == MediaStreamSource::Audio)
198         return AudioStreamTrack::create(*this);
199
200     return VideoStreamTrack::create(*this);
201 }
202
203 void MediaStreamTrack::stopProducingData()
204 {
205     // NOTE: this method is called when the "stop" method is called from JS, using
206     // the "ImplementedAs" IDL attribute. This is done because ActiveDOMObject requires
207     // a "stop" method.
208     
209     // The stop method should "Permanently stop the generation of data for track's source", but it
210     // should not post an 'ended' event. 
211     m_stoppingTrack = true;
212     m_privateTrack->stop(MediaStreamTrackPrivate::StopTrackAndStopSource);
213     m_stoppingTrack = false;
214 }
215
216 bool MediaStreamTrack::ended() const
217 {
218     return m_privateTrack->ended();
219 }
220
221 void MediaStreamTrack::addObserver(MediaStreamTrack::Observer* observer)
222 {
223     m_observers.append(observer);
224 }
225
226 void MediaStreamTrack::removeObserver(MediaStreamTrack::Observer* observer)
227 {
228     size_t pos = m_observers.find(observer);
229     if (pos != notFound)
230         m_observers.remove(pos);
231 }
232
233 void MediaStreamTrack::trackReadyStateChanged()
234 {
235     if (stopped())
236         return;
237
238     MediaStreamSource::ReadyState readyState = m_privateTrack->readyState();
239     if (readyState == MediaStreamSource::Live)
240         scheduleEventDispatch(Event::create(eventNames().startedEvent, false, false));
241     else if (readyState == MediaStreamSource::Ended && !m_stoppingTrack)
242         scheduleEventDispatch(Event::create(eventNames().endedEvent, false, false));
243
244     configureTrackRendering();
245 }
246     
247 void MediaStreamTrack::trackMutedChanged()
248 {
249     if (stopped())
250         return;
251
252     if (muted())
253         scheduleEventDispatch(Event::create(eventNames().muteEvent, false, false));
254     else
255         scheduleEventDispatch(Event::create(eventNames().unmuteEvent, false, false));
256
257     configureTrackRendering();
258 }
259
260 void MediaStreamTrack::trackEnabledChanged()
261 {
262     if (stopped())
263         return;
264
265     setEnabled(m_privateTrack->enabled());
266     configureTrackRendering();
267 }
268
269 void MediaStreamTrack::configureTrackRendering()
270 {
271     if (stopped())
272         return;
273
274     // 4.3.1
275     // ... media from the source only flows when a MediaStreamTrack object is both unmuted and enabled
276 }
277
278 void MediaStreamTrack::trackDidEnd()
279 {
280     m_privateTrack->setReadyState(MediaStreamSource::Ended);
281
282     for (Vector<Observer*>::iterator i = m_observers.begin(); i != m_observers.end(); ++i)
283         (*i)->trackDidEnd();
284 }
285
286 void MediaStreamTrack::stop()
287 {
288     m_privateTrack->stop(MediaStreamTrackPrivate::StopTrackOnly);
289 }
290
291 void MediaStreamTrack::scheduleEventDispatch(PassRefPtr<Event> event)
292 {
293     {
294         MutexLocker locker(m_mutex);
295         m_scheduledEvents.append(event);
296         if (m_eventDispatchScheduled)
297             return;
298         m_eventDispatchScheduled = true;
299     }
300
301     callOnMainThread(bind(&MediaStreamTrack::dispatchQueuedEvents, this));
302 }
303
304 void MediaStreamTrack::dispatchQueuedEvents()
305 {
306     Vector<RefPtr<Event>> events;
307     {
308         MutexLocker locker(m_mutex);
309         m_eventDispatchScheduled = false;
310         events.swap(m_scheduledEvents);
311     }
312     if (!scriptExecutionContext())
313         return;
314
315     for (auto it = events.begin(); it != events.end(); ++it)
316         dispatchEvent((*it).release());
317
318     events.clear();
319 }
320
321 } // namespace WebCore
322
323 #endif // ENABLE(MEDIA_STREAM)