Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1154)

Side by Side Diff: third_party/WebKit/Source/core/html/MediaController.cpp

Issue 1373423003: Remove MediaController (already diabled by REF) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: update web-platform-tests expectations Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2011 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "core/html/MediaController.h"
28
29 #include "bindings/core/v8/ExceptionMessages.h"
30 #include "bindings/core/v8/ExceptionState.h"
31 #include "bindings/core/v8/ExceptionStatePlaceholder.h"
32 #include "core/dom/ExceptionCode.h"
33 #include "core/dom/ExecutionContext.h"
34 #include "core/events/Event.h"
35 #include "core/events/GenericEventQueue.h"
36 #include "core/html/HTMLMediaElement.h"
37 #include "core/html/TimeRanges.h"
38 #include "platform/Clock.h"
39 #include "wtf/CurrentTime.h"
40 #include "wtf/StdLibExtras.h"
41 #include "wtf/text/AtomicString.h"
42
43 namespace blink {
44
45 MediaController* MediaController::create(ExecutionContext* context)
46 {
47 return new MediaController(context);
48 }
49
50 MediaController::MediaController(ExecutionContext* context)
51 : m_paused(false)
52 , m_defaultPlaybackRate(1)
53 , m_volume(1)
54 , m_position(std::numeric_limits<double>::quiet_NaN())
55 , m_muted(false)
56 , m_readyState(HTMLMediaElement::HAVE_NOTHING)
57 , m_playbackState(WAITING)
58 , m_pendingEventsQueue(GenericEventQueue::create(this))
59 , m_clearPositionTimer(this, &MediaController::clearPositionTimerFired)
60 , m_clock(Clock::create())
61 , m_executionContext(context)
62 , m_timeupdateTimer(this, &MediaController::timeupdateTimerFired)
63 , m_previousTimeupdateTime(0)
64 {
65 }
66
67 MediaController::~MediaController()
68 {
69 }
70
71 void MediaController::addMediaElement(HTMLMediaElement* element)
72 {
73 ASSERT(element);
74 ASSERT(!m_mediaElements.contains(element));
75
76 m_mediaElements.add(element);
77 bringElementUpToSpeed(element);
78 }
79
80 void MediaController::removeMediaElement(HTMLMediaElement* element)
81 {
82 ASSERT(element);
83 ASSERT(m_mediaElements.contains(element));
84 m_mediaElements.remove(m_mediaElements.find(element));
85 }
86
87 TimeRanges* MediaController::buffered() const
88 {
89 if (m_mediaElements.isEmpty())
90 return TimeRanges::create();
91
92 // The buffered attribute must return a new static normalized TimeRanges obj ect that represents
93 // the intersection of the ranges of the media resources of the slaved media elements that the
94 // user agent has buffered, at the time the attribute is evaluated.
95 MediaElementSequence::const_iterator it = m_mediaElements.begin();
96 TimeRanges* bufferedRanges = (*it)->buffered();
97 for (++it; it != m_mediaElements.end(); ++it)
98 bufferedRanges->intersectWith((*it)->buffered());
99 return bufferedRanges;
100 }
101
102 TimeRanges* MediaController::seekable() const
103 {
104 if (m_mediaElements.isEmpty())
105 return TimeRanges::create();
106
107 // The seekable attribute must return a new static normalized TimeRanges obj ect that represents
108 // the intersection of the ranges of the media resources of the slaved media elements that the
109 // user agent is able to seek to, at the time the attribute is evaluated.
110 MediaElementSequence::const_iterator it = m_mediaElements.begin();
111 TimeRanges* seekableRanges = (*it)->seekable();
112 for (++it; it != m_mediaElements.end(); ++it)
113 seekableRanges->intersectWith((*it)->seekable());
114 return seekableRanges;
115 }
116
117 TimeRanges* MediaController::played()
118 {
119 if (m_mediaElements.isEmpty())
120 return TimeRanges::create();
121
122 // The played attribute must return a new static normalized TimeRanges objec t that represents
123 // the union of the ranges of the media resources of the slaved media elemen ts that the
124 // user agent has so far rendered, at the time the attribute is evaluated.
125 MediaElementSequence::const_iterator it = m_mediaElements.begin();
126 TimeRanges* playedRanges = (*it)->played();
127 for (++it; it != m_mediaElements.end(); ++it)
128 playedRanges->unionWith((*it)->played());
129 return playedRanges;
130 }
131
132 double MediaController::duration() const
133 {
134 // FIXME: Investigate caching the maximum duration and only updating the cac hed value
135 // when the slaved media elements' durations change.
136 double maxDuration = 0;
137 for (const HTMLMediaElement* element : m_mediaElements) {
138 double duration = element->duration();
139 if (std::isnan(duration))
140 continue;
141 maxDuration = std::max(maxDuration, duration);
142 }
143 return maxDuration;
144 }
145
146 double MediaController::currentTime() const
147 {
148 if (m_mediaElements.isEmpty())
149 return 0;
150
151 if (std::isnan(m_position)) {
152 // Some clocks may return times outside the range of [0..duration].
153 m_position = std::max(0.0, std::min(duration(), m_clock->currentTime())) ;
154 m_clearPositionTimer.startOneShot(0, BLINK_FROM_HERE);
155 }
156
157 return m_position;
158 }
159
160 void MediaController::setCurrentTime(double time)
161 {
162 // When the user agent is to seek the media controller to a particular new p layback position,
163 // it must follow these steps:
164 // If the new playback position is less than zero, then set it to zero.
165 time = std::max(0.0, time);
166
167 // If the new playback position is greater than the media controller duratio n, then set it
168 // to the media controller duration.
169 time = std::min(time, duration());
170
171 // Set the media controller position to the new playback position.
172 m_position = time;
173 m_clock->setCurrentTime(time);
174
175 // Seek each slaved media element to the new playback position relative to t he media element timeline.
176 for (HTMLMediaElement* element : m_mediaElements)
177 element->seek(time);
178
179 scheduleTimeupdateEvent();
180 }
181
182 void MediaController::unpause()
183 {
184 // When the unpause() method is invoked, if the MediaController is a paused media controller,
185 if (!m_paused)
186 return;
187
188 // the user agent must change the MediaController into a playing media contr oller,
189 m_paused = false;
190 // queue a task to fire a simple event named play at the MediaController,
191 scheduleEvent(EventTypeNames::play);
192 // and then report the controller state of the MediaController.
193 reportControllerState();
194 }
195
196 void MediaController::play()
197 {
198 // When the play() method is invoked, the user agent must invoke the play me thod of each
199 // slaved media element in turn,
200 for (HTMLMediaElement* element : m_mediaElements)
201 element->play();
202
203 // and then invoke the unpause method of the MediaController.
204 unpause();
205 }
206
207 void MediaController::pause()
208 {
209 // When the pause() method is invoked, if the MediaController is a playing m edia controller,
210 if (m_paused)
211 return;
212
213 // then the user agent must change the MediaController into a paused media c ontroller,
214 m_paused = true;
215 // queue a task to fire a simple event named pause at the MediaController,
216 scheduleEvent(EventTypeNames::pause);
217 // and then report the controller state of the MediaController.
218 reportControllerState();
219 }
220
221 void MediaController::setDefaultPlaybackRate(double rate)
222 {
223 if (m_defaultPlaybackRate == rate)
224 return;
225
226 // The defaultPlaybackRate attribute, on setting, must set the MediaControll er's media controller
227 // default playback rate to the new value,
228 m_defaultPlaybackRate = rate;
229
230 // then queue a task to fire a simple event named ratechange at the MediaCon troller.
231 scheduleEvent(EventTypeNames::ratechange);
232 }
233
234 double MediaController::playbackRate() const
235 {
236 return m_clock->playRate();
237 }
238
239 void MediaController::setPlaybackRate(double rate)
240 {
241 if (m_clock->playRate() == rate)
242 return;
243
244 // The playbackRate attribute, on setting, must set the MediaController's me dia controller
245 // playback rate to the new value,
246 m_clock->setPlayRate(rate);
247
248 for (HTMLMediaElement* element : m_mediaElements)
249 element->updatePlaybackRate();
250
251 // then queue a task to fire a simple event named ratechange at the MediaCon troller.
252 scheduleEvent(EventTypeNames::ratechange);
253 }
254
255 void MediaController::setVolume(double level, ExceptionState& exceptionState)
256 {
257 if (m_volume == level)
258 return;
259
260 // If the new value is outside the range 0.0 to 1.0 inclusive, then, on sett ing, an
261 // IndexSizeError exception must be raised instead.
262 if (level < 0 || level > 1) {
263 exceptionState.throwDOMException(IndexSizeError, ExceptionMessages::inde xOutsideRange("volume", level, 0.0, ExceptionMessages::InclusiveBound, 1.0, Exce ptionMessages::InclusiveBound));
264 return;
265 }
266
267 // The volume attribute, on setting, if the new value is in the range 0.0 to 1.0 inclusive,
268 // must set the MediaController's media controller volume multiplier to the new value
269 m_volume = level;
270
271 // and queue a task to fire a simple event named volumechange at the MediaCo ntroller.
272 scheduleEvent(EventTypeNames::volumechange);
273
274 for (HTMLMediaElement* element : m_mediaElements)
275 element->updateVolume();
276 }
277
278 void MediaController::setMuted(bool flag)
279 {
280 if (m_muted == flag)
281 return;
282
283 // The muted attribute, on setting, must set the MediaController's media con troller mute override
284 // to the new value
285 m_muted = flag;
286
287 // and queue a task to fire a simple event named volumechange at the MediaCo ntroller.
288 scheduleEvent(EventTypeNames::volumechange);
289
290 for (HTMLMediaElement* element : m_mediaElements)
291 element->updateVolume();
292 }
293
294 static const AtomicString& playbackStateWaiting()
295 {
296 DEFINE_STATIC_LOCAL(AtomicString, waiting, ("waiting", AtomicString::Constru ctFromLiteral));
297 return waiting;
298 }
299
300 static const AtomicString& playbackStatePlaying()
301 {
302 DEFINE_STATIC_LOCAL(AtomicString, playing, ("playing", AtomicString::Constru ctFromLiteral));
303 return playing;
304 }
305
306 static const AtomicString& playbackStateEnded()
307 {
308 DEFINE_STATIC_LOCAL(AtomicString, ended, ("ended", AtomicString::ConstructFr omLiteral));
309 return ended;
310 }
311
312 const AtomicString& MediaController::playbackState() const
313 {
314 switch (m_playbackState) {
315 case WAITING:
316 return playbackStateWaiting();
317 case PLAYING:
318 return playbackStatePlaying();
319 case ENDED:
320 return playbackStateEnded();
321 default:
322 ASSERT_NOT_REACHED();
323 return nullAtom;
324 }
325 }
326
327 void MediaController::reportControllerState()
328 {
329 updateReadyState();
330 updatePlaybackState();
331 }
332
333 static const AtomicString& eventNameForReadyState(HTMLMediaElement::ReadyState s tate)
334 {
335 switch (state) {
336 case HTMLMediaElement::HAVE_NOTHING:
337 return EventTypeNames::emptied;
338 case HTMLMediaElement::HAVE_METADATA:
339 return EventTypeNames::loadedmetadata;
340 case HTMLMediaElement::HAVE_CURRENT_DATA:
341 return EventTypeNames::loadeddata;
342 case HTMLMediaElement::HAVE_FUTURE_DATA:
343 return EventTypeNames::canplay;
344 case HTMLMediaElement::HAVE_ENOUGH_DATA:
345 return EventTypeNames::canplaythrough;
346 default:
347 ASSERT_NOT_REACHED();
348 return nullAtom;
349 }
350 }
351
352 void MediaController::updateReadyState()
353 {
354 ReadyState oldReadyState = m_readyState;
355 ReadyState newReadyState;
356
357 if (m_mediaElements.isEmpty()) {
358 // If the MediaController has no slaved media elements, let new readines s state be 0.
359 newReadyState = HTMLMediaElement::HAVE_NOTHING;
360 } else {
361 // Otherwise, let it have the lowest value of the readyState IDL attribu tes of all of its
362 // slaved media elements.
363 MediaElementSequence::const_iterator it = m_mediaElements.begin();
364 newReadyState = (*it)->readyState();
365 for (++it; it != m_mediaElements.end(); ++it)
366 newReadyState = std::min(newReadyState, (*it)->readyState());
367 }
368
369 if (newReadyState == oldReadyState)
370 return;
371
372 // If the MediaController's most recently reported readiness state is greate r than new readiness
373 // state then queue a task to fire a simple event at the MediaController obj ect, whose name is the
374 // event name corresponding to the value of new readiness state given in the table below. [omitted]
375 if (oldReadyState > newReadyState) {
376 scheduleEvent(eventNameForReadyState(newReadyState));
377 return;
378 }
379
380 // If the MediaController's most recently reported readiness state is less t han the new readiness
381 // state, then run these substeps:
382 // 1. Let next state be the MediaController's most recently reported readine ss state.
383 ReadyState nextState = oldReadyState;
384 do {
385 // 2. Loop: Increment next state by one.
386 nextState = static_cast<ReadyState>(nextState + 1);
387 // 3. Queue a task to fire a simple event at the MediaController object, whose name is the
388 // event name corresponding to the value of next state given in the tabl e below. [omitted]
389 scheduleEvent(eventNameForReadyState(nextState));
390 // If next state is less than new readiness state, then return to the st ep labeled loop
391 } while (nextState < newReadyState);
392
393 // Let the MediaController's most recently reported readiness state be new r eadiness state.
394 m_readyState = newReadyState;
395 }
396
397 void MediaController::updatePlaybackState()
398 {
399 PlaybackState oldPlaybackState = m_playbackState;
400 PlaybackState newPlaybackState;
401
402 // Initialize new playback state by setting it to the state given for the fi rst matching
403 // condition from the following list:
404 if (m_mediaElements.isEmpty()) {
405 // If the MediaController has no slaved media elements
406 // Let new playback state be waiting.
407 newPlaybackState = WAITING;
408 } else if (hasEnded()) {
409 // If all of the MediaController's slaved media elements have ended play back and the media
410 // controller playback rate is positive or zero
411 // Let new playback state be ended.
412 newPlaybackState = ENDED;
413 } else if (isBlocked()) {
414 // If the MediaController is a blocked media controller
415 // Let new playback state be waiting.
416 newPlaybackState = WAITING;
417 } else {
418 // Otherwise
419 // Let new playback state be playing.
420 newPlaybackState = PLAYING;
421 }
422
423 // If the MediaController's most recently reported playback state is not equ al to new playback state
424 if (newPlaybackState == oldPlaybackState)
425 return;
426
427 // and the new playback state is ended,
428 if (newPlaybackState == ENDED) {
429 // then queue a task that, if the MediaController object is a playing me dia controller, and
430 // all of the MediaController's slaved media elements have still ended p layback, and the
431 // media controller playback rate is still positive or zero,
432 if (!m_paused && hasEnded()) {
433 // changes the MediaController object to a paused media controller
434 m_paused = true;
435
436 // and then fires a simple event named pause at the MediaController object.
437 scheduleEvent(EventTypeNames::pause);
438 }
439 }
440
441 // If the MediaController's most recently reported playback state is not equ al to new playback state
442 // then queue a task to fire a simple event at the MediaController object, w hose name is playing
443 // if new playback state is playing, ended if new playback state is ended, a nd waiting otherwise.
444 AtomicString eventName;
445 switch (newPlaybackState) {
446 case WAITING:
447 eventName = EventTypeNames::waiting;
448 m_clock->stop();
449 m_timeupdateTimer.stop();
450 break;
451 case ENDED:
452 eventName = EventTypeNames::ended;
453 m_clock->stop();
454 m_timeupdateTimer.stop();
455 break;
456 case PLAYING:
457 eventName = EventTypeNames::playing;
458 m_clock->start();
459 startTimeupdateTimer();
460 break;
461 default:
462 ASSERT_NOT_REACHED();
463 }
464 scheduleEvent(eventName);
465
466 // Let the MediaController's most recently reported playback state be new pl ayback state.
467 m_playbackState = newPlaybackState;
468
469 updateMediaElements();
470 }
471
472 void MediaController::updateMediaElements()
473 {
474 for (HTMLMediaElement* element : m_mediaElements)
475 element->updatePlayState();
476 }
477
478 void MediaController::bringElementUpToSpeed(HTMLMediaElement* element)
479 {
480 ASSERT(element);
481 ASSERT(m_mediaElements.contains(element));
482
483 // When the user agent is to bring a media element up to speed with its new media controller,
484 // it must seek that media element to the MediaController's media controller position relative
485 // to the media element's timeline.
486 element->seek(currentTime());
487
488 // Update volume to take controller volume and mute into account.
489 element->updateVolume();
490 }
491
492 bool MediaController::isRestrained() const
493 {
494 ASSERT(!m_mediaElements.isEmpty());
495
496 // A MediaController is a restrained media controller if the MediaController is a playing media
497 // controller,
498 if (m_paused)
499 return false;
500
501 bool anyAutoplayingAndPaused = false;
502 bool allPaused = true;
503 for (const HTMLMediaElement* element : m_mediaElements) {
504 if (element->isAutoplaying() && element->paused())
505 anyAutoplayingAndPaused = true;
506
507 if (!element->paused())
508 allPaused = false;
509 }
510
511 // but either at least one of its slaved media elements whose autoplaying fl ag is true still has
512 // its paused attribute set to true, or, all of its slaved media elements ha ve their paused
513 // attribute set to true.
514 return anyAutoplayingAndPaused || allPaused;
515 }
516
517 bool MediaController::isBlocked() const
518 {
519 ASSERT(!m_mediaElements.isEmpty());
520
521 // A MediaController is a blocked media controller if the MediaController is a paused media
522 // controller,
523 if (m_paused)
524 return true;
525
526 bool allPaused = true;
527 for (const HTMLMediaElement* element : m_mediaElements) {
528 // or if any of its slaved media elements are blocked media elements,
529 if (element->isBlocked())
530 return true;
531
532 // or if any of its slaved media elements whose autoplaying flag is true still have their
533 // paused attribute set to true,
534 if (element->isAutoplaying() && element->paused())
535 return true;
536
537 if (!element->paused())
538 allPaused = false;
539 }
540
541 // or if all of its slaved media elements have their paused attribute set to true.
542 return allPaused;
543 }
544
545 bool MediaController::hasEnded() const
546 {
547 // If the ... media controller playback rate is positive or zero
548 if (m_clock->playRate() < 0)
549 return false;
550
551 // [and] all of the MediaController's slaved media elements have ended playb ack ... let new
552 // playback state be ended.
553 if (m_mediaElements.isEmpty())
554 return false;
555
556 bool allHaveEnded = true;
557 for (const HTMLMediaElement* element : m_mediaElements) {
558 if (!element->ended())
559 allHaveEnded = false;
560 }
561 return allHaveEnded;
562 }
563
564 void MediaController::scheduleEvent(const AtomicString& eventName)
565 {
566 m_pendingEventsQueue->enqueueEvent(Event::createCancelable(eventName));
567 }
568
569 void MediaController::clearPositionTimerFired(Timer<MediaController>*)
570 {
571 m_position = std::numeric_limits<double>::quiet_NaN();
572 }
573
574 const AtomicString& MediaController::interfaceName() const
575 {
576 return EventTargetNames::MediaController;
577 }
578
579 // The spec says to fire periodic timeupdate events (those sent while playing) e very
580 // "15 to 250ms", we choose the slowest frequency
581 static const double maxTimeupdateEventFrequency = 0.25;
582
583 void MediaController::startTimeupdateTimer()
584 {
585 if (m_timeupdateTimer.isActive())
586 return;
587
588 m_timeupdateTimer.startRepeating(maxTimeupdateEventFrequency, BLINK_FROM_HER E);
589 }
590
591 void MediaController::timeupdateTimerFired(Timer<MediaController>*)
592 {
593 scheduleTimeupdateEvent();
594 }
595
596 void MediaController::scheduleTimeupdateEvent()
597 {
598 double now = WTF::currentTime();
599 double timedelta = now - m_previousTimeupdateTime;
600
601 if (timedelta < maxTimeupdateEventFrequency)
602 return;
603
604 scheduleEvent(EventTypeNames::timeupdate);
605 m_previousTimeupdateTime = now;
606 }
607
608 DEFINE_TRACE(MediaController)
609 {
610 #if ENABLE(OILPAN)
611 visitor->trace(m_mediaElements);
612 visitor->trace(m_pendingEventsQueue);
613 visitor->trace(m_executionContext);
614 #endif
615 RefCountedGarbageCollectedEventTargetWithInlineData<MediaController>::trace( visitor);
616 }
617
618 }
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/html/MediaController.h ('k') | third_party/WebKit/Source/core/html/MediaController.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698