diff options
| author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
|---|---|---|
| committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
| commit | 32761a6cee1d0dee366b885b7b9c777e67885688 (patch) | |
| tree | d6bec92bebfb216f4126356e55518842c2f476a1 /Source/WebCore/Modules/mediacontrols | |
| parent | a4e969f4965059196ca948db781e52f7cfebf19e (diff) | |
| download | WebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz | |
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/WebCore/Modules/mediacontrols')
11 files changed, 0 insertions, 7606 deletions
diff --git a/Source/WebCore/Modules/mediacontrols/MediaControlsHost.cpp b/Source/WebCore/Modules/mediacontrols/MediaControlsHost.cpp deleted file mode 100644 index cc7ca9d59..000000000 --- a/Source/WebCore/Modules/mediacontrols/MediaControlsHost.cpp +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(MEDIA_CONTROLS_SCRIPT) - -#include "MediaControlsHost.h" - -#include "CaptionUserPreferences.h" -#include "Element.h" -#include "HTMLMediaElement.h" -#include "Logging.h" -#include "MediaControlElements.h" -#include "Page.h" -#include "PageGroup.h" -#include "TextTrack.h" -#include "TextTrackList.h" -#include "UUID.h" -#include <runtime/JSCJSValueInlines.h> - -namespace WebCore { - -const AtomicString& MediaControlsHost::automaticKeyword() -{ - static NeverDestroyed<const AtomicString> automatic("automatic", AtomicString::ConstructFromLiteral); - return automatic; -} - -const AtomicString& MediaControlsHost::forcedOnlyKeyword() -{ - static NeverDestroyed<const AtomicString> forcedOn("forced-only", AtomicString::ConstructFromLiteral); - return forcedOn; -} - -const AtomicString& MediaControlsHost::alwaysOnKeyword() -{ - static NeverDestroyed<const AtomicString> alwaysOn("always-on", AtomicString::ConstructFromLiteral); - return alwaysOn; -} - -const AtomicString& MediaControlsHost::manualKeyword() -{ - static NeverDestroyed<const AtomicString> alwaysOn("manual", AtomicString::ConstructFromLiteral); - return alwaysOn; -} - - -Ref<MediaControlsHost> MediaControlsHost::create(HTMLMediaElement* mediaElement) -{ - return adoptRef(*new MediaControlsHost(mediaElement)); -} - -MediaControlsHost::MediaControlsHost(HTMLMediaElement* mediaElement) - : m_mediaElement(mediaElement) -{ - ASSERT(mediaElement); -} - -MediaControlsHost::~MediaControlsHost() -{ -} - -Vector<RefPtr<TextTrack>> MediaControlsHost::sortedTrackListForMenu(TextTrackList* trackList) -{ - if (!trackList) - return Vector<RefPtr<TextTrack>>(); - - Page* page = m_mediaElement->document().page(); - if (!page) - return Vector<RefPtr<TextTrack>>(); - - return page->group().captionPreferences().sortedTrackListForMenu(trackList); -} - -Vector<RefPtr<AudioTrack>> MediaControlsHost::sortedTrackListForMenu(AudioTrackList* trackList) -{ - if (!trackList) - return Vector<RefPtr<AudioTrack>>(); - - Page* page = m_mediaElement->document().page(); - if (!page) - return Vector<RefPtr<AudioTrack>>(); - - return page->group().captionPreferences().sortedTrackListForMenu(trackList); -} - -String MediaControlsHost::displayNameForTrack(TextTrack* track) -{ - if (!track) - return emptyString(); - - Page* page = m_mediaElement->document().page(); - if (!page) - return emptyString(); - - return page->group().captionPreferences().displayNameForTrack(track); -} - -String MediaControlsHost::displayNameForTrack(AudioTrack* track) -{ - if (!track) - return emptyString(); - - Page* page = m_mediaElement->document().page(); - if (!page) - return emptyString(); - - return page->group().captionPreferences().displayNameForTrack(track); -} - -TextTrack* MediaControlsHost::captionMenuOffItem() -{ - return TextTrack::captionMenuOffItem(); -} - -TextTrack* MediaControlsHost::captionMenuAutomaticItem() -{ - return TextTrack::captionMenuAutomaticItem(); -} - -AtomicString MediaControlsHost::captionDisplayMode() -{ - Page* page = m_mediaElement->document().page(); - if (!page) - return emptyAtom; - - switch (page->group().captionPreferences().captionDisplayMode()) { - case CaptionUserPreferences::Automatic: - return automaticKeyword(); - case CaptionUserPreferences::ForcedOnly: - return forcedOnlyKeyword(); - case CaptionUserPreferences::AlwaysOn: - return alwaysOnKeyword(); - case CaptionUserPreferences::Manual: - return manualKeyword(); - default: - ASSERT_NOT_REACHED(); - return emptyAtom; - } -} - -void MediaControlsHost::setSelectedTextTrack(TextTrack* track) -{ - m_mediaElement->setSelectedTextTrack(track); -} - -Element* MediaControlsHost::textTrackContainer() -{ - if (!m_textTrackContainer) { - m_textTrackContainer = MediaControlTextTrackContainerElement::create(m_mediaElement->document()); - m_textTrackContainer->setMediaController(m_mediaElement); - } - return m_textTrackContainer.get(); -} - -void MediaControlsHost::updateTextTrackContainer() -{ - if (m_textTrackContainer) - m_textTrackContainer->updateDisplay(); -} - -void MediaControlsHost::enteredFullscreen() -{ - if (m_textTrackContainer) - m_textTrackContainer->enteredFullscreen(); -} - -void MediaControlsHost::exitedFullscreen() -{ - if (m_textTrackContainer) - m_textTrackContainer->exitedFullscreen(); -} - -void MediaControlsHost::updateCaptionDisplaySizes() -{ - if (m_textTrackContainer) - m_textTrackContainer->updateSizes(true); -} - -bool MediaControlsHost::allowsInlineMediaPlayback() const -{ - return !m_mediaElement->mediaSession().requiresFullscreenForVideoPlayback(*m_mediaElement); -} - -bool MediaControlsHost::supportsFullscreen() -{ - return m_mediaElement->supportsFullscreen(HTMLMediaElementEnums::VideoFullscreenModeStandard); -} - -bool MediaControlsHost::userGestureRequired() const -{ - return !m_mediaElement->mediaSession().playbackPermitted(*m_mediaElement); -} - -String MediaControlsHost::externalDeviceDisplayName() const -{ -#if ENABLE(WIRELESS_PLAYBACK_TARGET) - MediaPlayer* player = m_mediaElement->player(); - if (!player) { - LOG(Media, "MediaControlsHost::externalDeviceDisplayName - returning \"\" because player is NULL"); - return emptyString(); - } - - String name = player->wirelessPlaybackTargetName(); - LOG(Media, "MediaControlsHost::externalDeviceDisplayName - returning \"%s\"", name.utf8().data()); - - return name; -#else - return emptyString(); -#endif -} - -String MediaControlsHost::externalDeviceType() const -{ - static NeverDestroyed<String> none(ASCIILiteral("none")); - String type = none; - -#if ENABLE(WIRELESS_PLAYBACK_TARGET) - static NeverDestroyed<String> airplay(ASCIILiteral("airplay")); - static NeverDestroyed<String> tvout(ASCIILiteral("tvout")); - - MediaPlayer* player = m_mediaElement->player(); - if (!player) { - LOG(Media, "MediaControlsHost::externalDeviceType - returning \"none\" because player is NULL"); - return none; - } - - switch (player->wirelessPlaybackTargetType()) { - case MediaPlayer::TargetTypeNone: - type = none; - break; - case MediaPlayer::TargetTypeAirPlay: - type = airplay; - break; - case MediaPlayer::TargetTypeTVOut: - type = tvout; - break; - } -#endif - - LOG(Media, "MediaControlsHost::externalDeviceType - returning \"%s\"", type.utf8().data()); - - return type; -} - -bool MediaControlsHost::controlsDependOnPageScaleFactor() const -{ - return m_mediaElement->mediaControlsDependOnPageScaleFactor(); -} - -void MediaControlsHost::setControlsDependOnPageScaleFactor(bool value) -{ - m_mediaElement->setMediaControlsDependOnPageScaleFactor(value); -} - -String MediaControlsHost::generateUUID() const -{ - return createCanonicalUUIDString(); -} - -} - -#endif diff --git a/Source/WebCore/Modules/mediacontrols/MediaControlsHost.h b/Source/WebCore/Modules/mediacontrols/MediaControlsHost.h deleted file mode 100644 index 1957713ae..000000000 --- a/Source/WebCore/Modules/mediacontrols/MediaControlsHost.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef MediaControlsHost_h -#define MediaControlsHost_h - -#if ENABLE(MEDIA_CONTROLS_SCRIPT) - -#include "ScriptState.h" -#include <bindings/ScriptObject.h> -#include <wtf/RefCounted.h> -#include <wtf/Vector.h> -#include <wtf/text/WTFString.h> - -namespace WebCore { - -class AudioTrack; -class AudioTrackList; -class Element; -class HTMLMediaElement; -class MediaControlTextTrackContainerElement; -class TextTrack; -class TextTrackList; - -class MediaControlsHost : public RefCounted<MediaControlsHost> { -public: - static Ref<MediaControlsHost> create(HTMLMediaElement*); - ~MediaControlsHost(); - - static const AtomicString& automaticKeyword(); - static const AtomicString& forcedOnlyKeyword(); - static const AtomicString& alwaysOnKeyword(); - static const AtomicString& manualKeyword(); - - Vector<RefPtr<TextTrack>> sortedTrackListForMenu(TextTrackList*); - Vector<RefPtr<AudioTrack>> sortedTrackListForMenu(AudioTrackList*); - String displayNameForTrack(TextTrack*); - String displayNameForTrack(AudioTrack*); - TextTrack* captionMenuOffItem(); - TextTrack* captionMenuAutomaticItem(); - AtomicString captionDisplayMode(); - void setSelectedTextTrack(TextTrack*); - Element* textTrackContainer(); - void updateTextTrackContainer(); - bool allowsInlineMediaPlayback() const; - bool supportsFullscreen(); - bool userGestureRequired() const; - - void updateCaptionDisplaySizes(); - void enteredFullscreen(); - void exitedFullscreen(); - - String externalDeviceDisplayName() const; - String externalDeviceType() const; - - bool controlsDependOnPageScaleFactor() const; - void setControlsDependOnPageScaleFactor(bool v); - - String generateUUID() const; - -private: - MediaControlsHost(HTMLMediaElement*); - - HTMLMediaElement* m_mediaElement; - RefPtr<MediaControlTextTrackContainerElement> m_textTrackContainer; -}; - -} - -#endif - -#endif diff --git a/Source/WebCore/Modules/mediacontrols/MediaControlsHost.idl b/Source/WebCore/Modules/mediacontrols/MediaControlsHost.idl deleted file mode 100644 index 4b164a718..000000000 --- a/Source/WebCore/Modules/mediacontrols/MediaControlsHost.idl +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -enum DeviceType { - "none", - "airplay", - "tvout" -}; - -[ - NoInterfaceObject, - Conditional=MEDIA_CONTROLS_SCRIPT, - ImplementationLacksVTable, -] interface MediaControlsHost { - TextTrack[] sortedTrackListForMenu(TextTrackList trackList); - AudioTrack[] sortedTrackListForMenu(AudioTrackList trackList); - DOMString displayNameForTrack(TextTrack track); - DOMString displayNameForTrack(AudioTrack track); - readonly attribute TextTrack captionMenuOffItem; - readonly attribute TextTrack captionMenuAutomaticItem; - readonly attribute DOMString captionDisplayMode; - void setSelectedTextTrack(TextTrack track); - readonly attribute HTMLElement textTrackContainer; - readonly attribute boolean allowsInlineMediaPlayback; - readonly attribute boolean supportsFullscreen; - readonly attribute boolean userGestureRequired; - - readonly attribute DOMString externalDeviceDisplayName; - readonly attribute DeviceType externalDeviceType; - - attribute boolean controlsDependOnPageScaleFactor; - - void updateTextTrackContainer(); - void enteredFullscreen(); - void exitedFullscreen(); - - DOMString generateUUID(); -}; diff --git a/Source/WebCore/Modules/mediacontrols/assets-apple-iOS.svg b/Source/WebCore/Modules/mediacontrols/assets-apple-iOS.svg deleted file mode 100644 index db2a2d334..000000000 --- a/Source/WebCore/Modules/mediacontrols/assets-apple-iOS.svg +++ /dev/null @@ -1,52 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 190 44"> - - <!-- - NOTE: THIS FILE IS NOT PART OF THE BUILD PROCESS. EDITS - HERE ARE NOT AUTOMATICALLY COPIED TO THE CSS FILES. - - This file holds the raw assets used in mediaControlsApple.css. - This is not part of the build process at the moment, but manually - copied into the CSS. However, editing from CSS is a burden, so - the idea is that you develop here and then paste into CSS. - --> - - <!-- PLAY --> - - <g transform="translate(0 0)"> - <rect width="44" height="44" fill="rgb(255, 255, 200)"/> - <svg width="44" height="44"> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 44 44"> - <path fill="rgba(0, 0, 0, 0.8)" d="M10,11 32,22 10,33z"/> - </svg> - </svg> - </g> - - <!-- PAUSE --> - - <g transform="translate(46 0)"> - <rect width="44" height="44" fill="rgb(255, 255, 200)"/> - <svg width="44" height="44"> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 44 44"> - <g fill="rgba(0, 0, 0, 0.8)"> - <rect x="13" y="11" width="6" height="22"/> - <rect x="24" y="11" width="6" height="22"/> - </g> - </svg> - </svg> - </g> - - <!-- FULLSCREEN --> - - <g transform="translate(92 0)"> - <rect width="44" height="44" fill="rgb(255, 255, 200)"/> - <svg width="44" height="44"> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 44 44"> - <g stroke="rgba(0, 0, 0, 0.8)" fill="none"> - <path d="M 14,20 v -6 h 6 M 14,14 l 6,6"/> - <path d="M 30,24 v 6 h -6 M 30,30 l -6,-6"/> - </g> - </svg> - </svg> - </g> - -</svg>
\ No newline at end of file diff --git a/Source/WebCore/Modules/mediacontrols/mediaControlsApple.css b/Source/WebCore/Modules/mediacontrols/mediaControlsApple.css deleted file mode 100644 index d8eb78652..000000000 --- a/Source/WebCore/Modules/mediacontrols/mediaControlsApple.css +++ /dev/null @@ -1,1123 +0,0 @@ -/* - * Copyright (C) 2013, 2014, 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -audio { - width: 200px; - height: 25px; -} - -body:-webkit-full-page-media { - background-color: rgb(38, 38, 38); -} - -video:-webkit-full-page-media { - margin: auto; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; -} - -video:-webkit-full-page-media::-webkit-media-controls-panel { - bottom: 0px; -} - -video:-webkit-full-page-media::-webkit-media-controls-panel.no-video { - opacity: 1; -} - -::-webkit-media-controls { - width: inherit; - height: inherit; - position: relative; - display: -webkit-flex !important; - -webkit-align-items: stretch; - -webkit-justify-content: flex-end; - -webkit-flex-direction: column; - font: -webkit-small-control; - white-space: nowrap; - -webkit-font-smoothing: subpixel-antialiased; -} - -video::-webkit-media-text-track-container, -audio::-webkit-media-text-track-container { - position: relative; - -webkit-flex: 1 1 auto; -} - -video::-webkit-media-controls-panel, -audio::-webkit-media-controls-panel { - box-sizing: border-box; - position: relative; - bottom: 0; - width: 100%; - min-height: 25px; - height: 25px; - line-height: 25px; - -webkit-user-select: none; - -webkit-user-drag: element; - background-color: transparent; - - display: -webkit-flex; - -webkit-flex-direction: row; - -webkit-align-items: center; - -webkit-user-select: none; - - direction: ltr; - - transition: opacity 0.25s linear; - - -webkit-text-zoom: reset -} - -video::-webkit-media-controls-panel { - opacity: 0; - padding-top: 20px; - min-height: 45px; - height: 45px; -} - -video::-webkit-media-controls-panel.show, -video::-webkit-media-controls-panel.paused, -video::-webkit-media-controls-panel:hover { - cursor: inherit; - opacity: 1; -} - -video::-webkit-media-controls-panel.picture-in-picture { - pointer-events: none; -} - -audio::-webkit-media-show-controls { - display: none !important; -} -video::-webkit-media-show-controls { - position: absolute; - left: 0; - bottom: 0; - display: block; - margin: 0; - padding: 0; - width: 100%; - height: 10px; - opacity: 0; - border: 0; - background: none; - -webkit-appearance: none; -} - -video::-webkit-media-controls-panel-background-container, -audio::-webkit-media-controls-panel-background-container { - position: absolute; - left: 0; - top: 0; - width: 100%; -} - -video::-webkit-media-controls-panel-background-container { - z-index: 0; -} - -video::-webkit-media-controls-panel-background-container { - min-height: 45px; - height: 45px; - -webkit-clip-path: inset(20px 0px 0px 0px); -} - -video::-webkit-media-controls-panel-tint, -audio::-webkit-media-controls-panel-tint { - position: absolute; - left: 0; - top: 0; - width: 100%; - background-color: transparent; -} - -video::-webkit-media-controls-panel-tint { - min-height: 45px; - height: 45px; - background-color: rgb(41, 41, 41); - mix-blend-mode: lighten; -} - -video::-webkit-media-controls-panel-background, -audio::-webkit-media-controls-panel-background { - position: absolute; - left: 0; - top: 0; - width: 100%; - min-height: 25px; - height: 25px; - background-color: rgb(41, 41, 41); -} - -video::-webkit-media-controls-panel-background { - min-height: 45px; - height: 45px; - background-color: rgba(30, 30, 30, 0.45); - -webkit-backdrop-filter: saturate(180%) blur(20px); -} - -video::-webkit-media-controls-panel button, -audio::-webkit-media-controls-panel button { - -webkit-appearance: none; - display: block; - padding: 0; - border: 0; - height: 15px; - background-color: transparent; - color: white; - background-origin: content-box; - background-repeat: no-repeat; - background-position: center; -} - -audio::-webkit-media-controls-panel button { - z-index: 0; -} - -video::-webkit-media-controls-panel button { - mix-blend-mode: plus-lighter; - -webkit-transform: translateZ(0); -} - -video::-webkit-media-controls-panel button:focus, -audio::-webkit-media-controls-panel button:focus { - outline: 0; -} - -video::-webkit-media-controls-rewind-button, -audio::-webkit-media-controls-rewind-button { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 17" fill="rgba(255,255,255,0.45)"><path d="m 7.9131,2 0,-1.548 -2.586,2.155 0,-2.171 -2.582,2.208 2.582,2.175 0,-2.139 2.586,2.155 0,-1.276 c 3.138,0.129 5.491,2.681 5.543,5.838 l -1.031,0 0.016,0.215 1.015,0 c -0.06,3.19 -2.629,5.765 -5.819,5.833 l 0,-1.018 -0.214,0 0,1.021 c -3.21,-0.047 -5.801,-2.631 -5.862,-5.836 l 1.045,0 -0.016,-0.215 -1.045,0 c -0.052,-0.288 -0.318,-0.654 -0.766,-0.654 -0.538,0 -0.755,0.484 -0.755,0.75 0,4.146 3.331,7.506 7.476,7.506 4.146,0 7.506,-3.36 7.506,-7.506 0,-4.059 -3.066,-7.357 -7.093,-7.493"/><path d="m 5.1729,11.0518 c -0.38,0 -0.668,-0.129 -0.945,-0.366 -0.083,-0.071 -0.186,-0.134 -0.338,-0.134 -0.277,0 -0.511,0.238 -0.511,0.521 0,0.154 0.083,0.301 0.179,0.383 0.394,0.346 0.911,0.563 1.601,0.563 1.077,0 1.739,-0.451 1.739,-1.608 l 0,-0.013 c 0,-0.911 -0.641,-1.265 -1.296,-1.376 l 0.945,-0.919 c 0.193,-0.19 0.317,-0.337 0.317,-0.604 0,-0.294 -0.228,-0.477 -0.538,-0.477 l -2.354,0 c -0.248,0 -0.455,0.21 -0.455,0.464 0,0.253 0.207,0.463 0.455,0.463 l 1.485,0 -0.939,0.961 c -0.166,0.169 -0.228,0.295 -0.228,0.444 0,0.25 0.207,0.463 0.455,0.463 l 0.166,0 c 0.594,0 0.945,0.222 0.945,0.624 l 0,0.012 c 0,0.367 -0.282,0.599 -0.453,0.599"/><path d="m 10.354,9.5342 c 0,0.876 -0.379,1.525 -0.979,1.525 -0.599,0 -0.992,-0.655 -0.992,-1.539 l 0,-0.012 c 0,-0.884 0.388,-1.527 0.979,-1.527 0.592,0 0.992,0.663 0.992,1.539 l 0,0.014 z m -0.979,-2.512 c -1.197,0 -2.008,1.097 -2.008,2.498 l 0,0.014 c 0,1.401 0.792,2.484 1.995,2.484 1.205,0 2.01,-1.097 2.01,-2.498 l 0,-0.012 c 0,-1.402 -0.805,-2.486 -1.997,-2.486"/></svg>'); - width: 16px; - min-width: 16px; - height: 18px; - margin-bottom: 1px; - margin-left: 8px; - margin-right: 8px; -} - -video::-webkit-media-controls-play-button, -audio::-webkit-media-controls-play-button { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 15" fill="rgba(255,255,255,0.45)"><rect x="0" y="1" width="4" height="13"/><rect x="8" y="1" width="4" height="13"/></svg>'); - margin-left: 8px; - margin-right: 8px; - width: 12px; - min-width: 12px; -} - -video::-webkit-media-controls-play-button.paused, -audio::-webkit-media-controls-play-button.paused { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 15" fill="rgba(255,255,255,0.45)"><path d="M 0,1 12,7.5 0,14 z"/></svg>'); - width: 12px; -} - -video::-webkit-media-controls-panel .mute-box, -audio::-webkit-media-controls-panel .mute-box { - width: 14px; - min-width: 14px; - height: 25px; - margin-right: 8px; - margin-left: 8px; - position: relative; - display: -webkit-flex; - -webkit-flex-direction: column; - -webkit-justify-content: center; - -webkit-align-items: center; -} - -video::-webkit-media-controls-mute-button, -audio::-webkit-media-controls-mute-button, -video::-webkit-media-controls-volume-max-button { - width: 14px; - min-width: 14px; - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 15" stroke="rgba(255,255,255,0.45)" fill="none" stroke-width="1.25" stroke-linecap="round"><defs><clipPath id="cut-hole"><rect x="3" y="0" width="3.5" height="15"/></clipPath></defs><path stroke="none" fill="rgba(255,255,255,0.45)" shape-rendering="crispEdges" d="M 0,10 0,6 3,6 3,10 z"/><path stroke="none" fill="rgba(255,255,255,0.45)" clip-path="url(#cut-hole)" shape-rendering="crispEdges" d="M 3.5,6 6.5,3 6.5,13 3.5,10 z"/><path d="M 9,5.5 C 10.75,7 10.75,9 9,10.5"/><path d="M 10,3.5 C 13,4.5 13,11.5 10,12.5" /><path d="M 11,1.5 C 15.67,3.5 15.67,12.5 11,14.5"/></svg>'); -} - -video::-webkit-media-controls-panel .volume-box, -audio::-webkit-media-controls-panel .volume-box { - position: absolute; - box-sizing: border-box; - width: 63px; - bottom: 5px; - left: -25px; - - -webkit-clip-path: inset(20px 20px 20px 20px round 4px 4px 0px 0px); - background-color: transparent; - overflow: hidden; - - display: -webkit-flex; - -webkit-flex-direction: row; - -webkit-align-items: center; - -webkit-justify-content: flex-end; - - opacity: 0; - /* make zero height (rather than display:none) for AX and FKA */ - height: 0px; /* will become 116px when shown */ - -} - -audio::-webkit-media-controls-panel .volume-box { - background-color: black; -} - -video::-webkit-media-controls-volume-slider-container-background, -audio::-webkit-media-controls-volume-slider-container-background { - position: absolute; - left: 0; - top: 0; - width: 100%; - height: 100%; - border-bottom-right-radius: 4px; - border-top-right-radius: 4px; - background-color: rgba(30, 30, 30, 0.45); -} - -video::-webkit-media-controls-volume-slider-container-background { - background-color: rgba(30, 30, 30, 0.45); - -webkit-backdrop-filter: saturate(180%) blur(20px); -} - -video::-webkit-media-controls-volume-slider-container-tint, -audio::-webkit-media-controls-volume-slider-container-tint { - position: absolute; - left: 0; - top: 0; - height: 100%; - width: 100%; - border-bottom-right-radius: 4px; - border-top-right-radius: 4px; - background-color: rgb(41, 41, 41); -} - -video::-webkit-media-controls-volume-slider-container-tint { - mix-blend-mode: lighten; -} - -/* FIXME: needs CSS4 !subject selector to show when slider inside .volume-box is focused */ -video::-webkit-media-controls-panel .mute-box:hover .volume-box, -video::-webkit-media-controls-panel .volume-box:hover, -video::-webkit-media-controls-panel .volume-box:active, -audio::-webkit-media-controls-panel .mute-box:hover .volume-box, -audio::-webkit-media-controls-panel .volume-box:hover, -audio::-webkit-media-controls-panel .volume-box:active { - opacity: 1; - /* resize to usable amount (rather than display:none) for AX and FKA */ - height: 116px; -} - -audio::-webkit-media-controls-volume-slider, -video::-webkit-media-controls-volume-slider { - -webkit-appearance: none !important; - box-sizing: border-box !important; - height: 9px !important; - min-width: 64px !important; - width: 64px !important; - padding: 0 !important; - margin: 0 !important; - - background-color: transparent !important; - background-size: 100% 100%; - background-repeat: no-repeat; - -webkit-transform-origin: 0 0; - -webkit-transform: rotate(-90deg) translateY(28px) translateX(-40px); -} - -video::-webkit-media-controls-volume-slider { - mix-blend-mode: plus-lighter; -} - -video::-webkit-media-controls-volume-slider::-webkit-slider-thumb, -audio::-webkit-media-controls-volume-slider::-webkit-slider-thumb { - -webkit-appearance: none !important; - width: 7px !important; - height: 7px !important; - visibility: hidden; -} - -video::-webkit-media-controls-mute-button.muted, -audio::-webkit-media-controls-mute-button.muted, -video::-webkit-media-controls-volume-min-button { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 15" stroke="rgba(255,255,255,0.45)" fill="none" stroke-width="1.25" stroke-linecap="round"><defs><clipPath id="cut-hole"><rect x="3" y="0" width="3.5" height="15"/></clipPath></defs><path stroke="none" fill="rgba(255,255,255,0.45)" shape-rendering="crispEdges" d="M 0,10 0,6 3,6 3,10 z"/><path stroke="none" fill="rgba(255,255,255,0.45)" clip-path="url(#cut-hole)" shape-rendering="crispEdges" d="M 3.5,6 6.5,3 6.5,13 3.5,10 z"/></svg>'); -} - -video::-webkit-media-controls-wireless-playback-picker-button, -audio::-webkit-media-controls-wireless-playback-picker-button { - margin-right: 8px; - margin-left: 8px; - width: 16px; - min-width: 16px; -} - -video::-webkit-media-controls-wireless-playback-picker-button.playing, -audio::-webkit-media-controls-wireless-playback-picker-button.playing { - mix-blend-mode: normal; -} - -video::-webkit-media-controls-toggle-closed-captions-button, -audio::-webkit-media-controls-toggle-closed-captions-button { - width: 16px; - min-width: 16px; - margin-right: 8px; - margin-left: 8px; - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 15" stroke="rgba(255,255,255,0.45)" fill="none"><defs> <clipPath id="cut-hole"><rect x="0" y="1" width="16" height="10"/><rect x="0" y="11" width="9" height="1"/><rect x="11" y="11" width="5" height="1"/></clipPath></defs> <rect x="0.5" y="1.5" rx="1" ry="1" width="15" height="10" clip-path="url(#cut-hole)"/><path d="M 2,6.5 h 4"/><path d="M 7,6.5 h 7"/><path d="M 3,8.5 h 2"/><path d="M 6,8.5 h 3"/><path d="M 10,8.5 h 3"/><path d="M 8.5,11.5 L 8.5,13.75 L 11,11"/></svg>'); - outline: 0; -} - -video::-webkit-media-controls-closed-captions-container, -audio::-webkit-media-controls-closed-captions-container { - -webkit-appearance: media-closed-captions-container; - position: absolute; - display: block; - right: 38px; - bottom: 29px; - max-width: calc(100% - 48px); /* right + 10px */ - max-height: calc(100% - 39px); /* bottom + 10px */ - overflow-x: hidden; - overflow-y: scroll; - background-color: rgba(0, 0, 0, 0.8); - border: 1px solid rgba(128, 128, 128, 0.75); - border-radius: 6px; - cursor: default; - z-index: 2; - text-align: initial; -} - -video::-webkit-media-controls-closed-captions-container .list, -audio::-webkit-media-controls-closed-captions-container .list { - display: block; - -webkit-user-select: none; -} - -video::-webkit-media-controls-closed-captions-container h3, -audio::-webkit-media-controls-closed-captions-container h3 { - margin: 0; - color: rgb(140, 140, 140); - text-shadow: 0 1px 0 black; - -webkit-margin-start: 16px; - padding-top: 4px; - font-size: 11px; -} - -video::-webkit-media-controls-closed-captions-container ul, -audio::-webkit-media-controls-closed-captions-container ul { - list-style-type: none; - margin: 0 0 8px 0; - padding: 0; -} - -video::-webkit-media-controls-closed-captions-container li, -audio::-webkit-media-controls-closed-captions-container li { - position: relative; - color: white; - background-image: none; - text-shadow: 0 1px 0 black; - margin: 0; - padding-left: 28px; - padding-right: 28px; - padding-top: 0.15em; - padding-bottom: 0.2em; - box-sizing: border-box; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; -} - -video::-webkit-media-controls-closed-captions-container li:focus, -audio::-webkit-media-controls-closed-captions-container li:focus { - outline: 0; - background-color: rgba(140, 140, 140, 0.5); -} - -video::-webkit-media-controls-closed-captions-container li:hover, -audio::-webkit-media-controls-closed-captions-container li:hover { - background-color: rgba(26, 68, 243, 0.6); -} - -video::-webkit-media-controls-closed-captions-container li .checkmark-container, -audio::-webkit-media-controls-closed-captions-container li .checkmark-container { - display: none; - position: absolute; - top: 0.25em; - left: 1em; - width: 1.1em; - height: 1.1em; -} - -video::-webkit-media-controls-closed-captions-container li.selected .checkmark-container, -audio::-webkit-media-controls-closed-captions-container li.selected .checkmark-container { - display: inline-block; - content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300"><polygon fill="rgb(163, 163, 163)" points="252.301,4.477 126.667,194.104 43.358,108.3 6.868,161.408 132.515,290.814 297.732,49.926"/></svg>'); -} - -video::-webkit-media-controls-closed-captions-container li.selected:hover .checkmark-container, -audio::-webkit-media-controls-closed-captions-container li.selected:hover .checkmark-container { - content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300"><polygon fill="rgba(255,255,255,0.45)" points="252.301,4.477 126.667,194.104 43.358,108.3 6.868,161.408 132.515,290.814 297.732,49.926"/></svg>'); -} - -video::-webkit-media-controls-fullscreen-button, -audio::-webkit-media-controls-fullscreen-button { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 15" stroke="rgba(255,255,255,0.45)" fill="none"><path d="M 7,1.5 L 12.5,1.5 L 12.5,7"/><path d="M 0.5,8 L 0.5,13.5 L 6,13.5"/><path stroke-linecap="round" d="M 12.5,1.5 L 7.5,6.5"/><path stroke-linecap="round" d="M 0.5,13.5 L 5.5,8.5"/></svg>'); - margin-right: 7px; - margin-left: 8px; - width: 14px; - min-width: 14px; -} - -video::-webkit-media-controls-fullscreen-button.exit, -audio::-webkit-media-controls-fullscreen-button.exit { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 15" stroke="rgba(255,255,255,0.45)" fill="none"><path d="M 7.5,1 L 7.5,6.5 L 13,6.5"/><path d="M 0,8.5 L 5.5,8.5 L 5.5,14"/><path stroke-linecap="round" d="M 7.5,6.5 L 12.5,1.5"/><path stroke-linecap="round" d="M 5.5,8.5 L 0.5,13.5"/></svg>'); - margin-right: 11px; - margin-left: 0px; - margin-top: 6px; -} - -video::-webkit-media-controls-status-display, -audio::-webkit-media-controls-status-display { - cursor: default; - overflow: hidden; - color: rgb(156, 156, 156); - opacity: 0.99; - - letter-spacing: normal; - word-spacing: normal; - line-height: 25px; - text-transform: none; - text-indent: 0; - text-decoration: none; - text-align: left; - - padding: 0 12px; - - -webkit-flex: 1 1 0; -} - -video::-webkit-media-controls-status-display { - color: white; - opacity: .45; - mix-blend-mode: plus-lighter; -} - -video::-webkit-media-controls-timeline, -audio::-webkit-media-controls-timeline { - -webkit-appearance: none !important; - -webkit-flex: 1 1 0 !important; - height: 17px !important; - margin: 0 !important; - background-size: 100% 100% !important; - background-repeat: no-repeat; - background-color: transparent; -} - -video::-webkit-media-controls-timeline { - mix-blend-mode: plus-lighter; -} - -video::-webkit-media-controls-timeline::-webkit-slider-thumb, -audio::-webkit-media-controls-timeline::-webkit-slider-thumb { - -webkit-appearance: none !important; - width: 3px !important; - height: 15px !important; -} - -video::-webkit-media-controls-current-time-display, -video::-webkit-media-controls-time-remaining-display, -audio::-webkit-media-controls-current-time-display, -audio::-webkit-media-controls-time-remaining-display { - -webkit-user-select: none; - -webkit-flex: 0 0 0; - display: -webkit-flex; - cursor: default; - overflow: hidden; - color: rgb(156, 156, 156); - letter-spacing: normal; - word-spacing: normal; - line-height: normal; - text-transform: none; - text-indent: 0px; - text-decoration: none; - position: relative; - bottom: 0.5px; - font-family: -apple-system-monospaced-numbers; - font-size: 11px !important; - font-style: normal !important; - font-weight: normal !important; - -webkit-text-size-adjust: none; -} - -video::-webkit-media-controls-current-time-display, -video::-webkit-media-controls-time-remaining-display { - color: white; - opacity: .45; - mix-blend-mode: plus-lighter; -} - -video::-webkit-media-controls-current-time-display, -audio::-webkit-media-controls-current-time-display { - margin-left: 8px; - margin-right: 8px; - width: 32px; - min-width: 32px; - -webkit-justify-content: flex-end; -} - -video::-webkit-media-controls-time-remaining-display, -audio::-webkit-media-controls-time-remaining-display { - margin-left: 8px; - margin-right: 8px; - width: 37px; - min-width: 37px; - -webkit-justify-content: flex-start; -} - -video::-webkit-media-controls-time-remaining-display.five-digit-time, -audio::-webkit-media-controls-time-remaining-display.five-digit-time { - min-width: 47px; -} - -video::-webkit-media-controls-current-time-display.five-digit-time, -audio::-webkit-media-controls-current-time-display.five-digit-time { - min-width: 42px; -} - -video::-webkit-media-controls-time-remaining-display.six-digit-time, -audio::-webkit-media-controls-time-remaining-display.six-digit-time { - min-width: 54px; -} - -video::-webkit-media-controls-current-time-display.six-digit-time, -audio::-webkit-media-controls-current-time-display.six-digit-time { - min-width: 49px; -} - -video::-webkit-media-controls-timeline-container, -audio::-webkit-media-controls-timeline-container { - display: -webkit-flex; - -webkit-flex-direction: row; - -webkit-align-items: center; - -webkit-user-select: none; - -webkit-flex: 1 1 0; - min-width: 0; - position: relative; - padding: 0; -} - -video::-webkit-media-controls-panel .thumbnail-track, -audio::-webkit-media-controls-panel .thumbnail-track { - position: relative; - -webkit-flex: 1 1 0; - min-width: 0; - height: 17px; - margin: 0 2px; - display: -webkit-flex; - -webkit-align-items: stretch; - -webkit-flex-direction: column; -} - -video::-webkit-media-controls-panel .thumbnail, -audio::-webkit-media-controls-panel .thumbnail { - position: absolute; - opacity: 0; - transition: opacity 0.25s linear; - bottom: 15px; - width: 100px; - height: 58px; - margin-left: -50px; - border: 5px solid black; - box-shadow: 0 0 3px white; - border-radius: 3px; -} - -video::-webkit-media-controls-panel .thumbnail-image, -audio::-webkit-media-controls-panel .thumbnail-image { - width: 100%; - height: 100%; -} - -video::-webkit-media-controls-panel .thumbnail.show, -audio::-webkit-media-controls-panel .thumbnail.show { - opacity: 1; -} - -video::-webkit-media-controls-panel.hidden, -audio::-webkit-media-controls-panel.hidden { - display: none; -} - -video::-webkit-media-controls-panel .hidden, -audio::-webkit-media-controls-panel .hidden, -video::-webkit-media-controls-panel .dropped, -audio::-webkit-media-controls-panel .dropped { - display: none; -} - -/* Full Screen */ - -/* - Page stylesheets are not allowed to override the style of media - controls while in full screen mode, so many if not all the rules - defined in this section will be marked as !important to enforce - this restriction -*/ - -video:-webkit-full-screen::-webkit-media-controls-panel { - -webkit-align-items: flex-start !important; - -webkit-justify-content: flex-end !important; - -webkit-clip-path: inset(20px round 6px); - - width: 480px !important; - height: 104px !important; - margin: 0 auto 12px auto !important; - padding: 20px; - padding-top: 30px !important; - - background-color: transparent; - border-radius: 6px !important; - - transition: opacity 0.3s linear !important; -} - -video:-webkit-full-screen::-webkit-media-controls-panel-tint, -audio:-webkit-full-screen::-webkit-media-controls-panel-tint { - position: absolute; - left: 0; - top: 0; - width: 480px !important; - height: 104px !important; - border-radius: 6px !important; - background-color: rgb(41, 41, 41); - mix-blend-mode: lighten; -} - -video:-webkit-full-screen::-webkit-media-controls-panel-background, -audio:-webkit-full-screen::-webkit-media-controls-panel-background { - position: absolute; - left: 0; - top: 0; - width: 480px !important; - height: 104px !important; - border-radius: 6px !important; - background-color: rgba(30, 30, 30, 0.45); - -webkit-backdrop-filter: saturate(180%) blur(20px); -} - -video:-webkit-animating-full-screen-transition::-webkit-media-controls-panel { - opacity: 0 ! important; - transition: opacity 0 ! important; -} - -video:-webkit-full-screen::-webkit-media-controls-panel .volume-box { - -webkit-transform: none; - -webkit-clip-path: none; - opacity: 1; - left: 32px; - top: 35px; - width: 96px; - height: 17px; - display: -webkit-flex; - -webkit-flex-direction: row; - -webkit-align-items: center; - background-color: transparent; - border: none; -} - -video:-webkit-full-screen::-webkit-media-controls-volume-slider { - -webkit-transform: none; - background-color: transparent; - min-width: 60px !important; - width: 60px !important; - height: 9px !important; - margin: 0 !important; -} - -video:-webkit-full-screen::-webkit-media-controls-mute-button, -audio:-webkit-full-screen::-webkit-media-controls-mute-button, -video:-webkit-full-screen::-webkit-media-controls-volume-max-button { - width: 14px !important; - margin-left: 6px !important; - margin-bottom: 2px !important; - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 15" stroke="rgba(255,255,255,0.45)" fill="none" stroke-width="1.25" stroke-linecap="round"><defs><clipPath id="cut-hole"><rect x="3" y="0" width="3.5" height="15"/></clipPath></defs><path stroke="none" fill="rgba(255,255,255,0.45)" shape-rendering="crispEdges" d="M 0,10 0,6 3,6 3,10 z"/><path stroke="none" fill="rgba(255,255,255,0.45)" clip-path="url(#cut-hole)" shape-rendering="crispEdges" d="M 3.5,6 6.5,3 6.5,13 3.5,10 z"/><path d="M 9,5.5 C 10.75,7 10.75,9 9,10.5"/><path d="M 10,3.5 C 13,4.5 13,11.5 10,12.5" /><path d="M 11,1.5 C 15.67,3.5 15.67,12.5 11,14.5"/></svg>'); -} -video:-webkit-full-screen::-webkit-media-controls-mute-button, -audio:-webkit-full-screen::-webkit-media-controls-mute-button, -video:-webkit-full-screen::-webkit-media-controls-volume-min-button { - width: 14px !important; - margin-right: 2px !important; - margin-bottom: 2px !important; - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 15" stroke="rgba(255,255,255,0.45)" fill="none" stroke-width="1.25" stroke-linecap="round"><defs><clipPath id="cut-hole"><rect x="3" y="0" width="3.5" height="15"/></clipPath></defs><path stroke="none" fill="rgba(255,255,255,0.45)" shape-rendering="crispEdges" d="M 0,10 0,6 3,6 3,10 z"/><path stroke="none" fill="rgba(255,255,255,0.45)" clip-path="url(#cut-hole)" shape-rendering="crispEdges" d="M 3.5,6 6.5,3 6.5,13 3.5,10 z"/><path d="M 9,5.5 C 10.75,7 10.75,9 9,10.5"/></svg>'); -} - -video:-webkit-full-screen::-webkit-media-controls-play-button { - position: absolute; - - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21 23" fill="rgba(255,255,255,0.45)"><path d="M 0,0 0,22 8,22 8,0 z"/><path d="M 13,0 13,22 21,22 21,0 z"/></svg>'); - - width: 21px; - height: 23px; - left: 230px; - top: 32px; - margin: 0; - padding: 0; -} - -video:-webkit-full-screen::-webkit-media-controls-play-button.paused { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21 23" fill="rgba(255,255,255,0.45)"><path d="M 0,0 21,11.5 0,23 z"/></svg>'); -} - -video:-webkit-full-screen::-webkit-media-controls-seek-back-button { - position: absolute; - - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 15" fill="rgba(255,255,255,0.45)"><path d="M 24,0 12,7 24,15 z"/><path d="M 12,0 0,7 12,15 z"/></svg>'); - - width: 24px; - height: 15px; - left: 176px; - top: 36px; -} - -video:-webkit-full-screen::-webkit-media-controls-return-to-realtime-button { - position: absolute; - display: -webkit-flex; - width: 29px; - height: 16px; - left: 262px; - top: 13px; -} - -video:-webkit-full-screen::-webkit-media-controls-seek-forward-button { - position: absolute; - - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 15" fill="rgba(255,255,255,0.45)"><path d="M 0,0 12,7 0,15 z"/><path d="M 12,0 24,7 12,15 z"/></svg>'); - - width: 24px; - height: 15px; - left: 275px; - top: 36px; -} - -video:-webkit-full-screen::-webkit-media-controls-timeline-container { - height: auto; - width: 440px; - position: absolute; - bottom: 28px; - left: 20px; -} - -video:-webkit-full-screen::-webkit-media-controls-current-time-display { - margin-left: 12px; -} - -video:-webkit-full-screen::-webkit-media-controls-time-remaining-display { - margin-right: 12px; -} - -video:-webkit-full-screen::-webkit-media-controls-status-display { - width: 440px; - position: absolute; - bottom: 25px; - text-align: center; - padding: 0; - left: 20px; -} - -video:-webkit-full-screen::-webkit-media-controls-toggle-closed-captions-button, -audio:-webkit-full-screen::-webkit-media-controls-toggle-closed-captions-button { - margin-top: 6px; - margin-right:24px; - margin-left: 0px; -} - -video:-webkit-full-screen::-webkit-media-controls-wireless-playback-picker-button, -audio:-webkit-full-screen::-webkit-media-controls-wireless-playback-picker-button { - margin-top: 6px; - margin-right:24px; - margin-left: 0px; -} - -video:-webkit-full-screen::-webkit-media-controls-closed-captions-container { - bottom: 100px; - right: calc(50% - 183px); /* 183px is 221px (half the media controller's width) minus 38px (the right position of the captions icon). */ - max-width: calc(50% + 173px); /* right + 10px */ - max-height: calc(100% - 124px); /* bottom + 10px */ -} - -video::-webkit-media-text-track-container { - position: relative; - width: 100%; - overflow: hidden; - padding-bottom: 5px; - - text-align: center; - color: rgba(255, 255, 255, 1); - - letter-spacing: normal; - word-spacing: normal; - text-transform: none; - text-indent: 0; - text-decoration: none; - pointer-events: none; - -webkit-user-select: none; - - -webkit-flex: 1 1; - - -webkit-line-box-contain: block inline-box replaced; -} - -video::cue { - background-color: rgba(0, 0, 0, 0.8); -} - -video::-webkit-media-text-track-display { - position: absolute; - overflow: hidden; - white-space: pre-wrap; - -webkit-box-sizing: border-box; - font: 22px sans-serif; -} - -video::-webkit-media-text-track-display-backdrop { - display: inline-block; -} - -video::cue(:future) { - color: gray; -} - -video::-webkit-media-text-track-container b { - font-weight: bold; -} - -video::-webkit-media-text-track-container u { - text-decoration: underline; -} - -video::-webkit-media-text-track-container i { - font-style: italic; -} - -video::-webkit-media-text-track-container .hidden, -audio::-webkit-media-text-track-container .hidden { - display: none; -} - -/* ============ ACTIVE VERSIONS OF ALL BUTTONS ============= */ - -video::-webkit-media-controls-mute-button:active, -audio::-webkit-media-controls-mute-button:active, -video::-webkit-media-controls-volume-max-button:active { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 15" stroke="white" fill="none" stroke-width="1.25" stroke-linecap="round"><defs><clipPath id="cut-hole"><rect x="3" y="0" width="3.5" height="15"/></clipPath></defs><path stroke="none" fill="white" shape-rendering="crispEdges" d="M 0,10 0,6 3,6 3,10 z"/><path stroke="none" fill="white" clip-path="url(#cut-hole)" shape-rendering="crispEdges" d="M 3.5,6 6.5,3 6.5,13 3.5,10 z"/><path d="M 9,5.5 C 10.75,7 10.75,9 9,10.5"/><path d="M 10,3.5 C 13,4.5 13,11.5 10,12.5" /><path d="M 11,1.5 C 15.67,3.5 15.67,12.5 11,14.5"/></svg>'); -} - -video::-webkit-media-controls-panel button.muted:active, -audio::-webkit-media-controls-panel button.muted:active, -video::-webkit-media-controls-volume-min-button:active { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 15" stroke="white" fill="none" stroke-width="1.25" stroke-linecap="round"><defs><clipPath id="cut-hole"><rect x="3" y="0" width="3.5" height="15"/></clipPath></defs><path stroke="none" fill="white" shape-rendering="crispEdges" d="M 0,10 0,6 3,6 3,10 z"/><path stroke="none" fill="white" clip-path="url(#cut-hole)" shape-rendering="crispEdges" d="M 3.5,6 6.5,3 6.5,13 3.5,10 z"/></svg>'); -} - -video::-webkit-media-controls-toggle-closed-captions-button:active, -audio::-webkit-media-controls-toggle-closed-captions-button:active { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 15" stroke="white" fill="none"><defs> <clipPath id="cut-hole"><rect x="0" y="1" width="16" height="10"/><rect x="0" y="11" width="9" height="1"/><rect x="11" y="11" width="5" height="1"/></clipPath></defs> <rect x="0.5" y="1.5" rx="1" ry="1" width="15" height="10" clip-path="url(#cut-hole)"/><path d="M 2,6.5 h 4"/><path d="M 7,6.5 h 7"/><path d="M 3,8.5 h 2"/><path d="M 6,8.5 h 3"/><path d="M 10,8.5 h 3"/><path d="M 8.5,11.5 L 8.5,13.75 L 11,11"/></svg>'); -} - -video::-webkit-media-controls-rewind-button:active, -audio::-webkit-media-controls-rewind-button:active { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 17" fill="white"><path d="m 7.9131,2 0,-1.548 -2.586,2.155 0,-2.171 -2.582,2.208 2.582,2.175 0,-2.139 2.586,2.155 0,-1.276 c 3.138,0.129 5.491,2.681 5.543,5.838 l -1.031,0 0.016,0.215 1.015,0 c -0.06,3.19 -2.629,5.765 -5.819,5.833 l 0,-1.018 -0.214,0 0,1.021 c -3.21,-0.047 -5.801,-2.631 -5.862,-5.836 l 1.045,0 -0.016,-0.215 -1.045,0 c -0.052,-0.288 -0.318,-0.654 -0.766,-0.654 -0.538,0 -0.755,0.484 -0.755,0.75 0,4.146 3.331,7.506 7.476,7.506 4.146,0 7.506,-3.36 7.506,-7.506 0,-4.059 -3.066,-7.357 -7.093,-7.493"/><path d="m 5.1729,11.0518 c -0.38,0 -0.668,-0.129 -0.945,-0.366 -0.083,-0.071 -0.186,-0.134 -0.338,-0.134 -0.277,0 -0.511,0.238 -0.511,0.521 0,0.154 0.083,0.301 0.179,0.383 0.394,0.346 0.911,0.563 1.601,0.563 1.077,0 1.739,-0.451 1.739,-1.608 l 0,-0.013 c 0,-0.911 -0.641,-1.265 -1.296,-1.376 l 0.945,-0.919 c 0.193,-0.19 0.317,-0.337 0.317,-0.604 0,-0.294 -0.228,-0.477 -0.538,-0.477 l -2.354,0 c -0.248,0 -0.455,0.21 -0.455,0.464 0,0.253 0.207,0.463 0.455,0.463 l 1.485,0 -0.939,0.961 c -0.166,0.169 -0.228,0.295 -0.228,0.444 0,0.25 0.207,0.463 0.455,0.463 l 0.166,0 c 0.594,0 0.945,0.222 0.945,0.624 l 0,0.012 c 0,0.367 -0.282,0.599 -0.453,0.599"/><path d="m 10.354,9.5342 c 0,0.876 -0.379,1.525 -0.979,1.525 -0.599,0 -0.992,-0.655 -0.992,-1.539 l 0,-0.012 c 0,-0.884 0.388,-1.527 0.979,-1.527 0.592,0 0.992,0.663 0.992,1.539 l 0,0.014 z m -0.979,-2.512 c -1.197,0 -2.008,1.097 -2.008,2.498 l 0,0.014 c 0,1.401 0.792,2.484 1.995,2.484 1.205,0 2.01,-1.097 2.01,-2.498 l 0,-0.012 c 0,-1.402 -0.805,-2.486 -1.997,-2.486"/></svg>'); -} - -video::-webkit-media-controls-panel button.paused:active, -audio::-webkit-media-controls-panel button.paused:active { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 15" fill="white"><path d="M 0,1 12,7.5 0,14 z"/></svg>'); -} - -video::-webkit-media-controls-play-button:active, -audio::-webkit-media-controls-play-button:active { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 15" fill="white"><rect x="0" y="1" width="4" height="13"/><rect x="8" y="1" width="4" height="13"/></svg>'); -} - -video:-webkit-full-screen::-webkit-media-controls-mute-button:active, -audio:-webkit-full-screen::-webkit-media-controls-mute-button:active, -video:-webkit-full-screen::-webkit-media-controls-volume-max-button:active { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 15" stroke="white" fill="none" stroke-width="1.25" stroke-linecap="round"><defs><clipPath id="cut-hole"><rect x="3" y="0" width="3.5" height="15"/></clipPath></defs><path stroke="none" fill="white" shape-rendering="crispEdges" d="M 0,10 0,6 3,6 3,10 z"/><path stroke="none" fill="white" clip-path="url(#cut-hole)" shape-rendering="crispEdges" d="M 3.5,6 6.5,3 6.5,13 3.5,10 z"/><path d="M 9,5.5 C 10.75,7 10.75,9 9,10.5"/><path d="M 10,3.5 C 13,4.5 13,11.5 10,12.5" /><path d="M 11,1.5 C 15.67,3.5 15.67,12.5 11,14.5"/></svg>'); -} -video:-webkit-full-screen::-webkit-media-controls-mute-button:active, -audio:-webkit-full-screen::-webkit-media-controls-mute-button:active, -video:-webkit-full-screen::-webkit-media-controls-volume-min-button:active { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 15" stroke="white" fill="none" stroke-width="1.25" stroke-linecap="round"><defs><clipPath id="cut-hole"><rect x="3" y="0" width="3.5" height="15"/></clipPath></defs><path stroke="none" fill="white" shape-rendering="crispEdges" d="M 0,10 0,6 3,6 3,10 z"/><path stroke="none" fill="white" clip-path="url(#cut-hole)" shape-rendering="crispEdges" d="M 3.5,6 6.5,3 6.5,13 3.5,10 z"/><path d="M 9,5.5 C 10.75,7 10.75,9 9,10.5"/></svg>'); -} - -video:-webkit-full-screen::-webkit-media-controls-play-button:active{ - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21 23" fill="white"><path d="M 0,0 0,22 8,22 8,0 z"/><path d="M 13,0 13,22 21,22 21,0 z"/></svg>'); -} - -video:-webkit-full-screen::-webkit-media-controls-panel button.paused:active { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21 23" fill="white"><path d="M 0,0 21,11.5 0,23 z"/></svg>'); -} - -video:-webkit-full-screen::-webkit-media-controls-seek-back-button:active { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 15" fill="white"><path d="M 24,0 12,7 24,15 z"/><path d="M 12,0 0,7 12,15 z"/></svg>'); -} - -video:-webkit-full-screen::-webkit-media-controls-seek-forward-button:active { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 15" fill="white"><path d="M 0,0 12,7 0,15 z"/><path d="M 12,0 24,7 12,15 z"/></svg>'); -} - -video::-webkit-media-controls-fullscreen-button:active, -audio::-webkit-media-controls-fullscreen-button:active { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 15" stroke="white" fill="none"><path d="M 7,1.5 L 12.5,1.5 L 12.5,7"/><path d="M 0.5,8 L 0.5,13.5 L 6,13.5"/><path stroke-linecap="round" d="M 12.5,1.5 L 7.5,6.5"/><path stroke-linecap="round" d="M 0.5,13.5 L 5.5,8.5"/></svg>'); -} - -video::-webkit-media-controls-panel button.exit:active, -audio::-webkit-media-controls-panel button.exit:active { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 15" stroke="white" fill="none"><path d="M 7.5,1 L 7.5,6.5 L 13,6.5"/><path d="M 0,8.5 L 5.5,8.5 L 5.5,14"/><path stroke-linecap="round" d="M 7.5,6.5 L 12.5,1.5"/><path stroke-linecap="round" d="M 5.5,8.5 L 0.5,13.5"/></svg>'); -} - -video::-webkit-media-controls-wireless-playback-picker-button:active, -audio::-webkit-media-controls-wireless-playback-picker-button:active { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 15" stroke="white"><defs> <clipPath fill-rule="evenodd" id="cut-hole"><path d="M 0,0.5 L 16,0.5 L 16,15.5 L 0,15.5 z M 0,14.5 L 16,14.5 L 8,5 z"/></clipPath></defs><rect fill="none" clip-path="url(#cut-hole)" x="0.5" y="2" width="15" height="8"/><path stroke="none" fill="white" d="M 3.5,13.25 L 12.5,13.25 L 8,8 z"/></svg>'); -} - -/* ==================== AIRPLAY PLACARD ==================== */ - -video::-webkit-media-controls-wireless-playback-status, -audio::-webkit-media-controls-wireless-playback-status { - display: block; - position: absolute; - left: 0px; - top: 0px; - width: 100%; - height: 100%; - background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 131 90"><g fill="none" stroke="-apple-system-gray" stroke-width="4"><rect x="2" y="2" width="127" height="76"/><line x1="30" y1="88" x2="101" y2="88"/></g></svg>'); - background-color: rgb(51, 51, 53); - background-repeat: no-repeat; - background-position: 50% calc(.5 * (100% - 25px) - 21pt); - background-size: 131px auto; - color: -apple-system-gray; - font-family: -apple-system; - vertical-align: text-bottom; -} - -video::-webkit-media-controls-wireless-playback-text, -audio::-webkit-media-controls-wireless-playback-text { - cursor: default; - position: absolute; - width: 100%; - top: calc(.5 * (100% - 25px) + (.5 * (90px + 42pt) - 42pt)); - -webkit-user-select: none; - margin: 0px; - height: 42pt; -} - -video::-webkit-media-controls-wireless-playback-text-top, -audio::-webkit-media-controls-wireless-playback-text-top { - position: absolute; - top: 15pt; - width: 100%; - line-height: 12pt; - height: 13pt; - font-size: 12pt; - text-align: center; - margin: 0px; -} - -video::-webkit-media-controls-wireless-playback-text-bottom, -audio::-webkit-media-controls-wireless-playback-text-bottom { - position: absolute; - bottom: 0; - left: 5%; - width: 90%; - line-height: 10pt; - height: 11pt; - font-size: 10pt; - text-align: center; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - margin: 0px; -} - -video::-webkit-media-controls-wireless-playback-status.small, -audio::-webkit-media-controls-wireless-playback-status.small { - background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 62 43"><g fill="none" stroke="-apple-system-gray" stroke-width="2"><rect x="1" y="1" width="60" height="36"/><line x1="14" y1="42" x2="48" y2="42"/></g></svg>'); - background-position: 50% calc(.5 * (100% - 25px) - 5pt); - background-size: 62px auto; -} - -video::-webkit-media-controls-wireless-playback-text-top.small, -audio::-webkit-media-controls-wireless-playback-text-top.small { - top: 4pt; -} - -video::-webkit-media-controls-wireless-playback-text-bottom.small, -audio::-webkit-media-controls-wireless-playback-text-bottom.small { - display: none; -} - -video::-webkit-media-controls-wireless-playback-status.picture-in-picture, -audio::-webkit-media-controls-wireless-playback-status.picture-in-picture -{ - background-size: 304px auto; - background-position: 50% calc(.5 * (100% - 25px)); - background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 304 150"><g fill="none" stroke="-apple-system-gray" stroke-width="3"><path d="m 172,106 -81,0 c -3.5,0 -6,-2.5 -6,-6 l 0,-89 c 0,-3.5 2.5,-6 6,-6 l 122,0 c 3.5,0 6,2.5 6,6 l 0,57" /><path d="m 233,119 -53,0 c -3,0 -3,-0 -3,-3 l 0,-40 c 0,-3 0,-3 3,-3 l 53,0 c 3,0 3,0 3,3 l 0,40 c 0,3 0,3 -3,3 z" /></g></svg>'); -} - -video::-webkit-media-controls-wireless-playback-text-top.picture-in-picture, -audio::-webkit-media-controls-wireless-playback-text-top.picture-in-picture { - top: initial; - bottom: 0; -} - -video::-webkit-media-controls-wireless-playback-text-bottom.picture-in-picture, -audio::-webkit-media-controls-wireless-playback-text-bottom.picture-in-picture { - display: none; -} - -video::-webkit-media-controls-wireless-playback-status.hidden, -audio::-webkit-media-controls-wireless-playback-status.hidden { - display: none; -} - -video::-webkit-media-controls-panel .picture-in-picture-button { - margin-right: 7px; - margin-left: 8px; - margin-top: 1px; - width: 18px; - min-width: 18px; - height: 14px; - - background-color: rgba(255,255,255,0.45); - -webkit-mask-size: 18px 14px; - -webkit-mask-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAAAkCAYAAAD2IghRAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAANhJREFUeNrslzEOwjAMRR2UA3AQ7sLKwsTEglg6sTIgLgs7qCZBRbIsWpDayHH1v/SHJmn0ZFutHYiIqX4F+cDMtCCncgseh1JiLJ5lxH+Br2qGZ2Gpa/IjeVMZ1/ur0ndgLdaeydsvF9/7LrYEz7oo+J0X8Kyz2GuT917As04K/uAFPKtR5xov4FnHLuIy+i7AqavxVr1jAh7H/HbRZE3QZGndBvaW1k1Z6VqdHtjzIBELZrHoKIfRzbpUxqY4IOJzLpWAiAMc4AAHOMAB/m9T9Bn1veklwACtBYmnlYBaIQAAAABJRU5ErkJggg=='); -} - -video::-webkit-media-controls-panel .picture-in-picture-button.return-from-picture-in-picture { - -webkit-mask-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAAAkCAYAAAD2IghRAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAOZJREFUeNpiZGBg+M8w+AEjMuf///8MTAxDFAxZh7Pgi5IBBv+HZYgPS4f/JwJ/GA1xCjMnIfAejf9poHPvfyy5GFvS6KdjyYPLXeAKiFiH/0ZiT6GT46ni8CAg/onEn0WH/EEVh4OAL5rjFwIx81BwOAh4APE3JPGlNHQ8VR0OAs5A/BVJbjUQsw0Fh4OAHRB/RpLPG0wOJwSsoTXnfBolF5o5HARUBqL2pYbDB6bGBDqchYYlAk27cqPt8YFuHVIaxYyjIT6ckwrjaIiPOnzU4aMOH3X4qMNHHU5sowjWmxhqACDAAI3lmdvpn4aTAAAAAElFTkSuQmCC'); -} - -video::-webkit-media-controls-panel.picture-in-picture { - opacity: 0; - pointer-events: none; -} diff --git a/Source/WebCore/Modules/mediacontrols/mediaControlsApple.js b/Source/WebCore/Modules/mediacontrols/mediaControlsApple.js deleted file mode 100644 index 1885c38ef..000000000 --- a/Source/WebCore/Modules/mediacontrols/mediaControlsApple.js +++ /dev/null @@ -1,2291 +0,0 @@ -function createControls(root, video, host) -{ - return new Controller(root, video, host); -}; - -function Controller(root, video, host) -{ - this.video = video; - this.root = root; - this.host = host; - this.controls = {}; - this.listeners = {}; - this.isLive = false; - this.statusHidden = true; - this.hasWirelessPlaybackTargets = false; - this.isListeningForPlaybackTargetAvailabilityEvent = false; - this.currentTargetIsWireless = false; - this.wirelessPlaybackDisabled = false; - this.isVolumeSliderActive = false; - this.currentDisplayWidth = 0; - this._scrubbing = false; - this._pageScaleFactor = 1; - - this.addVideoListeners(); - this.createBase(); - this.createControls(); - this.updateBase(); - this.updateControls(); - this.updateDuration(); - this.updateProgress(); - this.updateTime(); - this.updateReadyState(); - this.updatePlaying(); - this.updateThumbnail(); - this.updateCaptionButton(); - this.updateCaptionContainer(); - this.updateFullscreenButtons(); - this.updateVolume(); - this.updateHasAudio(); - this.updateHasVideo(); - this.updateWirelessTargetAvailable(); - this.updateWirelessPlaybackStatus(); - this.scheduleUpdateLayoutForDisplayedWidth(); - - this.listenFor(this.root, 'resize', this.handleRootResize); -}; - -/* Enums */ -Controller.InlineControls = 0; -Controller.FullScreenControls = 1; - -Controller.PlayAfterSeeking = 0; -Controller.PauseAfterSeeking = 1; - -/* Globals */ -Controller.gSimulateWirelessPlaybackTarget = false; // Used for testing when there are no wireless targets. -Controller.gSimulatePictureInPictureAvailable = false; // Used for testing when picture-in-picture is not available. - -Controller.prototype = { - - /* Constants */ - HandledVideoEvents: { - loadstart: 'handleLoadStart', - error: 'handleError', - abort: 'handleAbort', - suspend: 'handleSuspend', - stalled: 'handleStalled', - waiting: 'handleWaiting', - emptied: 'handleReadyStateChange', - loadedmetadata: 'handleReadyStateChange', - loadeddata: 'handleReadyStateChange', - canplay: 'handleReadyStateChange', - canplaythrough: 'handleReadyStateChange', - timeupdate: 'handleTimeUpdate', - durationchange: 'handleDurationChange', - playing: 'handlePlay', - pause: 'handlePause', - progress: 'handleProgress', - volumechange: 'handleVolumeChange', - webkitfullscreenchange: 'handleFullscreenChange', - webkitbeginfullscreen: 'handleFullscreenChange', - webkitendfullscreen: 'handleFullscreenChange', - }, - HideControlsDelay: 4 * 1000, - RewindAmount: 30, - MaximumSeekRate: 8, - SeekDelay: 1500, - ClassNames: { - active: 'active', - dropped: 'dropped', - exit: 'exit', - failed: 'failed', - hidden: 'hidden', - hiding: 'hiding', - threeDigitTime: 'three-digit-time', - fourDigitTime: 'four-digit-time', - fiveDigitTime: 'five-digit-time', - sixDigitTime: 'six-digit-time', - list: 'list', - muteBox: 'mute-box', - muted: 'muted', - paused: 'paused', - pictureInPicture: 'picture-in-picture', - playing: 'playing', - returnFromPictureInPicture: 'return-from-picture-in-picture', - selected: 'selected', - show: 'show', - small: 'small', - thumbnail: 'thumbnail', - thumbnailImage: 'thumbnail-image', - thumbnailTrack: 'thumbnail-track', - volumeBox: 'volume-box', - noVideo: 'no-video', - down: 'down', - out: 'out', - pictureInPictureButton: 'picture-in-picture-button', - }, - KeyCodes: { - enter: 13, - escape: 27, - space: 32, - pageUp: 33, - pageDown: 34, - end: 35, - home: 36, - left: 37, - up: 38, - right: 39, - down: 40 - }, - MinimumTimelineWidth: 150, - ButtonWidth: 32, - - extend: function(child) - { - // This function doesn't actually do what we want it to. In particular it - // is not copying the getters and setters to the child class, since they are - // not enumerable. What we should do is use ES6 classes, or assign the __proto__ - // directly. - // FIXME: Use ES6 classes. - - for (var property in this) { - if (!child.hasOwnProperty(property)) - child[property] = this[property]; - } - }, - - get idiom() - { - return "apple"; - }, - - UIString: function(developmentString, replaceString, replacementString) - { - var localized = UIStringTable[developmentString]; - if (replaceString && replacementString) - return localized.replace(replaceString, replacementString); - - if (localized) - return localized; - - console.error("Localization for string \"" + developmentString + "\" not found."); - return "LOCALIZED STRING NOT FOUND"; - }, - - listenFor: function(element, eventName, handler, useCapture) - { - if (typeof useCapture === 'undefined') - useCapture = false; - - if (!(this.listeners[eventName] instanceof Array)) - this.listeners[eventName] = []; - this.listeners[eventName].push({element:element, handler:handler, useCapture:useCapture}); - element.addEventListener(eventName, this, useCapture); - }, - - stopListeningFor: function(element, eventName, handler, useCapture) - { - if (typeof useCapture === 'undefined') - useCapture = false; - - if (!(this.listeners[eventName] instanceof Array)) - return; - - this.listeners[eventName] = this.listeners[eventName].filter(function(entry) { - return !(entry.element === element && entry.handler === handler && entry.useCapture === useCapture); - }); - element.removeEventListener(eventName, this, useCapture); - }, - - addVideoListeners: function() - { - for (var name in this.HandledVideoEvents) { - this.listenFor(this.video, name, this.HandledVideoEvents[name]); - }; - - /* text tracks */ - this.listenFor(this.video.textTracks, 'change', this.handleTextTrackChange); - this.listenFor(this.video.textTracks, 'addtrack', this.handleTextTrackAdd); - this.listenFor(this.video.textTracks, 'removetrack', this.handleTextTrackRemove); - - /* audio tracks */ - this.listenFor(this.video.audioTracks, 'change', this.handleAudioTrackChange); - this.listenFor(this.video.audioTracks, 'addtrack', this.handleAudioTrackAdd); - this.listenFor(this.video.audioTracks, 'removetrack', this.handleAudioTrackRemove); - - /* video tracks */ - this.listenFor(this.video.videoTracks, 'change', this.updateHasVideo); - this.listenFor(this.video.videoTracks, 'addtrack', this.updateHasVideo); - this.listenFor(this.video.videoTracks, 'removetrack', this.updateHasVideo); - - /* controls attribute */ - this.controlsObserver = new MutationObserver(this.handleControlsChange.bind(this)); - this.controlsObserver.observe(this.video, { attributes: true, attributeFilter: ['controls'] }); - - this.listenFor(this.video, 'webkitcurrentplaybacktargetiswirelesschanged', this.handleWirelessPlaybackChange); - - if ('webkitPresentationMode' in this.video) - this.listenFor(this.video, 'webkitpresentationmodechanged', this.handlePresentationModeChange); - }, - - removeVideoListeners: function() - { - for (var name in this.HandledVideoEvents) { - this.stopListeningFor(this.video, name, this.HandledVideoEvents[name]); - }; - - /* text tracks */ - this.stopListeningFor(this.video.textTracks, 'change', this.handleTextTrackChange); - this.stopListeningFor(this.video.textTracks, 'addtrack', this.handleTextTrackAdd); - this.stopListeningFor(this.video.textTracks, 'removetrack', this.handleTextTrackRemove); - - /* audio tracks */ - this.stopListeningFor(this.video.audioTracks, 'change', this.handleAudioTrackChange); - this.stopListeningFor(this.video.audioTracks, 'addtrack', this.handleAudioTrackAdd); - this.stopListeningFor(this.video.audioTracks, 'removetrack', this.handleAudioTrackRemove); - - /* video tracks */ - this.stopListeningFor(this.video.videoTracks, 'change', this.updateHasVideo); - this.stopListeningFor(this.video.videoTracks, 'addtrack', this.updateHasVideo); - this.stopListeningFor(this.video.videoTracks, 'removetrack', this.updateHasVideo); - - /* controls attribute */ - this.controlsObserver.disconnect(); - delete(this.controlsObserver); - - this.stopListeningFor(this.video, 'webkitcurrentplaybacktargetiswirelesschanged', this.handleWirelessPlaybackChange); - this.setShouldListenForPlaybackTargetAvailabilityEvent(false); - - if ('webkitPresentationMode' in this.video) - this.stopListeningFor(this.video, 'webkitpresentationmodechanged', this.handlePresentationModeChange); - }, - - handleEvent: function(event) - { - var preventDefault = false; - - try { - if (event.target === this.video) { - var handlerName = this.HandledVideoEvents[event.type]; - var handler = this[handlerName]; - if (handler && handler instanceof Function) - handler.call(this, event); - } - - if (!(this.listeners[event.type] instanceof Array)) - return; - - this.listeners[event.type].forEach(function(entry) { - if (entry.element === event.currentTarget && entry.handler instanceof Function) - preventDefault |= entry.handler.call(this, event); - }, this); - } catch(e) { - if (window.console) - console.error(e); - } - - if (preventDefault) { - event.stopPropagation(); - event.preventDefault(); - } - }, - - createBase: function() - { - var base = this.base = document.createElement('div'); - base.setAttribute('pseudo', '-webkit-media-controls'); - this.listenFor(base, 'mousemove', this.handleWrapperMouseMove); - this.listenFor(this.video, 'mouseout', this.handleWrapperMouseOut); - if (this.host.textTrackContainer) - base.appendChild(this.host.textTrackContainer); - }, - - shouldHaveAnyUI: function() - { - return this.shouldHaveControls() || (this.video.textTracks && this.video.textTracks.length) || this.currentPlaybackTargetIsWireless(); - }, - - shouldHaveControls: function() - { - if (!this.isAudio() && !this.host.allowsInlineMediaPlayback) - return true; - - return this.video.controls || this.isFullScreen(); - }, - - setNeedsTimelineMetricsUpdate: function() - { - this.timelineMetricsNeedsUpdate = true; - }, - - scheduleUpdateLayoutForDisplayedWidth: function() - { - setTimeout(this.updateLayoutForDisplayedWidth.bind(this), 0); - }, - - updateTimelineMetricsIfNeeded: function() - { - if (this.timelineMetricsNeedsUpdate && !this.controlsAreHidden()) { - this.timelineLeft = this.controls.timeline.offsetLeft; - this.timelineWidth = this.controls.timeline.offsetWidth; - this.timelineHeight = this.controls.timeline.offsetHeight; - this.timelineMetricsNeedsUpdate = false; - } - }, - - updateBase: function() - { - if (this.shouldHaveAnyUI()) { - if (!this.base.parentNode) { - this.root.appendChild(this.base); - } - } else { - if (this.base.parentNode) { - this.base.parentNode.removeChild(this.base); - } - } - }, - - createControls: function() - { - var panel = this.controls.panel = document.createElement('div'); - panel.setAttribute('pseudo', '-webkit-media-controls-panel'); - panel.setAttribute('aria-label', (this.isAudio() ? this.UIString('Audio Playback') : this.UIString('Video Playback'))); - panel.setAttribute('role', 'toolbar'); - this.listenFor(panel, 'mousedown', this.handlePanelMouseDown); - this.listenFor(panel, 'transitionend', this.handlePanelTransitionEnd); - this.listenFor(panel, 'click', this.handlePanelClick); - this.listenFor(panel, 'dblclick', this.handlePanelClick); - this.listenFor(panel, 'dragstart', this.handlePanelDragStart); - - var panelBackgroundContainer = this.controls.panelBackgroundContainer = document.createElement('div'); - panelBackgroundContainer.setAttribute('pseudo', '-webkit-media-controls-panel-background-container'); - - var panelTint = this.controls.panelTint = document.createElement('div'); - panelTint.setAttribute('pseudo', '-webkit-media-controls-panel-tint'); - this.listenFor(panelTint, 'mousedown', this.handlePanelMouseDown); - this.listenFor(panelTint, 'transitionend', this.handlePanelTransitionEnd); - this.listenFor(panelTint, 'click', this.handlePanelClick); - this.listenFor(panelTint, 'dblclick', this.handlePanelClick); - this.listenFor(panelTint, 'dragstart', this.handlePanelDragStart); - - var panelBackground = this.controls.panelBackground = document.createElement('div'); - panelBackground.setAttribute('pseudo', '-webkit-media-controls-panel-background'); - - var rewindButton = this.controls.rewindButton = document.createElement('button'); - rewindButton.setAttribute('pseudo', '-webkit-media-controls-rewind-button'); - rewindButton.setAttribute('aria-label', this.UIString('Rewind ##sec## Seconds', '##sec##', this.RewindAmount)); - this.listenFor(rewindButton, 'click', this.handleRewindButtonClicked); - - var seekBackButton = this.controls.seekBackButton = document.createElement('button'); - seekBackButton.setAttribute('pseudo', '-webkit-media-controls-seek-back-button'); - seekBackButton.setAttribute('aria-label', this.UIString('Rewind')); - this.listenFor(seekBackButton, 'mousedown', this.handleSeekBackMouseDown); - this.listenFor(seekBackButton, 'mouseup', this.handleSeekBackMouseUp); - - var seekForwardButton = this.controls.seekForwardButton = document.createElement('button'); - seekForwardButton.setAttribute('pseudo', '-webkit-media-controls-seek-forward-button'); - seekForwardButton.setAttribute('aria-label', this.UIString('Fast Forward')); - this.listenFor(seekForwardButton, 'mousedown', this.handleSeekForwardMouseDown); - this.listenFor(seekForwardButton, 'mouseup', this.handleSeekForwardMouseUp); - - var playButton = this.controls.playButton = document.createElement('button'); - playButton.setAttribute('pseudo', '-webkit-media-controls-play-button'); - playButton.setAttribute('aria-label', this.UIString('Play')); - this.listenFor(playButton, 'click', this.handlePlayButtonClicked); - - var statusDisplay = this.controls.statusDisplay = document.createElement('div'); - statusDisplay.setAttribute('pseudo', '-webkit-media-controls-status-display'); - statusDisplay.classList.add(this.ClassNames.hidden); - - var timelineBox = this.controls.timelineBox = document.createElement('div'); - timelineBox.setAttribute('pseudo', '-webkit-media-controls-timeline-container'); - - var currentTime = this.controls.currentTime = document.createElement('div'); - currentTime.setAttribute('pseudo', '-webkit-media-controls-current-time-display'); - currentTime.setAttribute('aria-label', this.UIString('Elapsed')); - currentTime.setAttribute('role', 'timer'); - - var timeline = this.controls.timeline = document.createElement('input'); - timeline.setAttribute('pseudo', '-webkit-media-controls-timeline'); - timeline.setAttribute('aria-label', this.UIString('Duration')); - timeline.type = 'range'; - timeline.value = 0; - this.listenFor(timeline, 'input', this.handleTimelineInput); - this.listenFor(timeline, 'change', this.handleTimelineChange); - this.listenFor(timeline, 'mouseover', this.handleTimelineMouseOver); - this.listenFor(timeline, 'mouseout', this.handleTimelineMouseOut); - this.listenFor(timeline, 'mousemove', this.handleTimelineMouseMove); - this.listenFor(timeline, 'mousedown', this.handleTimelineMouseDown); - this.listenFor(timeline, 'mouseup', this.handleTimelineMouseUp); - timeline.step = .01; - - this.timelineContextName = "_webkit-media-controls-timeline-" + this.host.generateUUID(); - timeline.style.backgroundImage = '-webkit-canvas(' + this.timelineContextName + ')'; - - var thumbnailTrack = this.controls.thumbnailTrack = document.createElement('div'); - thumbnailTrack.classList.add(this.ClassNames.thumbnailTrack); - - var thumbnail = this.controls.thumbnail = document.createElement('div'); - thumbnail.classList.add(this.ClassNames.thumbnail); - - var thumbnailImage = this.controls.thumbnailImage = document.createElement('img'); - thumbnailImage.classList.add(this.ClassNames.thumbnailImage); - - var remainingTime = this.controls.remainingTime = document.createElement('div'); - remainingTime.setAttribute('pseudo', '-webkit-media-controls-time-remaining-display'); - remainingTime.setAttribute('aria-label', this.UIString('Remaining')); - remainingTime.setAttribute('role', 'timer'); - - var muteBox = this.controls.muteBox = document.createElement('div'); - muteBox.classList.add(this.ClassNames.muteBox); - this.listenFor(muteBox, 'mouseover', this.handleMuteBoxOver); - - var muteButton = this.controls.muteButton = document.createElement('button'); - muteButton.setAttribute('pseudo', '-webkit-media-controls-mute-button'); - muteButton.setAttribute('aria-label', this.UIString('Mute')); - this.listenFor(muteButton, 'click', this.handleMuteButtonClicked); - - var minButton = this.controls.minButton = document.createElement('button'); - minButton.setAttribute('pseudo', '-webkit-media-controls-volume-min-button'); - minButton.setAttribute('aria-label', this.UIString('Minimum Volume')); - this.listenFor(minButton, 'click', this.handleMinButtonClicked); - - var maxButton = this.controls.maxButton = document.createElement('button'); - maxButton.setAttribute('pseudo', '-webkit-media-controls-volume-max-button'); - maxButton.setAttribute('aria-label', this.UIString('Maximum Volume')); - this.listenFor(maxButton, 'click', this.handleMaxButtonClicked); - - var volumeBox = this.controls.volumeBox = document.createElement('div'); - volumeBox.setAttribute('pseudo', '-webkit-media-controls-volume-slider-container'); - volumeBox.classList.add(this.ClassNames.volumeBox); - - var volumeBoxBackground = this.controls.volumeBoxBackground = document.createElement('div'); - volumeBoxBackground.setAttribute('pseudo', '-webkit-media-controls-volume-slider-container-background'); - - var volumeBoxTint = this.controls.volumeBoxTint = document.createElement('div'); - volumeBoxTint.setAttribute('pseudo', '-webkit-media-controls-volume-slider-container-tint'); - - var volume = this.controls.volume = document.createElement('input'); - volume.setAttribute('pseudo', '-webkit-media-controls-volume-slider'); - volume.setAttribute('aria-label', this.UIString('Volume')); - volume.type = 'range'; - volume.min = 0; - volume.max = 1; - volume.step = .01; - this.listenFor(volume, 'input', this.handleVolumeSliderInput); - this.listenFor(volume, 'mousedown', this.handleVolumeSliderMouseDown); - this.listenFor(volume, 'mouseup', this.handleVolumeSliderMouseUp); - - this.volumeContextName = "_webkit-media-controls-volume-" + this.host.generateUUID(); - volume.style.backgroundImage = '-webkit-canvas(' + this.volumeContextName + ')'; - - var captionButton = this.controls.captionButton = document.createElement('button'); - captionButton.setAttribute('pseudo', '-webkit-media-controls-toggle-closed-captions-button'); - captionButton.setAttribute('aria-label', this.UIString('Captions')); - captionButton.setAttribute('aria-haspopup', 'true'); - captionButton.setAttribute('aria-owns', 'audioAndTextTrackMenu'); - this.listenFor(captionButton, 'click', this.handleCaptionButtonClicked); - - var fullscreenButton = this.controls.fullscreenButton = document.createElement('button'); - fullscreenButton.setAttribute('pseudo', '-webkit-media-controls-fullscreen-button'); - fullscreenButton.setAttribute('aria-label', this.UIString('Display Full Screen')); - this.listenFor(fullscreenButton, 'click', this.handleFullscreenButtonClicked); - - var pictureInPictureButton = this.controls.pictureInPictureButton = document.createElement('button'); - pictureInPictureButton.setAttribute('pseudo', '-webkit-media-controls-picture-in-picture-button'); - pictureInPictureButton.setAttribute('aria-label', this.UIString('Display Picture in Picture')); - pictureInPictureButton.classList.add(this.ClassNames.pictureInPictureButton); - this.listenFor(pictureInPictureButton, 'click', this.handlePictureInPictureButtonClicked); - - var inlinePlaybackPlaceholder = this.controls.inlinePlaybackPlaceholder = document.createElement('div'); - inlinePlaybackPlaceholder.setAttribute('pseudo', '-webkit-media-controls-wireless-playback-status'); - inlinePlaybackPlaceholder.setAttribute('aria-label', this.UIString('Video Playback Placeholder')); - if (!Controller.gSimulatePictureInPictureAvailable) - inlinePlaybackPlaceholder.classList.add(this.ClassNames.hidden); - - var inlinePlaybackPlaceholderText = this.controls.inlinePlaybackPlaceholderText = document.createElement('div'); - inlinePlaybackPlaceholderText.setAttribute('pseudo', '-webkit-media-controls-wireless-playback-text'); - - var inlinePlaybackPlaceholderTextTop = this.controls.inlinePlaybackPlaceholderTextTop = document.createElement('p'); - inlinePlaybackPlaceholderTextTop.setAttribute('pseudo', '-webkit-media-controls-wireless-playback-text-top'); - - var inlinePlaybackPlaceholderTextBottom = this.controls.inlinePlaybackPlaceholderTextBottom = document.createElement('p'); - inlinePlaybackPlaceholderTextBottom.setAttribute('pseudo', '-webkit-media-controls-wireless-playback-text-bottom'); - - var wirelessTargetPicker = this.controls.wirelessTargetPicker = document.createElement('button'); - wirelessTargetPicker.setAttribute('pseudo', '-webkit-media-controls-wireless-playback-picker-button'); - wirelessTargetPicker.setAttribute('aria-label', this.UIString('Choose Wireless Display')); - this.listenFor(wirelessTargetPicker, 'click', this.handleWirelessPickerButtonClicked); - - // Show controls button is an accessibility workaround since the controls are now removed from the DOM. http://webkit.org/b/145684 - var showControlsButton = this.showControlsButton = document.createElement('button'); - showControlsButton.setAttribute('pseudo', '-webkit-media-show-controls'); - showControlsButton.hidden = true; - showControlsButton.setAttribute('aria-label', this.UIString('Show Controls')); - this.listenFor(showControlsButton, 'click', this.handleShowControlsClick); - this.base.appendChild(showControlsButton); - - if (!Controller.gSimulateWirelessPlaybackTarget) - wirelessTargetPicker.classList.add(this.ClassNames.hidden); - }, - - setControlsType: function(type) - { - if (type === this.controlsType) - return; - this.controlsType = type; - - this.reconnectControls(); - this.updateShouldListenForPlaybackTargetAvailabilityEvent(); - }, - - setIsLive: function(live) - { - if (live === this.isLive) - return; - this.isLive = live; - - this.updateStatusDisplay(); - - this.reconnectControls(); - }, - - reconnectControls: function() - { - this.disconnectControls(); - - if (this.controlsType === Controller.InlineControls) - this.configureInlineControls(); - else if (this.controlsType == Controller.FullScreenControls) - this.configureFullScreenControls(); - if (this.shouldHaveControls() || this.currentPlaybackTargetIsWireless()) - this.addControls(); - }, - - disconnectControls: function(event) - { - for (var item in this.controls) { - var control = this.controls[item]; - if (control && control.parentNode) - control.parentNode.removeChild(control); - } - }, - - configureInlineControls: function() - { - this.controls.inlinePlaybackPlaceholder.appendChild(this.controls.inlinePlaybackPlaceholderText); - this.controls.inlinePlaybackPlaceholderText.appendChild(this.controls.inlinePlaybackPlaceholderTextTop); - this.controls.inlinePlaybackPlaceholderText.appendChild(this.controls.inlinePlaybackPlaceholderTextBottom); - this.controls.panel.appendChild(this.controls.panelBackgroundContainer); - this.controls.panelBackgroundContainer.appendChild(this.controls.panelBackground); - this.controls.panelBackgroundContainer.appendChild(this.controls.panelTint); - this.controls.panel.appendChild(this.controls.playButton); - if (!this.isLive) - this.controls.panel.appendChild(this.controls.rewindButton); - this.controls.panel.appendChild(this.controls.statusDisplay); - if (!this.isLive) { - this.controls.panel.appendChild(this.controls.timelineBox); - this.controls.timelineBox.appendChild(this.controls.currentTime); - this.controls.timelineBox.appendChild(this.controls.thumbnailTrack); - this.controls.thumbnailTrack.appendChild(this.controls.timeline); - this.controls.thumbnailTrack.appendChild(this.controls.thumbnail); - this.controls.thumbnail.appendChild(this.controls.thumbnailImage); - this.controls.timelineBox.appendChild(this.controls.remainingTime); - } - this.controls.panel.appendChild(this.controls.muteBox); - this.controls.muteBox.appendChild(this.controls.volumeBox); - this.controls.volumeBox.appendChild(this.controls.volumeBoxBackground); - this.controls.volumeBox.appendChild(this.controls.volumeBoxTint); - this.controls.volumeBox.appendChild(this.controls.volume); - this.controls.muteBox.appendChild(this.controls.muteButton); - this.controls.panel.appendChild(this.controls.wirelessTargetPicker); - this.controls.panel.appendChild(this.controls.captionButton); - if (!this.isAudio()) { - this.updatePictureInPictureButton(); - this.controls.panel.appendChild(this.controls.fullscreenButton); - } - - this.controls.panel.style.removeProperty('left'); - this.controls.panel.style.removeProperty('top'); - this.controls.panel.style.removeProperty('bottom'); - }, - - configureFullScreenControls: function() - { - this.controls.inlinePlaybackPlaceholder.appendChild(this.controls.inlinePlaybackPlaceholderText); - this.controls.inlinePlaybackPlaceholderText.appendChild(this.controls.inlinePlaybackPlaceholderTextTop); - this.controls.inlinePlaybackPlaceholderText.appendChild(this.controls.inlinePlaybackPlaceholderTextBottom); - this.controls.panel.appendChild(this.controls.panelBackground); - this.controls.panel.appendChild(this.controls.panelTint); - this.controls.panel.appendChild(this.controls.volumeBox); - this.controls.volumeBox.appendChild(this.controls.minButton); - this.controls.volumeBox.appendChild(this.controls.volume); - this.controls.volumeBox.appendChild(this.controls.maxButton); - this.controls.panel.appendChild(this.controls.seekBackButton); - this.controls.panel.appendChild(this.controls.playButton); - this.controls.panel.appendChild(this.controls.seekForwardButton); - this.controls.panel.appendChild(this.controls.wirelessTargetPicker); - this.controls.panel.appendChild(this.controls.captionButton); - if (!this.isAudio()) - this.controls.panel.appendChild(this.controls.fullscreenButton); - if (!this.isLive) { - this.controls.panel.appendChild(this.controls.timelineBox); - this.controls.timelineBox.appendChild(this.controls.currentTime); - this.controls.timelineBox.appendChild(this.controls.thumbnailTrack); - this.controls.thumbnailTrack.appendChild(this.controls.timeline); - this.controls.thumbnailTrack.appendChild(this.controls.thumbnail); - this.controls.thumbnail.appendChild(this.controls.thumbnailImage); - this.controls.timelineBox.appendChild(this.controls.remainingTime); - } else - this.controls.panel.appendChild(this.controls.statusDisplay); - }, - - updateControls: function() - { - if (this.isFullScreen()) - this.setControlsType(Controller.FullScreenControls); - else - this.setControlsType(Controller.InlineControls); - - this.setNeedsUpdateForDisplayedWidth(); - this.updateLayoutForDisplayedWidth(); - this.setNeedsTimelineMetricsUpdate(); - - if (this.shouldHaveControls()) { - this.controls.panel.classList.add(this.ClassNames.show); - this.controls.panel.classList.remove(this.ClassNames.hidden); - this.resetHideControlsTimer(); - } else { - this.controls.panel.classList.remove(this.ClassNames.show); - this.controls.panel.classList.add(this.ClassNames.hidden); - } - }, - - isPlayable: function() - { - return this.video.readyState > HTMLMediaElement.HAVE_NOTHING && !this.video.error; - }, - - updateStatusDisplay: function(event) - { - this.updateShouldListenForPlaybackTargetAvailabilityEvent(); - if (this.video.error !== null) - this.controls.statusDisplay.innerText = this.UIString('Error'); - else if (this.isLive && this.video.readyState >= HTMLMediaElement.HAVE_CURRENT_DATA) - this.controls.statusDisplay.innerText = this.UIString('Live Broadcast'); - else if (!this.isPlayable() && this.video.networkState === HTMLMediaElement.NETWORK_LOADING) - this.controls.statusDisplay.innerText = this.UIString('Loading'); - else - this.controls.statusDisplay.innerText = ''; - - this.setStatusHidden(!this.isLive && this.isPlayable()); - }, - - handleLoadStart: function(event) - { - this.updateStatusDisplay(); - this.updateProgress(); - }, - - handleError: function(event) - { - this.updateStatusDisplay(); - }, - - handleAbort: function(event) - { - this.updateStatusDisplay(); - }, - - handleSuspend: function(event) - { - this.updateStatusDisplay(); - }, - - handleStalled: function(event) - { - this.updateStatusDisplay(); - this.updateProgress(); - }, - - handleWaiting: function(event) - { - this.updateStatusDisplay(); - }, - - handleReadyStateChange: function(event) - { - this.updateReadyState(); - this.updateDuration(); - this.updateCaptionButton(); - this.updateCaptionContainer(); - this.updateFullscreenButtons(); - this.updateWirelessTargetAvailable(); - this.updateWirelessTargetPickerButton(); - this.updateProgress(); - this.updateControls(); - }, - - handleTimeUpdate: function(event) - { - if (!this.scrubbing) { - this.updateTime(); - this.updateProgress(); - } - this.drawTimelineBackground(); - }, - - handleDurationChange: function(event) - { - this.updateDuration(); - this.updateTime(); - this.updateProgress(); - }, - - handlePlay: function(event) - { - this.setPlaying(true); - }, - - handlePause: function(event) - { - this.setPlaying(false); - }, - - handleProgress: function(event) - { - this.updateProgress(); - }, - - handleVolumeChange: function(event) - { - this.updateVolume(); - }, - - handleTextTrackChange: function(event) - { - this.updateCaptionContainer(); - }, - - handleTextTrackAdd: function(event) - { - var track = event.track; - - if (this.trackHasThumbnails(track) && track.mode === 'disabled') - track.mode = 'hidden'; - - this.updateThumbnail(); - this.updateCaptionButton(); - this.updateCaptionContainer(); - }, - - handleTextTrackRemove: function(event) - { - this.updateThumbnail(); - this.updateCaptionButton(); - this.updateCaptionContainer(); - }, - - handleAudioTrackChange: function(event) - { - this.updateHasAudio(); - }, - - handleAudioTrackAdd: function(event) - { - this.updateHasAudio(); - this.updateCaptionButton(); - }, - - handleAudioTrackRemove: function(event) - { - this.updateHasAudio(); - this.updateCaptionButton(); - }, - - presentationMode: function() { - if ('webkitPresentationMode' in this.video) - return this.video.webkitPresentationMode; - - if (this.isFullScreen()) - return 'fullscreen'; - - return 'inline'; - }, - - isFullScreen: function() - { - if (!this.video.webkitDisplayingFullscreen) - return false; - - if ('webkitPresentationMode' in this.video && this.video.webkitPresentationMode === 'picture-in-picture') - return false; - - return true; - }, - - updatePictureInPictureButton: function() - { - var shouldShowPictureInPictureButton = Controller.gSimulatePictureInPictureAvailable || ('webkitSupportsPresentationMode' in this.video && this.video.webkitSupportsPresentationMode('picture-in-picture')); - if (shouldShowPictureInPictureButton) { - this.controls.panel.appendChild(this.controls.pictureInPictureButton); - this.controls.pictureInPictureButton.classList.remove(this.ClassNames.hidden); - } else - this.controls.pictureInPictureButton.classList.add(this.ClassNames.hidden); - }, - - handlePresentationModeChange: function(event) - { - var presentationMode = this.presentationMode(); - - switch (presentationMode) { - case 'inline': - this.controls.panel.classList.remove(this.ClassNames.pictureInPicture); - this.controls.inlinePlaybackPlaceholder.classList.add(this.ClassNames.hidden); - this.controls.inlinePlaybackPlaceholder.classList.remove(this.ClassNames.pictureInPicture); - this.controls.inlinePlaybackPlaceholderTextTop.classList.remove(this.ClassNames.pictureInPicture); - this.controls.inlinePlaybackPlaceholderTextBottom.classList.remove(this.ClassNames.pictureInPicture); - - this.controls.pictureInPictureButton.classList.remove(this.ClassNames.returnFromPictureInPicture); - break; - case 'picture-in-picture': - this.controls.panel.classList.add(this.ClassNames.pictureInPicture); - this.controls.inlinePlaybackPlaceholder.classList.add(this.ClassNames.pictureInPicture); - this.controls.inlinePlaybackPlaceholder.classList.remove(this.ClassNames.hidden); - - this.controls.inlinePlaybackPlaceholderTextTop.innerText = this.UIString('This video is playing in Picture in Picture'); - this.controls.inlinePlaybackPlaceholderTextTop.classList.add(this.ClassNames.pictureInPicture); - this.controls.inlinePlaybackPlaceholderTextBottom.innerText = ""; - this.controls.inlinePlaybackPlaceholderTextBottom.classList.add(this.ClassNames.pictureInPicture); - - this.controls.pictureInPictureButton.classList.add(this.ClassNames.returnFromPictureInPicture); - break; - default: - this.controls.panel.classList.remove(this.ClassNames.pictureInPicture); - this.controls.inlinePlaybackPlaceholder.classList.remove(this.ClassNames.pictureInPicture); - this.controls.inlinePlaybackPlaceholderTextTop.classList.remove(this.ClassNames.pictureInPicture); - this.controls.inlinePlaybackPlaceholderTextBottom.classList.remove(this.ClassNames.pictureInPicture); - - this.controls.pictureInPictureButton.classList.remove(this.ClassNames.returnFromPictureInPicture); - break; - } - - this.updateControls(); - this.updateCaptionContainer(); - this.resetHideControlsTimer(); - if (presentationMode != 'fullscreen' && this.video.paused && this.controlsAreHidden()) - this.showControls(); - }, - - handleFullscreenChange: function(event) - { - this.updateBase(); - this.updateControls(); - this.updateFullscreenButtons(); - this.updateWirelessPlaybackStatus(); - - if (this.isFullScreen()) { - this.controls.fullscreenButton.classList.add(this.ClassNames.exit); - this.controls.fullscreenButton.setAttribute('aria-label', this.UIString('Exit Full Screen')); - this.host.enteredFullscreen(); - } else { - this.controls.fullscreenButton.classList.remove(this.ClassNames.exit); - this.controls.fullscreenButton.setAttribute('aria-label', this.UIString('Display Full Screen')); - this.host.exitedFullscreen(); - } - - if ('webkitPresentationMode' in this.video) - this.handlePresentationModeChange(event); - }, - - handleShowControlsClick: function(event) - { - if (!this.video.controls && !this.isFullScreen()) - return; - - if (this.controlsAreHidden()) - this.showControls(true); - }, - - handleWrapperMouseMove: function(event) - { - if (!this.video.controls && !this.isFullScreen()) - return; - - if (this.controlsAreHidden()) - this.showControls(); - this.resetHideControlsTimer(); - - if (!this.isDragging) - return; - var delta = new WebKitPoint(event.clientX - this.initialDragLocation.x, event.clientY - this.initialDragLocation.y); - this.controls.panel.style.left = this.initialOffset.x + delta.x + 'px'; - this.controls.panel.style.top = this.initialOffset.y + delta.y + 'px'; - event.stopPropagation() - }, - - handleWrapperMouseOut: function(event) - { - this.hideControls(); - this.clearHideControlsTimer(); - }, - - handleWrapperMouseUp: function(event) - { - this.isDragging = false; - this.stopListeningFor(this.base, 'mouseup', 'handleWrapperMouseUp', true); - }, - - handlePanelMouseDown: function(event) - { - if (event.target != this.controls.panelTint && event.target != this.controls.inlinePlaybackPlaceholder) - return; - - if (!this.isFullScreen()) - return; - - this.listenFor(this.base, 'mouseup', this.handleWrapperMouseUp, true); - this.isDragging = true; - this.initialDragLocation = new WebKitPoint(event.clientX, event.clientY); - this.initialOffset = new WebKitPoint( - parseInt(this.controls.panel.style.left) | 0, - parseInt(this.controls.panel.style.top) | 0 - ); - }, - - handlePanelTransitionEnd: function(event) - { - var opacity = window.getComputedStyle(this.controls.panel).opacity; - if (!parseInt(opacity) && !this.controlsAlwaysVisible() && (this.video.controls || this.isFullScreen())) { - this.base.removeChild(this.controls.inlinePlaybackPlaceholder); - this.base.removeChild(this.controls.panel); - } - }, - - handlePanelClick: function(event) - { - // Prevent clicks in the panel from playing or pausing the video in a MediaDocument. - event.preventDefault(); - }, - - handlePanelDragStart: function(event) - { - // Prevent drags in the panel from triggering a drag event on the <video> element. - event.preventDefault(); - }, - - handleRewindButtonClicked: function(event) - { - var newTime = Math.max( - this.video.currentTime - this.RewindAmount, - this.video.seekable.start(0)); - this.video.currentTime = newTime; - return true; - }, - - canPlay: function() - { - return this.video.paused || this.video.ended || this.video.readyState < HTMLMediaElement.HAVE_METADATA; - }, - - handlePlayButtonClicked: function(event) - { - if (this.canPlay()) - this.video.play(); - else - this.video.pause(); - return true; - }, - - handleTimelineInput: function(event) - { - if (this.scrubbing) - this.video.pause(); - - this.video.fastSeek(this.controls.timeline.value); - this.updateControlsWhileScrubbing(); - }, - - handleTimelineChange: function(event) - { - this.video.currentTime = this.controls.timeline.value; - this.updateProgress(); - }, - - handleTimelineDown: function(event) - { - this.controls.thumbnail.classList.add(this.ClassNames.show); - }, - - handleTimelineUp: function(event) - { - this.controls.thumbnail.classList.remove(this.ClassNames.show); - }, - - handleTimelineMouseOver: function(event) - { - this.controls.thumbnail.classList.add(this.ClassNames.show); - }, - - handleTimelineMouseOut: function(event) - { - this.controls.thumbnail.classList.remove(this.ClassNames.show); - }, - - handleTimelineMouseMove: function(event) - { - if (this.controls.thumbnail.classList.contains(this.ClassNames.hidden)) - return; - - this.updateTimelineMetricsIfNeeded(); - this.controls.thumbnail.classList.add(this.ClassNames.show); - var localPoint = webkitConvertPointFromPageToNode(this.controls.timeline, new WebKitPoint(event.clientX, event.clientY)); - var percent = (localPoint.x - this.timelineLeft) / this.timelineWidth; - percent = Math.max(Math.min(1, percent), 0); - this.controls.thumbnail.style.left = percent * 100 + '%'; - - var thumbnailTime = percent * this.video.duration; - for (var i = 0; i < this.video.textTracks.length; ++i) { - var track = this.video.textTracks[i]; - if (!this.trackHasThumbnails(track)) - continue; - - if (!track.cues) - continue; - - for (var j = 0; j < track.cues.length; ++j) { - var cue = track.cues[j]; - if (thumbnailTime >= cue.startTime && thumbnailTime < cue.endTime) { - this.controls.thumbnailImage.src = cue.text; - return; - } - } - } - }, - - handleTimelineMouseDown: function(event) - { - this.scrubbing = true; - }, - - handleTimelineMouseUp: function(event) - { - this.scrubbing = false; - }, - - handleMuteButtonClicked: function(event) - { - this.video.muted = !this.video.muted; - if (this.video.muted) - this.controls.muteButton.setAttribute('aria-label', this.UIString('Unmute')); - this.drawVolumeBackground(); - return true; - }, - - handleMuteBoxOver: function(event) - { - this.drawVolumeBackground(); - }, - - handleMinButtonClicked: function(event) - { - if (this.video.muted) { - this.video.muted = false; - this.controls.muteButton.setAttribute('aria-label', this.UIString('Mute')); - } - this.video.volume = 0; - return true; - }, - - handleMaxButtonClicked: function(event) - { - if (this.video.muted) { - this.video.muted = false; - this.controls.muteButton.setAttribute('aria-label', this.UIString('Mute')); - } - this.video.volume = 1; - }, - - handleVolumeSliderInput: function(event) - { - if (this.video.muted) { - this.video.muted = false; - this.controls.muteButton.setAttribute('aria-label', this.UIString('Mute')); - } - this.video.volume = this.controls.volume.value; - this.drawVolumeBackground(); - }, - - handleVolumeSliderMouseDown: function(event) - { - this.isVolumeSliderActive = true; - this.drawVolumeBackground(); - }, - - handleVolumeSliderMouseUp: function(event) - { - this.isVolumeSliderActive = false; - this.drawVolumeBackground(); - }, - - handleCaptionButtonClicked: function(event) - { - if (this.captionMenu) - this.destroyCaptionMenu(); - else - this.buildCaptionMenu(); - return true; - }, - - hasVideo: function() - { - return this.video.videoTracks && this.video.videoTracks.length; - }, - - updateFullscreenButtons: function() - { - var shouldBeHidden = !this.video.webkitSupportsFullscreen || !this.hasVideo(); - this.controls.fullscreenButton.classList.toggle(this.ClassNames.hidden, shouldBeHidden && !this.isFullScreen()); - this.controls.pictureInPictureButton.classList.toggle(this.ClassNames.hidden, shouldBeHidden); - this.setNeedsUpdateForDisplayedWidth(); - this.updateLayoutForDisplayedWidth(); - }, - - handleFullscreenButtonClicked: function(event) - { - if (this.isFullScreen()) - this.video.webkitExitFullscreen(); - else - this.video.webkitEnterFullscreen(); - return true; - }, - - updateWirelessTargetPickerButton: function() { - var wirelessTargetPickerColor; - if (this.controls.wirelessTargetPicker.classList.contains('playing')) - wirelessTargetPickerColor = "-apple-wireless-playback-target-active"; - else - wirelessTargetPickerColor = "rgba(255,255,255,0.45)"; - if (window.devicePixelRatio == 2) - this.controls.wirelessTargetPicker.style.backgroundImage = "url(\"data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 15' stroke='" + wirelessTargetPickerColor + "'><defs> <clipPath fill-rule='evenodd' id='cut-hole'><path d='M 0,0.5 L 16,0.5 L 16,15.5 L 0,15.5 z M 0,14.5 L 16,14.5 L 8,5 z'/></clipPath></defs><rect fill='none' clip-path='url(#cut-hole)' x='0.5' y='2' width='15' height='8'/><path stroke='none' fill='" + wirelessTargetPickerColor +"' d='M 3.5,13.25 L 12.5,13.25 L 8,8 z'/></svg>\")"; - else - this.controls.wirelessTargetPicker.style.backgroundImage = "url(\"data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 15' stroke='" + wirelessTargetPickerColor + "'><defs> <clipPath fill-rule='evenodd' id='cut-hole'><path d='M 0,1 L 16,1 L 16,16 L 0,16 z M 0,15 L 16,15 L 8,5.5 z'/></clipPath></defs><rect fill='none' clip-path='url(#cut-hole)' x='0.5' y='2.5' width='15' height='8'/><path stroke='none' fill='" + wirelessTargetPickerColor +"' d='M 2.75,14 L 13.25,14 L 8,8.75 z'/></svg>\")"; - }, - - handleControlsChange: function() - { - try { - this.updateBase(); - - if (this.shouldHaveControls() && !this.hasControls()) - this.addControls(); - else if (!this.shouldHaveControls() && this.hasControls()) - this.removeControls(); - } catch(e) { - if (window.console) - console.error(e); - } - }, - - nextRate: function() - { - return Math.min(this.MaximumSeekRate, Math.abs(this.video.playbackRate * 2)); - }, - - handleSeekBackMouseDown: function(event) - { - this.actionAfterSeeking = (this.canPlay() ? Controller.PauseAfterSeeking : Controller.PlayAfterSeeking); - this.video.play(); - this.video.playbackRate = this.nextRate() * -1; - this.seekInterval = setInterval(this.seekBackFaster.bind(this), this.SeekDelay); - }, - - seekBackFaster: function() - { - this.video.playbackRate = this.nextRate() * -1; - }, - - handleSeekBackMouseUp: function(event) - { - this.video.playbackRate = this.video.defaultPlaybackRate; - if (this.actionAfterSeeking === Controller.PauseAfterSeeking) - this.video.pause(); - else if (this.actionAfterSeeking === Controller.PlayAfterSeeking) - this.video.play(); - if (this.seekInterval) - clearInterval(this.seekInterval); - }, - - handleSeekForwardMouseDown: function(event) - { - this.actionAfterSeeking = (this.canPlay() ? Controller.PauseAfterSeeking : Controller.PlayAfterSeeking); - this.video.play(); - this.video.playbackRate = this.nextRate(); - this.seekInterval = setInterval(this.seekForwardFaster.bind(this), this.SeekDelay); - }, - - seekForwardFaster: function() - { - this.video.playbackRate = this.nextRate(); - }, - - handleSeekForwardMouseUp: function(event) - { - this.video.playbackRate = this.video.defaultPlaybackRate; - if (this.actionAfterSeeking === Controller.PauseAfterSeeking) - this.video.pause(); - else if (this.actionAfterSeeking === Controller.PlayAfterSeeking) - this.video.play(); - if (this.seekInterval) - clearInterval(this.seekInterval); - }, - - updateDuration: function() - { - var duration = this.video.duration; - this.controls.timeline.min = 0; - this.controls.timeline.max = duration; - - this.setIsLive(duration === Number.POSITIVE_INFINITY); - - // Reset existing style. - this.controls.currentTime.classList.remove(this.ClassNames.threeDigitTime); - this.controls.currentTime.classList.remove(this.ClassNames.fourDigitTime); - this.controls.currentTime.classList.remove(this.ClassNames.fiveDigitTime); - this.controls.currentTime.classList.remove(this.ClassNames.sixDigitTime); - this.controls.remainingTime.classList.remove(this.ClassNames.threeDigitTime); - this.controls.remainingTime.classList.remove(this.ClassNames.fourDigitTime); - this.controls.remainingTime.classList.remove(this.ClassNames.fiveDigitTime); - this.controls.remainingTime.classList.remove(this.ClassNames.sixDigitTime); - - if (duration >= 60*60*10) { - this.controls.currentTime.classList.add(this.ClassNames.sixDigitTime); - this.controls.remainingTime.classList.add(this.ClassNames.sixDigitTime); - } else if (duration >= 60*60) { - this.controls.currentTime.classList.add(this.ClassNames.fiveDigitTime); - this.controls.remainingTime.classList.add(this.ClassNames.fiveDigitTime); - } else if (duration >= 60*10) { - this.controls.currentTime.classList.add(this.ClassNames.fourDigitTime); - this.controls.remainingTime.classList.add(this.ClassNames.fourDigitTime); - } else { - this.controls.currentTime.classList.add(this.ClassNames.threeDigitTime); - this.controls.remainingTime.classList.add(this.ClassNames.threeDigitTime); - } - }, - - progressFillStyle: function(context) - { - var height = this.timelineHeight; - var gradient = context.createLinearGradient(0, 0, 0, height); - gradient.addColorStop(0, 'rgb(2, 2, 2)'); - gradient.addColorStop(1, 'rgb(23, 23, 23)'); - return gradient; - }, - - updateProgress: function() - { - this.updateTimelineMetricsIfNeeded(); - this.drawTimelineBackground(); - }, - - addRoundedRect: function(ctx, x, y, width, height, radius) { - ctx.moveTo(x + radius, y); - ctx.arcTo(x + width, y, x + width, y + radius, radius); - ctx.lineTo(x + width, y + height - radius); - ctx.arcTo(x + width, y + height, x + width - radius, y + height, radius); - ctx.lineTo(x + radius, y + height); - ctx.arcTo(x, y + height, x, y + height - radius, radius); - ctx.lineTo(x, y + radius); - ctx.arcTo(x, y, x + radius, y, radius); - }, - - drawTimelineBackground: function() { - var dpr = window.devicePixelRatio; - var width = this.timelineWidth * dpr; - var height = this.timelineHeight * dpr; - - if (!width || !height) - return; - - var played = this.controls.timeline.value / this.controls.timeline.max; - var buffered = 0; - for (var i = 0, end = this.video.buffered.length; i < end; ++i) - buffered = Math.max(this.video.buffered.end(i), buffered); - - buffered /= this.video.duration; - - var ctx = document.getCSSCanvasContext('2d', this.timelineContextName, width, height); - - width /= dpr; - height /= dpr; - - ctx.save(); - ctx.scale(dpr, dpr); - ctx.clearRect(0, 0, width, height); - - var timelineHeight = 3; - var trackHeight = 1; - var scrubberWidth = 3; - var scrubberHeight = 15; - var borderSize = 2; - var scrubberPosition = Math.max(0, Math.min(width - scrubberWidth, Math.round(width * played))); - - // Draw buffered section. - ctx.save(); - if (this.isAudio()) - ctx.fillStyle = "rgb(71, 71, 71)"; - else - ctx.fillStyle = "rgb(30, 30, 30)"; - ctx.fillRect(1, 8, Math.round(width * buffered) - borderSize, trackHeight); - ctx.restore(); - - // Draw timeline border. - ctx.save(); - ctx.beginPath(); - this.addRoundedRect(ctx, scrubberPosition, 7, width - scrubberPosition, timelineHeight, timelineHeight / 2.0); - this.addRoundedRect(ctx, scrubberPosition + 1, 8, width - scrubberPosition - borderSize , trackHeight, trackHeight / 2.0); - ctx.closePath(); - ctx.clip("evenodd"); - if (this.isAudio()) - ctx.fillStyle = "rgb(71, 71, 71)"; - else - ctx.fillStyle = "rgb(30, 30, 30)"; - ctx.fillRect(0, 0, width, height); - ctx.restore(); - - // Draw played section. - ctx.save(); - ctx.beginPath(); - this.addRoundedRect(ctx, 0, 7, width, timelineHeight, timelineHeight / 2.0); - ctx.closePath(); - ctx.clip(); - if (this.isAudio()) - ctx.fillStyle = "rgb(116, 116, 116)"; - else - ctx.fillStyle = "rgb(75, 75, 75)"; - ctx.fillRect(0, 0, width * played, height); - ctx.restore(); - - // Draw the scrubber. - ctx.save(); - ctx.clearRect(scrubberPosition - 1, 0, scrubberWidth + borderSize, height, 0); - ctx.beginPath(); - this.addRoundedRect(ctx, scrubberPosition, 1, scrubberWidth, scrubberHeight, 1); - ctx.closePath(); - ctx.clip(); - if (this.isAudio()) - ctx.fillStyle = "rgb(181, 181, 181)"; - else - ctx.fillStyle = "rgb(140, 140, 140)"; - ctx.fillRect(0, 0, width, height); - ctx.restore(); - - ctx.restore(); - }, - - drawVolumeBackground: function() { - var dpr = window.devicePixelRatio; - var width = this.controls.volume.offsetWidth * dpr; - var height = this.controls.volume.offsetHeight * dpr; - - if (!width || !height) - return; - - var ctx = document.getCSSCanvasContext('2d', this.volumeContextName, width, height); - - width /= dpr; - height /= dpr; - - ctx.save(); - ctx.scale(dpr, dpr); - ctx.clearRect(0, 0, width, height); - - var seekerPosition = this.controls.volume.value; - var trackHeight = 1; - var timelineHeight = 3; - var scrubberRadius = 3.5; - var scrubberDiameter = 2 * scrubberRadius; - var borderSize = 2; - - var scrubberPosition = Math.round(seekerPosition * (width - scrubberDiameter - borderSize)); - - - // Draw portion of volume under slider thumb. - ctx.save(); - ctx.beginPath(); - this.addRoundedRect(ctx, 0, 3, scrubberPosition + 2, timelineHeight, timelineHeight / 2.0); - ctx.closePath(); - ctx.clip(); - ctx.fillStyle = "rgb(75, 75, 75)"; - ctx.fillRect(0, 0, width, height); - ctx.restore(); - - // Draw portion of volume above slider thumb. - ctx.save(); - ctx.beginPath(); - this.addRoundedRect(ctx, scrubberPosition, 3, width - scrubberPosition, timelineHeight, timelineHeight / 2.0); - ctx.closePath(); - ctx.clip(); - ctx.fillStyle = "rgb(30, 30, 30)"; - ctx.fillRect(0, 0, width, height); - ctx.restore(); - - // Clear a hole in the slider for the scrubber. - ctx.save(); - ctx.beginPath(); - this.addRoundedRect(ctx, scrubberPosition, 0, scrubberDiameter + borderSize, height, (scrubberDiameter + borderSize) / 2.0); - ctx.closePath(); - ctx.clip(); - ctx.clearRect(0, 0, width, height); - ctx.restore(); - - // Draw scrubber. - ctx.save(); - ctx.beginPath(); - this.addRoundedRect(ctx, scrubberPosition + 1, 1, scrubberDiameter, scrubberDiameter, scrubberRadius); - ctx.closePath(); - ctx.clip(); - if (this.isVolumeSliderActive) - ctx.fillStyle = "white"; - else - ctx.fillStyle = "rgb(140, 140, 140)"; - ctx.fillRect(0, 0, width, height); - ctx.restore(); - - ctx.restore(); - }, - - formatTime: function(time) - { - if (isNaN(time)) - time = 0; - var absTime = Math.abs(time); - var intSeconds = Math.floor(absTime % 60).toFixed(0); - var intMinutes = Math.floor((absTime / 60) % 60).toFixed(0); - var intHours = Math.floor(absTime / (60 * 60)).toFixed(0); - var sign = time < 0 ? '-' : String(); - - if (intHours > 0) - return sign + intHours + ':' + String('00' + intMinutes).slice(-2) + ":" + String('00' + intSeconds).slice(-2); - - return sign + String('00' + intMinutes).slice(-2) + ":" + String('00' + intSeconds).slice(-2) - }, - - updatePlaying: function() - { - this.setPlaying(!this.canPlay()); - }, - - setPlaying: function(isPlaying) - { - if (!this.video.controls && !this.isFullScreen()) - return; - - if (this.isPlaying === isPlaying) - return; - this.isPlaying = isPlaying; - - if (!isPlaying) { - this.controls.panel.classList.add(this.ClassNames.paused); - if (this.controls.panelBackground) - this.controls.panelBackground.classList.add(this.ClassNames.paused); - this.controls.playButton.classList.add(this.ClassNames.paused); - this.controls.playButton.setAttribute('aria-label', this.UIString('Play')); - this.showControls(); - } else { - this.controls.panel.classList.remove(this.ClassNames.paused); - if (this.controls.panelBackground) - this.controls.panelBackground.classList.remove(this.ClassNames.paused); - this.controls.playButton.classList.remove(this.ClassNames.paused); - this.controls.playButton.setAttribute('aria-label', this.UIString('Pause')); - this.resetHideControlsTimer(); - } - }, - - updateForShowingControls: function() - { - this.updateLayoutForDisplayedWidth(); - this.setNeedsTimelineMetricsUpdate(); - this.updateTime(); - this.updateProgress(); - this.drawVolumeBackground(); - this.drawTimelineBackground(); - this.controls.panel.classList.add(this.ClassNames.show); - this.controls.panel.classList.remove(this.ClassNames.hidden); - if (this.controls.panelBackground) { - this.controls.panelBackground.classList.add(this.ClassNames.show); - this.controls.panelBackground.classList.remove(this.ClassNames.hidden); - } - }, - - showControls: function(focusControls) - { - this.updateShouldListenForPlaybackTargetAvailabilityEvent(); - if (!this.video.controls && !this.isFullScreen()) - return; - - this.updateForShowingControls(); - if (this.shouldHaveControls() && !this.controls.panel.parentElement) { - this.base.appendChild(this.controls.inlinePlaybackPlaceholder); - this.base.appendChild(this.controls.panel); - if (focusControls) - this.controls.playButton.focus(); - } - this.showControlsButton.hidden = true; - }, - - hideControls: function() - { - if (this.controlsAlwaysVisible()) - return; - - this.clearHideControlsTimer(); - this.updateShouldListenForPlaybackTargetAvailabilityEvent(); - this.controls.panel.classList.remove(this.ClassNames.show); - if (this.controls.panelBackground) - this.controls.panelBackground.classList.remove(this.ClassNames.show); - this.showControlsButton.hidden = false; - }, - - setNeedsUpdateForDisplayedWidth: function() - { - this.currentDisplayWidth = 0; - }, - - scheduleUpdateLayoutForDisplayedWidth: function() - { - setTimeout(this.updateLayoutForDisplayedWidth.bind(this), 0); - }, - - isControlVisible: function(control) - { - if (!control) - return false; - if (!this.root.contains(control)) - return false; - return !control.classList.contains(this.ClassNames.hidden) - }, - - updateLayoutForDisplayedWidth: function() - { - if (!this.controls || !this.controls.panel) - return; - - var visibleWidth = this.controls.panel.getBoundingClientRect().width; - if (this._pageScaleFactor > 1) - visibleWidth *= this._pageScaleFactor; - - if (visibleWidth <= 0 || visibleWidth == this.currentDisplayWidth) - return; - - this.currentDisplayWidth = visibleWidth; - - // Filter all the buttons which are not explicitly hidden. - var buttons = [this.controls.playButton, this.controls.rewindButton, this.controls.captionButton, - this.controls.fullscreenButton, this.controls.pictureInPictureButton, - this.controls.wirelessTargetPicker, this.controls.muteBox]; - var visibleButtons = buttons.filter(this.isControlVisible, this); - - // This tells us how much room we need in order to display every visible button. - var visibleButtonWidth = this.ButtonWidth * visibleButtons.length; - - // Check if there is enough room for the scrubber. - var shouldDropTimeline = (visibleWidth - visibleButtonWidth) < this.MinimumTimelineWidth; - this.controls.timeline.classList.toggle(this.ClassNames.dropped, shouldDropTimeline); - this.controls.currentTime.classList.toggle(this.ClassNames.dropped, shouldDropTimeline); - this.controls.thumbnailTrack.classList.toggle(this.ClassNames.dropped, shouldDropTimeline); - this.controls.remainingTime.classList.toggle(this.ClassNames.dropped, shouldDropTimeline); - - // Then controls in the following order: - var removeOrder = [this.controls.wirelessTargetPicker, this.controls.pictureInPictureButton, - this.controls.captionButton, this.controls.muteBox, this.controls.rewindButton, - this.controls.fullscreenButton]; - removeOrder.forEach(function(control) { - var shouldDropControl = visibleWidth < visibleButtonWidth && this.isControlVisible(control); - control.classList.toggle(this.ClassNames.dropped, shouldDropControl); - if (shouldDropControl) - visibleButtonWidth -= this.ButtonWidth; - }, this); - }, - - controlsAlwaysVisible: function() - { - if (this.presentationMode() === 'picture-in-picture') - return true; - - return this.isAudio() || this.currentPlaybackTargetIsWireless() || this.scrubbing; - }, - - controlsAreHidden: function() - { - return !this.controlsAlwaysVisible() && !this.controls.panel.classList.contains(this.ClassNames.show) && !this.controls.panel.parentElement; - }, - - removeControls: function() - { - if (this.controls.panel.parentNode) - this.controls.panel.parentNode.removeChild(this.controls.panel); - this.destroyCaptionMenu(); - }, - - addControls: function() - { - this.base.appendChild(this.controls.inlinePlaybackPlaceholder); - this.base.appendChild(this.controls.panel); - this.updateControls(); - }, - - hasControls: function() - { - return this.controls.panel.parentElement; - }, - - updateTime: function() - { - var currentTime = this.video.currentTime; - var timeRemaining = currentTime - this.video.duration; - this.controls.currentTime.innerText = this.formatTime(currentTime); - this.controls.timeline.value = this.video.currentTime; - this.controls.remainingTime.innerText = this.formatTime(timeRemaining); - }, - - updateControlsWhileScrubbing: function() - { - if (!this.scrubbing) - return; - - var currentTime = (this.controls.timeline.value / this.controls.timeline.max) * this.video.duration; - var timeRemaining = currentTime - this.video.duration; - this.controls.currentTime.innerText = this.formatTime(currentTime); - this.controls.remainingTime.innerText = this.formatTime(timeRemaining); - this.drawTimelineBackground(); - }, - - updateReadyState: function() - { - this.updateStatusDisplay(); - }, - - setStatusHidden: function(hidden) - { - if (this.statusHidden === hidden) - return; - - this.statusHidden = hidden; - - if (hidden) { - this.controls.statusDisplay.classList.add(this.ClassNames.hidden); - this.controls.currentTime.classList.remove(this.ClassNames.hidden); - this.controls.timeline.classList.remove(this.ClassNames.hidden); - this.controls.remainingTime.classList.remove(this.ClassNames.hidden); - this.setNeedsTimelineMetricsUpdate(); - this.showControls(); - } else { - this.controls.statusDisplay.classList.remove(this.ClassNames.hidden); - this.controls.currentTime.classList.add(this.ClassNames.hidden); - this.controls.timeline.classList.add(this.ClassNames.hidden); - this.controls.remainingTime.classList.add(this.ClassNames.hidden); - this.hideControls(); - } - this.updateWirelessTargetAvailable(); - }, - - trackHasThumbnails: function(track) - { - return track.kind === 'thumbnails' || (track.kind === 'metadata' && track.label === 'thumbnails'); - }, - - updateThumbnail: function() - { - for (var i = 0; i < this.video.textTracks.length; ++i) { - var track = this.video.textTracks[i]; - if (this.trackHasThumbnails(track)) { - this.controls.thumbnail.classList.remove(this.ClassNames.hidden); - return; - } - } - - this.controls.thumbnail.classList.add(this.ClassNames.hidden); - }, - - updateCaptionButton: function() - { - if (this.video.webkitHasClosedCaptions || this.video.audioTracks.length > 1) - this.controls.captionButton.classList.remove(this.ClassNames.hidden); - else - this.controls.captionButton.classList.add(this.ClassNames.hidden); - this.setNeedsUpdateForDisplayedWidth(); - this.updateLayoutForDisplayedWidth(); - }, - - updateCaptionContainer: function() - { - if (!this.host.textTrackContainer) - return; - - var hasClosedCaptions = this.video.webkitHasClosedCaptions; - var hasHiddenClass = this.host.textTrackContainer.classList.contains(this.ClassNames.hidden); - - if (hasClosedCaptions && hasHiddenClass) - this.host.textTrackContainer.classList.remove(this.ClassNames.hidden); - else if (!hasClosedCaptions && !hasHiddenClass) - this.host.textTrackContainer.classList.add(this.ClassNames.hidden); - - this.updateBase(); - this.host.updateTextTrackContainer(); - }, - - buildCaptionMenu: function() - { - var audioTracks = this.host.sortedTrackListForMenu(this.video.audioTracks); - var textTracks = this.host.sortedTrackListForMenu(this.video.textTracks); - - if ((!textTracks || !textTracks.length) && (!audioTracks || !audioTracks.length)) - return; - - this.captionMenu = document.createElement('div'); - this.captionMenu.setAttribute('pseudo', '-webkit-media-controls-closed-captions-container'); - this.captionMenu.setAttribute('id', 'audioAndTextTrackMenu'); - this.base.appendChild(this.captionMenu); - this.captionMenuItems = []; - - var offItem = this.host.captionMenuOffItem; - var automaticItem = this.host.captionMenuAutomaticItem; - var displayMode = this.host.captionDisplayMode; - - var list = document.createElement('div'); - this.captionMenu.appendChild(list); - list.classList.add(this.ClassNames.list); - - if (audioTracks && audioTracks.length > 1) { - var heading = document.createElement('h3'); - heading.id = 'webkitMediaControlsAudioTrackHeading'; // for AX menu label - list.appendChild(heading); - heading.innerText = this.UIString('Audio'); - - var ul = document.createElement('ul'); - ul.setAttribute('role', 'menu'); - ul.setAttribute('aria-labelledby', 'webkitMediaControlsAudioTrackHeading'); - list.appendChild(ul); - - for (var i = 0; i < audioTracks.length; ++i) { - var menuItem = document.createElement('li'); - menuItem.setAttribute('role', 'menuitemradio'); - menuItem.setAttribute('tabindex', '-1'); - this.captionMenuItems.push(menuItem); - this.listenFor(menuItem, 'click', this.audioTrackItemSelected); - this.listenFor(menuItem, 'keyup', this.handleAudioTrackItemKeyUp); - ul.appendChild(menuItem); - - var track = audioTracks[i]; - menuItem.innerText = this.host.displayNameForTrack(track); - menuItem.track = track; - - var itemCheckmark = document.createElement("img"); - itemCheckmark.classList.add("checkmark-container"); - menuItem.insertBefore(itemCheckmark, menuItem.firstChild); - - if (track.enabled) { - menuItem.classList.add(this.ClassNames.selected); - menuItem.setAttribute('tabindex', '0'); - menuItem.setAttribute('aria-checked', 'true'); - } - } - } - - if (textTracks && textTracks.length > 2) { - var heading = document.createElement('h3'); - heading.id = 'webkitMediaControlsClosedCaptionsHeading'; // for AX menu label - list.appendChild(heading); - heading.innerText = this.UIString('Subtitles'); - - var ul = document.createElement('ul'); - ul.setAttribute('role', 'menu'); - ul.setAttribute('aria-labelledby', 'webkitMediaControlsClosedCaptionsHeading'); - list.appendChild(ul); - - for (var i = 0; i < textTracks.length; ++i) { - var menuItem = document.createElement('li'); - menuItem.setAttribute('role', 'menuitemradio'); - menuItem.setAttribute('tabindex', '-1'); - this.captionMenuItems.push(menuItem); - this.listenFor(menuItem, 'click', this.captionItemSelected); - this.listenFor(menuItem, 'keyup', this.handleCaptionItemKeyUp); - ul.appendChild(menuItem); - - var track = textTracks[i]; - menuItem.innerText = this.host.displayNameForTrack(track); - menuItem.track = track; - - var itemCheckmark = document.createElement("img"); - itemCheckmark.classList.add("checkmark-container"); - menuItem.insertBefore(itemCheckmark, menuItem.firstChild); - - if (track === offItem) { - var offMenu = menuItem; - continue; - } - - if (track === automaticItem) { - if (displayMode === 'automatic') { - menuItem.classList.add(this.ClassNames.selected); - menuItem.setAttribute('tabindex', '0'); - menuItem.setAttribute('aria-checked', 'true'); - } - continue; - } - - if (displayMode != 'automatic' && track.mode === 'showing') { - var trackMenuItemSelected = true; - menuItem.classList.add(this.ClassNames.selected); - menuItem.setAttribute('tabindex', '0'); - menuItem.setAttribute('aria-checked', 'true'); - } - - } - - if (offMenu && (displayMode === 'forced-only' || displayMode === 'manual') && !trackMenuItemSelected) { - offMenu.classList.add(this.ClassNames.selected); - offMenu.setAttribute('tabindex', '0'); - offMenu.setAttribute('aria-checked', 'true'); - } - } - - // focus first selected menuitem - for (var i = 0, c = this.captionMenuItems.length; i < c; i++) { - var item = this.captionMenuItems[i]; - if (item.classList.contains(this.ClassNames.selected)) { - item.focus(); - break; - } - } - - }, - - captionItemSelected: function(event) - { - this.host.setSelectedTextTrack(event.target.track); - this.destroyCaptionMenu(); - }, - - focusSiblingCaptionItem: function(event) - { - var currentItem = event.target; - var pendingItem = false; - switch(event.keyCode) { - case this.KeyCodes.left: - case this.KeyCodes.up: - pendingItem = currentItem.previousSibling; - break; - case this.KeyCodes.right: - case this.KeyCodes.down: - pendingItem = currentItem.nextSibling; - break; - } - if (pendingItem) { - currentItem.setAttribute('tabindex', '-1'); - pendingItem.setAttribute('tabindex', '0'); - pendingItem.focus(); - } - }, - - handleCaptionItemKeyUp: function(event) - { - switch (event.keyCode) { - case this.KeyCodes.enter: - case this.KeyCodes.space: - this.captionItemSelected(event); - break; - case this.KeyCodes.escape: - this.destroyCaptionMenu(); - break; - case this.KeyCodes.left: - case this.KeyCodes.up: - case this.KeyCodes.right: - case this.KeyCodes.down: - this.focusSiblingCaptionItem(event); - break; - default: - return; - } - // handled - event.stopPropagation(); - event.preventDefault(); - }, - - audioTrackItemSelected: function(event) - { - for (var i = 0; i < this.video.audioTracks.length; ++i) { - var track = this.video.audioTracks[i]; - track.enabled = (track == event.target.track); - } - - this.destroyCaptionMenu(); - }, - - focusSiblingAudioTrackItem: function(event) - { - var currentItem = event.target; - var pendingItem = false; - switch(event.keyCode) { - case this.KeyCodes.left: - case this.KeyCodes.up: - pendingItem = currentItem.previousSibling; - break; - case this.KeyCodes.right: - case this.KeyCodes.down: - pendingItem = currentItem.nextSibling; - break; - } - if (pendingItem) { - currentItem.setAttribute('tabindex', '-1'); - pendingItem.setAttribute('tabindex', '0'); - pendingItem.focus(); - } - }, - - handleAudioTrackItemKeyUp: function(event) - { - switch (event.keyCode) { - case this.KeyCodes.enter: - case this.KeyCodes.space: - this.audioTrackItemSelected(event); - break; - case this.KeyCodes.escape: - this.destroyCaptionMenu(); - break; - case this.KeyCodes.left: - case this.KeyCodes.up: - case this.KeyCodes.right: - case this.KeyCodes.down: - this.focusSiblingAudioTrackItem(event); - break; - default: - return; - } - // handled - event.stopPropagation(); - event.preventDefault(); - }, - - destroyCaptionMenu: function() - { - if (!this.captionMenu) - return; - - this.captionMenuItems.forEach(function(item){ - this.stopListeningFor(item, 'click', this.captionItemSelected); - this.stopListeningFor(item, 'keyup', this.handleCaptionItemKeyUp); - }, this); - - // FKA and AX: focus the trigger before destroying the element with focus - if (this.controls.captionButton) - this.controls.captionButton.focus(); - - if (this.captionMenu.parentNode) - this.captionMenu.parentNode.removeChild(this.captionMenu); - delete this.captionMenu; - delete this.captionMenuItems; - }, - - updateHasAudio: function() - { - if (this.video.audioTracks.length && !this.currentPlaybackTargetIsWireless()) - this.controls.muteBox.classList.remove(this.ClassNames.hidden); - else - this.controls.muteBox.classList.add(this.ClassNames.hidden); - - this.setNeedsUpdateForDisplayedWidth(); - this.updateLayoutForDisplayedWidth(); - }, - - updateHasVideo: function() - { - if (this.hasVideo()) - this.controls.panel.classList.remove(this.ClassNames.noVideo); - else - this.controls.panel.classList.add(this.ClassNames.noVideo); - }, - - updateVolume: function() - { - if (this.video.muted || !this.video.volume) { - this.controls.muteButton.classList.add(this.ClassNames.muted); - this.controls.volume.value = 0; - } else { - this.controls.muteButton.classList.remove(this.ClassNames.muted); - this.controls.volume.value = this.video.volume; - } - this.drawVolumeBackground(); - }, - - isAudio: function() - { - return this.video instanceof HTMLAudioElement; - }, - - clearHideControlsTimer: function() - { - if (this.hideTimer) - clearTimeout(this.hideTimer); - this.hideTimer = null; - }, - - resetHideControlsTimer: function() - { - if (this.hideTimer) { - clearTimeout(this.hideTimer); - this.hideTimer = null; - } - - if (this.isPlaying) - this.hideTimer = setTimeout(this.hideControls.bind(this), this.HideControlsDelay); - }, - - handlePictureInPictureButtonClicked: function(event) { - if (!('webkitSetPresentationMode' in this.video)) - return; - - if (this.presentationMode() === 'picture-in-picture') - this.video.webkitSetPresentationMode('inline'); - else - this.video.webkitSetPresentationMode('picture-in-picture'); - }, - - currentPlaybackTargetIsWireless: function() { - if (Controller.gSimulateWirelessPlaybackTarget) - return true; - - if (!this.currentTargetIsWireless || this.wirelessPlaybackDisabled) - return false; - - return true; - }, - - updateShouldListenForPlaybackTargetAvailabilityEvent: function() { - var shouldListen = true; - if (this.video.error) - shouldListen = false; - if (!this.isAudio() && !this.video.paused && this.controlsAreHidden()) - shouldListen = false; - if (document.hidden) - shouldListen = false; - - this.setShouldListenForPlaybackTargetAvailabilityEvent(shouldListen); - }, - - updateWirelessPlaybackStatus: function() { - if (this.currentPlaybackTargetIsWireless()) { - var deviceName = ""; - var deviceType = ""; - var type = this.host.externalDeviceType; - if (type == "airplay") { - deviceType = this.UIString('##WIRELESS_PLAYBACK_DEVICE_TYPE##'); - deviceName = this.UIString('##WIRELESS_PLAYBACK_DEVICE_NAME##', '##DEVICE_NAME##', this.host.externalDeviceDisplayName || "Apple TV"); - } else if (type == "tvout") { - deviceType = this.UIString('##TVOUT_DEVICE_TYPE##'); - deviceName = this.UIString('##TVOUT_DEVICE_NAME##'); - } - - this.controls.inlinePlaybackPlaceholderTextTop.innerText = deviceType; - this.controls.inlinePlaybackPlaceholderTextBottom.innerText = deviceName; - this.controls.inlinePlaybackPlaceholder.setAttribute('aria-label', deviceType + ", " + deviceName); - this.controls.inlinePlaybackPlaceholder.classList.remove(this.ClassNames.hidden); - this.controls.wirelessTargetPicker.classList.add(this.ClassNames.playing); - if (!this.isFullScreen() && (this.video.offsetWidth <= 250 || this.video.offsetHeight <= 200)) { - this.controls.inlinePlaybackPlaceholder.classList.add(this.ClassNames.small); - this.controls.inlinePlaybackPlaceholderTextTop.classList.add(this.ClassNames.small); - this.controls.inlinePlaybackPlaceholderTextBottom.classList.add(this.ClassNames.small); - } else { - this.controls.inlinePlaybackPlaceholder.classList.remove(this.ClassNames.small); - this.controls.inlinePlaybackPlaceholderTextTop.classList.remove(this.ClassNames.small); - this.controls.inlinePlaybackPlaceholderTextBottom.classList.remove(this.ClassNames.small); - } - this.controls.volumeBox.classList.add(this.ClassNames.hidden); - this.controls.muteBox.classList.add(this.ClassNames.hidden); - this.updateBase(); - this.showControls(); - } else { - this.controls.inlinePlaybackPlaceholder.classList.add(this.ClassNames.hidden); - this.controls.wirelessTargetPicker.classList.remove(this.ClassNames.playing); - this.controls.volumeBox.classList.remove(this.ClassNames.hidden); - this.controls.muteBox.classList.remove(this.ClassNames.hidden); - } - this.setNeedsUpdateForDisplayedWidth(); - this.updateLayoutForDisplayedWidth(); - this.reconnectControls(); - this.updateWirelessTargetPickerButton(); - }, - - updateWirelessTargetAvailable: function() { - this.currentTargetIsWireless = this.video.webkitCurrentPlaybackTargetIsWireless; - this.wirelessPlaybackDisabled = this.video.webkitWirelessVideoPlaybackDisabled; - - var wirelessPlaybackTargetsAvailable = Controller.gSimulateWirelessPlaybackTarget || this.hasWirelessPlaybackTargets; - if (this.wirelessPlaybackDisabled) - wirelessPlaybackTargetsAvailable = false; - - if (wirelessPlaybackTargetsAvailable && this.isPlayable()) - this.controls.wirelessTargetPicker.classList.remove(this.ClassNames.hidden); - else - this.controls.wirelessTargetPicker.classList.add(this.ClassNames.hidden); - this.setNeedsUpdateForDisplayedWidth(); - this.updateLayoutForDisplayedWidth(); - }, - - handleWirelessPickerButtonClicked: function(event) - { - this.video.webkitShowPlaybackTargetPicker(); - return true; - }, - - handleWirelessPlaybackChange: function(event) { - this.updateWirelessTargetAvailable(); - this.updateWirelessPlaybackStatus(); - this.setNeedsTimelineMetricsUpdate(); - }, - - handleWirelessTargetAvailableChange: function(event) { - var wirelessPlaybackTargetsAvailable = event.availability == "available"; - if (this.hasWirelessPlaybackTargets === wirelessPlaybackTargetsAvailable) - return; - - this.hasWirelessPlaybackTargets = wirelessPlaybackTargetsAvailable; - this.updateWirelessTargetAvailable(); - this.setNeedsTimelineMetricsUpdate(); - }, - - setShouldListenForPlaybackTargetAvailabilityEvent: function(shouldListen) { - if (!window.WebKitPlaybackTargetAvailabilityEvent || this.isListeningForPlaybackTargetAvailabilityEvent == shouldListen) - return; - - if (shouldListen && this.video.error) - return; - - this.isListeningForPlaybackTargetAvailabilityEvent = shouldListen; - if (shouldListen) - this.listenFor(this.video, 'webkitplaybacktargetavailabilitychanged', this.handleWirelessTargetAvailableChange); - else - this.stopListeningFor(this.video, 'webkitplaybacktargetavailabilitychanged', this.handleWirelessTargetAvailableChange); - }, - - get scrubbing() - { - return this._scrubbing; - }, - - set scrubbing(flag) - { - if (this._scrubbing == flag) - return; - this._scrubbing = flag; - - if (this._scrubbing) - this.wasPlayingWhenScrubbingStarted = !this.video.paused; - else if (this.wasPlayingWhenScrubbingStarted && this.video.paused) { - this.video.play(); - this.resetHideControlsTimer(); - } - }, - - get pageScaleFactor() - { - return this._pageScaleFactor; - }, - - set pageScaleFactor(newScaleFactor) - { - if (this._pageScaleFactor === newScaleFactor) - return; - - this._pageScaleFactor = newScaleFactor; - }, - - handleRootResize: function(event) - { - this.updateLayoutForDisplayedWidth(); - this.setNeedsTimelineMetricsUpdate(); - this.updateTimelineMetricsIfNeeded(); - this.drawTimelineBackground(); - }, - - getCurrentControlsStatus: function () - { - var result = { - idiom: this.idiom, - status: "ok" - }; - - var elements = [ - { - name: "Show Controls", - object: this.showControlsButton, - extraProperties: ["hidden"] - }, - { - name: "Status Display", - object: this.controls.statusDisplay, - styleValues: ["display"], - extraProperties: ["textContent"] - }, - { - name: "Play Button", - object: this.controls.playButton - }, - { - name: "Rewind Button", - object: this.controls.rewindButton - }, - { - name: "Timeline Box", - object: this.controls.timelineBox - }, - { - name: "Mute Box", - object: this.controls.muteBox - }, - { - name: "Fullscreen Button", - object: this.controls.fullscreenButton - }, - { - name: "AppleTV Device Picker", - object: this.controls.wirelessTargetPicker, - styleValues: ["display"], - extraProperties: ["hidden"], - }, - { - name: "Picture-in-picture Button", - object: this.controls.pictureInPictureButton - }, - { - name: "Track Menu", - object: this.captionMenu - }, - ]; - - elements.forEach(function (element) { - var obj = element.object; - delete element.object; - - element.computedStyle = {}; - if (obj && element.styleValues) { - var computedStyle = window.getComputedStyle(obj); - element.styleValues.forEach(function (propertyName) { - element.computedStyle[propertyName] = computedStyle[propertyName]; - }); - delete element.styleValues; - } - - element.bounds = obj ? obj.getBoundingClientRect() : null; - element.className = obj ? obj.className : null; - element.ariaLabel = obj ? obj.getAttribute('aria-label') : null; - - if (element.extraProperties) { - element.extraProperties.forEach(function (property) { - element[property] = obj ? obj[property] : null; - }); - delete element.extraProperties; - } - - element.element = obj; - }); - - result.elements = elements; - - return JSON.stringify(result); - } - -}; diff --git a/Source/WebCore/Modules/mediacontrols/mediaControlsBase.css b/Source/WebCore/Modules/mediacontrols/mediaControlsBase.css deleted file mode 100644 index 61cf47e89..000000000 --- a/Source/WebCore/Modules/mediacontrols/mediaControlsBase.css +++ /dev/null @@ -1,758 +0,0 @@ -/* - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -audio { - width: 200px; - height: 25px; -} - -body:-webkit-full-page-media { - background-color: rgb(38, 38, 38); -} - -video:-webkit-full-page-media { - margin: auto; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; -} - -video:-webkit-full-page-media::-webkit-media-controls-panel { - bottom: 0px; -} - -video:-webkit-full-page-media::-webkit-media-controls-panel.no-video { - opacity: 1; -} - -::-webkit-media-controls { - width: inherit; - height: inherit; - position: relative; - display: -webkit-flex; - -webkit-align-items: stretch; - -webkit-justify-content: flex-end; - -webkit-flex-direction: column; -} - -video::-webkit-media-text-track-container, -audio::-webkit-media-text-track-container { - position: relative; - -webkit-flex: 1 1 auto; -} - -video::-webkit-media-controls-panel-composited-parent { - -webkit-transform: translateZ(0); - width: 100%; -} - -video::-webkit-media-controls-panel, -audio::-webkit-media-controls-panel { - box-sizing: border-box; - position: relative; - bottom: 0; - width: 100%; - padding-top: 1px; - min-height: 25px; - height: 25px; - line-height: 25px; - -webkit-user-select: none; - background-color: transparent; - background-image: -webkit-linear-gradient(top, - rgba(0, 0, 0, .92) 0, - rgba(0, 0, 0, .92) 1px, - rgba(89, 89, 89, .92) 1px, - rgba(89, 89, 89, .92) 2px, - rgba(60, 60, 60, .92) 2px, - rgba(35, 35, 35, .92) 12px, - rgba(30, 30, 30, .92) 12px, - rgba(30, 30, 30, .92) 13px, - rgba(25, 25, 25, .92) 13px, - rgba(17, 17, 17, .92) 100% - ); - - display: -webkit-flex; - -webkit-flex-direction: row; - -webkit-align-items: center; - -webkit-user-select: none; - - direction: ltr; - - transition: opacity 0.25s linear; -} - -video::-webkit-media-controls-panel { - cursor: none; - opacity: 0; -} - -video::-webkit-media-controls-panel.show, -video::-webkit-media-controls-panel.paused, -video::-webkit-media-controls-panel:hover { - cursor: inherit; - opacity: 1; -} - -video::-webkit-media-controls-panel button, -audio::-webkit-media-controls-panel button { - -webkit-appearance: none; - display: block; - padding: 0; - border: 0; - height: 16px; - width: 16px; - background-color: transparent; - color: white; - background-origin: content-box; - background-repeat: no-repeat; - background-position: center; - -webkit-filter: drop-shadow(black 0 1px 1px); -} - -video::-webkit-media-controls-panel button:active, -audio::-webkit-media-controls-panel button:active { - -webkit-filter: drop-shadow(white 0 0 10px); -} - -video::-webkit-media-controls-rewind-button, -audio::-webkit-media-controls-rewind-button { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 17"><linearGradient id="gradient" x2="0" y2="100%" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="rgb(216, 216, 216)"/><stop offset="0.44444" stop-color="rgb(216, 216, 216)"/><stop offset="0.44444" stop-color="rgb(208, 208, 208)"/><stop offset="0.55555" stop-color="rgb(208, 208, 208)"/><stop offset="0.55555" stop-color="rgb(200, 200, 200)"/><stop offset="1" stop-color="rgb(208, 208, 208)"/></linearGradient><path d="m 7.9131,2 0,-1.548 -2.586,2.155 0,-2.171 -2.582,2.208 2.582,2.175 0,-2.139 2.586,2.155 0,-1.276 c 3.138,0.129 5.491,2.681 5.543,5.838 l -1.031,0 0.016,0.215 1.015,0 c -0.06,3.19 -2.629,5.765 -5.819,5.833 l 0,-1.018 -0.214,0 0,1.021 c -3.21,-0.047 -5.801,-2.631 -5.862,-5.836 l 1.045,0 -0.016,-0.215 -1.045,0 c -0.052,-0.288 -0.318,-0.654 -0.766,-0.654 -0.538,0 -0.755,0.484 -0.755,0.75 0,4.146 3.331,7.506 7.476,7.506 4.146,0 7.506,-3.36 7.506,-7.506 0,-4.059 -3.066,-7.357 -7.093,-7.493" fill="url(#gradient)"/><path d="m 5.1729,11.0518 c -0.38,0 -0.668,-0.129 -0.945,-0.366 -0.083,-0.071 -0.186,-0.134 -0.338,-0.134 -0.277,0 -0.511,0.238 -0.511,0.521 0,0.154 0.083,0.301 0.179,0.383 0.394,0.346 0.911,0.563 1.601,0.563 1.077,0 1.739,-0.681 1.739,-1.608 l 0,-0.013 c 0,-0.911 -0.641,-1.265 -1.296,-1.376 l 0.945,-0.919 c 0.193,-0.19 0.317,-0.337 0.317,-0.604 0,-0.294 -0.228,-0.477 -0.538,-0.477 l -2.354,0 c -0.248,0 -0.455,0.21 -0.455,0.464 0,0.253 0.207,0.463 0.455,0.463 l 1.485,0 -0.939,0.961 c -0.166,0.169 -0.228,0.295 -0.228,0.444 0,0.25 0.207,0.463 0.455,0.463 l 0.166,0 c 0.594,0 0.945,0.222 0.945,0.624 l 0,0.012 c 0,0.367 -0.282,0.599 -0.683,0.599" fill="url(#gradient)"/><path d="m 10.354,9.5342 c 0,0.876 -0.379,1.525 -0.979,1.525 -0.599,0 -0.992,-0.655 -0.992,-1.539 l 0,-0.012 c 0,-0.884 0.388,-1.527 0.979,-1.527 0.592,0 0.992,0.663 0.992,1.539 l 0,0.014 z m -0.979,-2.512 c -1.197,0 -2.008,1.097 -2.008,2.498 l 0,0.014 c 0,1.401 0.792,2.484 1.995,2.484 1.205,0 2.01,-1.097 2.01,-2.498 l 0,-0.012 c 0,-1.402 -0.805,-2.486 -1.997,-2.486" fill="url(#gradient)"/></svg>'); - width: 16px; - height: 18px; - margin-bottom: 1px; - margin-left: 6px; - margin-right: 4px; -} - -video::-webkit-media-controls-play-button, -audio::-webkit-media-controls-play-button { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 15"><linearGradient id="gradient" x2="0" y2="100%" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="rgb(216, 216, 216)"/><stop offset="0.4375" stop-color="rgb(216, 216, 216)"/><stop offset="0.4375" stop-color="rgb(208, 208, 208)"/><stop offset="0.5" stop-color="rgb(208, 208, 208)"/><stop offset="0.5" stop-color="rgb(200, 200, 200)"/><stop offset="1" stop-color="rgb(208, 208, 208)"/></linearGradient><path d="M 0,0 v 16 h 6 v -16 h -6 z" fill="url(#gradient)"/><path d="M 9,0 v 16 h 6 v -16 h -6 z" fill="url(#gradient)"/></svg>'); - margin-left: 6px; - margin-right: 1px; -} - -video::-webkit-media-controls-play-button.paused, -audio::-webkit-media-controls-play-button.paused { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 15"><linearGradient id="gradient" x2="0" y2="100%" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="rgb(216, 216, 216)"/><stop offset="0.4375" stop-color="rgb(216, 216, 216)"/><stop offset="0.4375" stop-color="rgb(208, 208, 208)"/><stop offset="0.5" stop-color="rgb(208, 208, 208)"/><stop offset="0.5" stop-color="rgb(200, 200, 200)"/><stop offset="1" stop-color="rgb(208, 208, 208)"/></linearGradient><path d="M 0,0 15,7 0,15 z" fill="url(#gradient)"/></svg>'); -} - -video::-webkit-media-controls-panel .mute-box, -audio::-webkit-media-controls-panel .mute-box { - width: 22px; - height: 22px; - margin-right: 2px; - - position: relative; - display: -webkit-flex; - -webkit-flex-direction: column; - -webkit-justify-content: center; - -webkit-align-items: center; -} - -video::-webkit-media-controls-mute-button, -audio::-webkit-media-controls-mute-button, -video::-webkit-media-controls-volume-max-button { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 15"><linearGradient id="gradient" x2="0" y2="100%" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="rgb(216, 216, 216)"/><stop offset="0.4375" stop-color="rgb(216, 216, 216)"/><stop offset="0.4375" stop-color="rgb(208, 208, 208)"/><stop offset="0.5" stop-color="rgb(208, 208, 208)"/><stop offset="0.5" stop-color="rgb(200, 200, 200)"/><stop offset="1" stop-color="rgb(208, 208, 208)"/></linearGradient><path d="m 0,9 0,-4 3,0 3,-3 0,10 -3,-3 -3,0 z" style="fill:url(#gradient) "/><path d="m 10.449,1.087 c 1.963,1.055 3.322,3.291 3.322,5.881 0,2.642 -1.402,4.913 -3.424,5.945" style="fill:none;stroke:url(#gradient);stroke-width:1.25;stroke-linecap:round;"/><path d="m 9.13,3.134 c 1.289,0.681 2.181,2.142 2.181,3.835 0,1.743001 -0.939,3.24 -2.285,3.897" style="fill:none;stroke:url(#gradient);stroke-width:1.25;stroke-linecap:round;"/><path d="M 7.794,5.175 C 8.403001,5.491 8.827001,6.167 8.827001,6.971 8.827001,7.818 8.356,8.537001 7.688,8.826" style="fill:none;stroke:url(#gradient);stroke-width:1.25;stroke-linecap:round;"/></svg>'); - width: 14px; -} - -video::-webkit-media-controls-panel .volume-box, -audio::-webkit-media-controls-panel .volume-box { - position: absolute; - box-sizing: border-box; - height: 22px; - bottom: 0; - left: 0; - - -webkit-transform: rotate(-90deg); - -webkit-transform-origin: 11px 11px; - - background-color: transparent; - background-image: -webkit-linear-gradient( - left, - rgba(17, 17, 17, 0.92), - rgba(42, 42, 42, 0.92) - ); - border: 1px solid rgba(0, 0, 0, 0.95); - border-radius: 12px; - - display: -webkit-flex; - -webkit-flex-direction: row; - -webkit-align-items: center; - -webkit-justify-content: flex-end; - - opacity: 0; - /* make zero width (rather than display:none) for AX and FKA */ - width: 0; /* will become 114px when shown */ - -} - -/* FIXME: needs CSS4 !subject selector to show when slider inside .volume-box is focused */ -video::-webkit-media-controls-panel .mute-box:hover .volume-box, -video::-webkit-media-controls-panel .volume-box:hover, -video::-webkit-media-controls-panel .volume-box:active, -audio::-webkit-media-controls-panel .mute-box:hover .volume-box, -audio::-webkit-media-controls-panel .volume-box:hover, -audio::-webkit-media-controls-panel .volume-box:active { - opacity: 1; - /* resize to usable amount (rather than display:none) for AX and FKA */ - width: 114px; -} - -audio::-webkit-media-controls-volume-slider, -video::-webkit-media-controls-volume-slider { - -webkit-appearance: none !important; - box-sizing: border-box !important; - height: 10px !important; - width: 80px !important; - padding: 0 !important; - margin-right: 6px !important; - - border-radius: 5px !important; - background-color: transparent !important; - background-image: -webkit-linear-gradient( - top, - rgba(15, 15, 15, .85) 0, - rgba(23, 23, 23, .85) 50%, - rgba(15, 15, 15, .85) 100% - ) !important; - border: 1px solid rgba(0, 0, 0, 0.875) !important; -} - -video::-webkit-media-controls-volume-slider::-webkit-slider-thumb, -audio::-webkit-media-controls-volume-slider::-webkit-slider-thumb { - -webkit-appearance: none !important; - width: 8px !important; - height: 8px !important; - border-radius: 4px !important; - background-color: transparent !important; - - /* rotateZ() forces the layer into compositing mode. - Slider thumbs are small, so forcing a compositing layer is inexpensive, - and it keeps the slider from having to repaint while sliding. */ - -webkit-transform: rotateZ(0) !important; - background-image: -webkit-linear-gradient( - left, - rgba(99, 99, 99, 1), - rgba(144, 144, 144, 1) - ) !important; - box-shadow: inset -1px 0 0 rgba(255, 255, 255, .5), 0 1px rgba(255, 255, 255, .14) !important; -} -video::-webkit-media-controls-volume-slider::-webkit-slider-thumb::-webkit-slider-thumb:active, -video::-webkit-media-controls-volume-slider::-webkit-slider-thumb:active::-webkit-slider-thumb, -audio::-webkit-media-controls-volume-slider::-webkit-slider-thumb::-webkit-slider-thumb:active, -audio::-webkit-media-controls-volume-slider::-webkit-slider-thumb:active::-webkit-slider-thumb { - background-image: -webkit-linear-gradient( - right top, - rgba(160, 160, 160, 1), - rgba(221, 221, 221, 1) - ) !important; -} - -video::-webkit-media-controls-mute-button.muted, -audio::-webkit-media-controls-mute-button.muted, -video::-webkit-media-controls-volume-min-button { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 15"><linearGradient id="gradient" x2="0" y2="100%" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="rgb(216, 216, 216)"/><stop offset="0.4375" stop-color="rgb(216, 216, 216)"/><stop offset="0.4375" stop-color="rgb(208, 208, 208)"/><stop offset="0.5" stop-color="rgb(208, 208, 208)"/><stop offset="0.5" stop-color="rgb(200, 200, 200)"/><stop offset="1" stop-color="rgb(208, 208, 208)"/></linearGradient><path d="m 0,9 0,-4 3,0 3,-3 0,10 -3,-3 -3,0 z" fill="url(#gradient)"/></svg>'); -} - -video::-webkit-media-controls-toggle-closed-captions-button, -audio::-webkit-media-controls-toggle-closed-captions-button { - width: 16px; - height: 16px; - margin: 0 7px; - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 102 105"><linearGradient id="gradient" x2="0" y2="100%" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="rgb(216, 216, 216)"/><stop offset="0.46875" stop-color="rgb(216, 216, 216)"/><stop offset="0.46875" stop-color="rgb(208, 208, 208)"/><stop offset="0.53125" stop-color="rgb(208, 208, 208)"/><stop offset="0.53125" stop-color="rgb(200, 200, 200)"/><stop offset="1" stop-color="rgb(208, 208, 208)"/></linearGradient><path d="M98.766,43.224c0-23.163-21.775-41.94-48.637-41.94c-26.859,0-48.635,18.777-48.635,41.94c0,18.266,13.546,33.796,32.444,39.549c1.131,8.356,26.037,24.255,22.864,19.921c-4.462-6.096-5.159-13.183-5.07-17.566C77.85,84.397,98.766,65.923,98.766,43.224z" fill="url(#gradient)"/></svg>'); - outline: 0; -} - -video::-webkit-media-controls-closed-captions-container, -audio::-webkit-media-controls-closed-captions-container { - -webkit-appearance: media-closed-captions-container; - position: absolute; - display: block; - right: 38px; - bottom: 29px; - max-width: calc(100% - 48px); /* right + 10px */ - max-height: calc(100% - 39px); /* bottom + 10px */ - overflow-x: hidden; - overflow-y: scroll; - background-color: rgba(0, 0, 0, 0.85); - border: 3px solid rgba(128, 128, 128, 0.75); - border-radius: 10px; - cursor: default; - z-index: 2; - text-align: initial; -} - -video::-webkit-media-controls-closed-captions-container .list, -audio::-webkit-media-controls-closed-captions-container .list { - display: block; - font-family: "Helvetica Bold", Helvetica, sans-serif; - font-size: 10pt; - -webkit-user-select: none; -} - -video::-webkit-media-controls-closed-captions-container h3, -audio::-webkit-media-controls-closed-captions-container h3 { - margin: 0; - color: rgb(117, 117, 117); - text-shadow: 0 1px 0 black; - -webkit-margin-start: 23px; - padding-top: 4px; - font-weight: bold; - font-size: 10pt; -} - -video::-webkit-media-controls-closed-captions-container ul, -audio::-webkit-media-controls-closed-captions-container ul { - list-style-type: none; - margin: 0 0 4px 0; - padding: 0; - font-weight: bold; -} - -video::-webkit-media-controls-closed-captions-container li, -audio::-webkit-media-controls-closed-captions-container li { - position: relative; - color: white; - background-image: none; - text-shadow: 0 1px 0 black; - margin: 0; - padding-left: 37px; - padding-right: 35px; - padding-top: 0.15em; - padding-bottom: 0.2em; - box-sizing: border-box; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; -} - -video::-webkit-media-controls-closed-captions-container li:focus, -audio::-webkit-media-controls-closed-captions-container li:focus { - outline: 0; - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, rgba(255, 255, 255, 0.3)), color-stop(1, rgba(255, 255, 255, 0.2))); -} - -video::-webkit-media-controls-closed-captions-container li:hover, -audio::-webkit-media-controls-closed-captions-container li:hover { - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, rgb(79, 112, 246)), color-stop(1, rgb(26, 68, 243))); - border-top: 1px solid rgb(70, 103, 234); - border-bottom: 1px solid rgb(3, 54, 229); -} - -video::-webkit-media-controls-closed-captions-container li.selected::before, -audio::-webkit-media-controls-closed-captions-container li.selected::before { - display: block; - content: ""; - position: absolute; - top: 0.25em; - width: 1.1em; - height: 1.1em; - -webkit-margin-start: -20px; - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300"><polygon fill="rgb(163, 163, 163)" points="252.301,4.477 126.667,194.104 43.358,108.3 6.868,161.408 132.515,290.814 297.732,49.926"/></svg>'); - background-repeat: no-repeat; -} - -video::-webkit-media-controls-closed-captions-container li.selected:hover::before, -audio::-webkit-media-controls-closed-captions-container li.selected:hover::before { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300"><polygon fill="white" points="252.301,4.477 126.667,194.104 43.358,108.3 6.868,161.408 132.515,290.814 297.732,49.926"/></svg>'); -} - -video::-webkit-media-controls-fullscreen-button, -audio::-webkit-media-controls-fullscreen-button { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 15" transform="rotate(90,0,0)"><linearGradient id="gradient" x2="0" y2="100%" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="rgb(216, 216, 216)"/><stop offset="0.4375" stop-color="rgb(216, 216, 216)"/><stop offset="0.4375" stop-color="rgb(208, 208, 208)"/><stop offset="0.5" stop-color="rgb(208, 208, 208)"/><stop offset="0.5" stop-color="rgb(200, 200, 200)"/><stop offset="1" stop-color="rgb(208, 208, 208)"/></linearGradient><path d="M 14,1 m 0,6 -2,-2 -2,2 c 0,0 -1,1 -2,0 -1,-1 0,-2 0,-2 l 2,-2 -2,-2 6,0 z" style="fill:url(#gradient) "/><path d="M 1,14 m 0,-6 2,2 2,-2 c 0,0 1,-1 2,0 1,1 0,2 0,2 l -2,2 2,2 -6,0 z" style="fill:url(#gradient) "/></svg>'); - margin: 0 7px; -} -video::-webkit-media-controls-fullscreen-button.exit, -audio::-webkit-media-controls-fullscreen-button.exit { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 15" transform="rotate(90,0,0)"><linearGradient id="gradient" x2="0" y2="100%" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="rgb(216, 216, 216)"/><stop offset="0.4375" stop-color="rgb(216, 216, 216)"/><stop offset="0.4375" stop-color="rgb(208, 208, 208)"/><stop offset="0.5" stop-color="rgb(208, 208, 208)"/><stop offset="0.5" stop-color="rgb(200, 200, 200)"/><stop offset="1" stop-color="rgb(208, 208, 208)"/></linearGradient><path d="M 7,8 m 0,6 -2,-2 -2,2 c 0,0 -1,1 -2,0 -1,-1 0,-2 0,-2 l 2,-2 -2,-2 6,0 z" style="fill:url(#gradient) "/><path d="M 8,7 m 0,-6 2,2 2,-2 c 0,0 1,-1 2,0 1,1 0,2 0,2 l -2,2 2,2 -6,0 z" style="fill:url(#gradient) "/></svg>'); -} -video::-webkit-media-controls-status-display, -audio::-webkit-media-controls-status-display { - cursor: default; - font: -webkit-small-control; - font-size: 9px; - overflow: hidden; - color: white; - text-shadow: black 0px 1px 1px; - - letter-spacing: normal; - word-spacing: normal; - line-height: 25px; - text-transform: none; - text-indent: 0; - text-decoration: none; - text-align: left; - - padding: 0 12px; - - -webkit-flex: 1 1 0; -} -video::-webkit-media-controls-timeline, -audio::-webkit-media-controls-timeline { - -webkit-appearance: none !important; - -webkit-flex: 1 1 0 !important; - height: 9px !important; - margin: 0 !important; - - border-radius: 4.5px !important; - background-color: rgb(74, 74, 74) !important; - box-shadow: inset -1px 0 0 rgba(0, 0, 0, .68), 0 1px rgba(255, 255, 255, .08) !important; -} -video::-webkit-media-controls-timeline::-webkit-slider-thumb, -audio::-webkit-media-controls-timeline::-webkit-slider-thumb { - -webkit-appearance: none !important; - width:6px !important; - height: 6px !important; - background-color: white !important; - - /* rotateZ() forces the layer into compositing mode. - Slider thumbs are small, so forcing a compositing layer is inexpensive, - and it keeps the slider from having to repaint while sliding. */ - -webkit-transform: translateY(1px) rotateZ(-45deg) !important; - - background-image: -webkit-gradient( - linear, - left bottom, - right top, - color-stop(0, rgba(99, 99, 99, 1)), - color-stop(1, rgba(144, 144, 144, 1)) - ) !important; -} -video::-webkit-media-controls-timeline::-webkit-slider-thumb:active, -video::-webkit-media-controls-timeline:active::-webkit-slider-thumb, -audio::-webkit-media-controls-timeline::-webkit-slider-thumb:active, -audio::-webkit-media-controls-timeline:active::-webkit-slider-thumb, - { - background-image: -webkit-gradient( - linear, - left bottom, - right top, - color-stop(0, rgba(160, 160, 160, 1)), - color-stop(1, rgba(221, 221, 221, 1)) - ) !important; -} -video::-webkit-media-controls-current-time-display, -video::-webkit-media-controls-time-remaining-display, -audio::-webkit-media-controls-current-time-display, -audio::-webkit-media-controls-time-remaining-display { - -webkit-user-select: none; - -webkit-flex: 0 0 0; - display: -webkit-flex; - -webkit-justify-content: center; - -webkit-align-items: center; - cursor: default; - font: -webkit-small-control; - font-size: 9px; - overflow-y: hidden; - overflow-x: hidden; - width: 45px; - min-width: 45px; - color: white; - text-shadow: black 0px 1px 1px; - letter-spacing: normal; - word-spacing: normal; - line-height: normal; - text-transform: none; - text-indent: 0px; - text-decoration: none; -} - -video::-webkit-media-controls-timeline-container .hour-long-time, -audio::-webkit-media-controls-timeline-container .hour-long-time { - min-width: 67px; -} - -video::-webkit-media-controls-timeline-container, -audio::-webkit-media-controls-timeline-container { - display: -webkit-flex; - -webkit-flex-direction: row; - -webkit-align-items: center; - -webkit-user-select: none; - -webkit-flex: 1 1 0; - position: relative; - padding: 0; -} - -video::-webkit-media-controls-panel .thumbnail-track, -audio::-webkit-media-controls-panel .thumbnail-track { - position: relative; - -webkit-flex: 1 1 0; - height: 9px; - margin: 0 2px; - display: -webkit-flex; - -webkit-align-items: stretch; - -webkit-flex-direction: column; -} - -video::-webkit-media-controls-panel .thumbnail, -audio::-webkit-media-controls-panel .thumbnail { - position: absolute; - opacity: 0; - transition: opacity 0.25s linear; - bottom: 15px; - width: 100px; - height: 58px; - margin-left: -50px; - border: 5px solid black; - box-shadow: 0 0 3px white; - border-radius: 3px; -} - -video::-webkit-media-controls-panel .thumbnail-image, -audio::-webkit-media-controls-panel .thumbnail-image { - width: 100%; - height: 100%; -} - -video::-webkit-media-controls-panel .thumbnail.show, -audio::-webkit-media-controls-panel .thumbnail.show { - opacity: 1; -} - -video::-webkit-media-controls-panel .hidden, -audio::-webkit-media-controls-panel .hidden { - display: none; -} - -/* Full Screen */ - -/* - Page stylesheets are not allowed to override the style of media - controls while in full screen mode, so many if not all the rules - defined in this section will be marked as !important to enforce - this restriction -*/ - -video:-webkit-full-screen::-webkit-media-controls-panel { - -webkit-align-items: flex-start !important; - -webkit-justify-content: flex-end !important; - - width: 440px !important; - height: 60px !important; - margin: 0 auto 50px auto !important; - padding-top: 10px !important; - - background: -webkit-linear-gradient(top, - rgba(45, 45, 45, .97) 0, - rgba(30, 30, 30, .97) 19px, - rgba(25, 25, 25, .97) 19px, - rgba(25, 25, 25, .97) 20px, - rgba(19, 19, 19, .97) 20px, - rgba(12, 12, 12, .97) 100% - ) !important; - - box-shadow: - inset 0 -1px 1px rgba(0, 0, 0, 0.5), - inset 0 1px 0 0px rgba(255, 255, 255, 0.15), - inset 0 -1px 0 0px rgba(202, 202, 202, 0.09), - 0 0 0 1px rgba(0, 0, 0, 0.5); - border-radius: 8px !important; - - transition: opacity 0.3s linear !important; -} - -video:-webkit-animating-full-screen-transition::-webkit-media-controls-panel { - opacity: 0 ! important; - transition: opacity 0 ! important; -} - -video:-webkit-full-screen::-webkit-media-controls-panel .volume-box { - -webkit-transform: none; - opacity: 1; - left: 11px; - top: 13px; - width: 90px; - height: 14px; - display: -webkit-flex; - -webkit-flex-direction: row; - -webkit-align-items: center; - background-image: none; - border: none; -} - -video:-webkit-full-screen::-webkit-media-controls-volume-slider { - height: 6px !important; - border-radius: 3px !important; - background-image: -webkit-linear-gradient(top, - rgba(16, 16, 16, .300) 0, - rgba(9, 9, 9, .629) 100% - ) !important; - box-shadow: inset -1px 0 0 rgba(0, 0, 0, .68), 0 1px rgba(255, 255, 255, .08) !important; -} - -video:-webkit-full-screen::-webkit-media-controls-volume-slider::-webkit-slider-thumb { - width: 10px !important; - height: 10px !important; - border-radius: 5px !important; - - /* rotateZ() forces the layer into compositing mode. - Slider thumbs are small, so forcing a compositing layer is inexpensive, - and it keeps the slider from having to repaint while sliding. */ - -webkit-transform: rotateZ(270deg) !important; -} - -video:-webkit-full-screen::-webkit-media-controls-play-button { - position: absolute; - - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21 22"><linearGradient id="gradient" x2="0" y2="100%" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="rgb(216, 216, 216)"/><stop offset="0.478" stop-color="rgb(216, 216, 216)"/><stop offset="0.478" stop-color="rgb(208, 208, 208)"/><stop offset="0.522" stop-color="rgb(208, 208, 208)"/><stop offset="0.522" stop-color="rgb(200, 200, 200)"/><stop offset="1" stop-color="rgb(208, 208, 208)"/></linearGradient><path d="M 0,0 0,22 8,22 8,0 z" fill="url(#gradient)"/><path d="M 13,0 13,22 21,22 21,0 z" fill="url(#gradient)"/></svg>'); - - width: 22px; - height: 23px; - left: 209px; - top: 9px; - margin: 0; - padding: 0; -} - -video:-webkit-full-screen::-webkit-media-controls-play-button.paused { - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21 22"><linearGradient id="gradient" x2="0" y2="100%" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="rgb(216, 216, 216)"/><stop offset="0.478" stop-color="rgb(216, 216, 216)"/><stop offset="0.478" stop-color="rgb(208, 208, 208)"/><stop offset="0.522" stop-color="rgb(208, 208, 208)"/><stop offset="0.522" stop-color="rgb(200, 200, 200)"/><stop offset="1" stop-color="rgb(208, 208, 208)"/></linearGradient><path d="M 0,0 21,11 0,22 z" fill="url(#gradient)"/></svg>'); -} - -video:-webkit-full-screen::-webkit-media-controls-rewind-button { - position: absolute; - left: 162px; - top: 13px; - width: 18px; - height: 18px; -} - -video:-webkit-full-screen::-webkit-media-controls-seek-back-button { - position: absolute; - - - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 15"><linearGradient id="gradient" x2="0" y2="100%" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="rgb(216, 216, 216)"/><stop offset="0.4375" stop-color="rgb(216, 216, 216)"/><stop offset="0.4375" stop-color="rgb(208, 208, 208)"/><stop offset="0.5" stop-color="rgb(208, 208, 208)"/><stop offset="0.5" stop-color="rgb(200, 200, 200)"/><stop offset="1" stop-color="rgb(208, 208, 208)"/></linearGradient><path d="M 22,0 11,7 22,15 z" fill="url(#gradient)"/><path d="M 11,0 0,7 11,15 z" fill="url(#gradient)"/></svg>'); - - width: 23px; - height: 16px; - left: 156px; - top: 13px; -} - -video:-webkit-full-screen::-webkit-media-controls-return-to-realtime-button { - position: absolute; - display: -webkit-flex; - width: 29px; - height: 16px; - left: 262px; - top: 13px; -} - -video:-webkit-full-screen::-webkit-media-controls-seek-forward-button { - position: absolute; - - background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 15"><linearGradient id="gradient" x2="0" y2="100%" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="rgb(216, 216, 216)"/><stop offset="0.4375" stop-color="rgb(216, 216, 216)"/><stop offset="0.4375" stop-color="rgb(208, 208, 208)"/><stop offset="0.5" stop-color="rgb(208, 208, 208)"/><stop offset="0.5" stop-color="rgb(200, 200, 200)"/><stop offset="1" stop-color="rgb(208, 208, 208)"/></linearGradient><path d="M 0,0 11,7 0,15 z" fill="url(#gradient)"/><path d="M 11,0 22,7 11,15 z" fill="url(#gradient)"/></svg>'); - - width: 23px; - height: 16px; - left: 256px; - top: 13px; -} - -video:-webkit-full-screen::-webkit-media-controls-timeline-container { - height: auto; - width: 420px; - position: absolute; - bottom: 9px; - left: 8px; - right: 8px; -} - -video:-webkit-full-screen::-webkit-media-controls-status-display { - width: 420px; - position: absolute; - bottom: 7px; - left: 8px; - right: 8px; -} - -video:-webkit-full-screen::-webkit-media-controls-closed-captions-container { - bottom: 114px; - right: calc(50% - 183px); /* 183px is 221px (half the media controller's width) minus 38px (the right position of the captions icon). */ - max-width: calc(50% + 173px); /* right + 10px */ - max-height: calc(100% - 124px); /* bottom + 10px */ -} - -video::-webkit-media-text-track-container { - position: relative; - width: 100%; - overflow: hidden; - padding-bottom: 5px; - - text-align: center; - color: rgba(255, 255, 255, 1); - - letter-spacing: normal; - word-spacing: normal; - text-transform: none; - text-indent: 0; - text-decoration: none; - pointer-events: none; - -webkit-user-select: none; - - -webkit-flex: 1 1; - - -webkit-line-box-contain: block inline-box replaced; -} - -video::cue { - background-color: rgba(0, 0, 0, 0.8); -} - -video::-webkit-media-text-track-display { - position: absolute; - overflow: hidden; - white-space: pre-wrap; - -webkit-box-sizing: border-box; - font: 22px sans-serif; -} - -video::-webkit-media-text-track-display-backdrop { - display: inline-block; -} - -video::cue(:future) { - color: gray; -} - -video::-webkit-media-text-track-container b { - font-weight: bold; -} - -video::-webkit-media-text-track-container u { - text-decoration: underline; -} - -video::-webkit-media-text-track-container i { - font-style: italic; -} - -video::-webkit-media-text-track-container .hidden, -audio::-webkit-media-text-track-container .hidden { - display: none; -} diff --git a/Source/WebCore/Modules/mediacontrols/mediaControlsBase.js b/Source/WebCore/Modules/mediacontrols/mediaControlsBase.js deleted file mode 100644 index f78696d64..000000000 --- a/Source/WebCore/Modules/mediacontrols/mediaControlsBase.js +++ /dev/null @@ -1,1336 +0,0 @@ -function createControls(root, video, host) -{ - return new Controller(root, video, host); -}; - -function Controller(root, video, host) -{ - this.video = video; - this.root = root; - this.host = host; - this.controls = {}; - this.listeners = {}; - this.isLive = false; - this.statusHidden = true; - this.hasVisualMedia = false; - - this.addVideoListeners(); - this.createBase(); - this.createControls(); - this.updateBase(); - this.updateControls(); - this.updateDuration(); - this.updateProgress(); - this.updateTime(); - this.updateReadyState(); - this.updatePlaying(); - this.updateThumbnail(); - this.updateCaptionButton(); - this.updateCaptionContainer(); - this.updateFullscreenButton(); - this.updateVolume(); - this.updateHasAudio(); - this.updateHasVideo(); -}; - -/* Enums */ -Controller.InlineControls = 0; -Controller.FullScreenControls = 1; - -Controller.PlayAfterSeeking = 0; -Controller.PauseAfterSeeking = 1; - -/* Globals */ -Controller.gLastTimelineId = 0; - -Controller.prototype = { - - /* Constants */ - HandledVideoEvents: { - loadstart: 'handleLoadStart', - error: 'handleError', - abort: 'handleAbort', - suspend: 'handleSuspend', - stalled: 'handleStalled', - waiting: 'handleWaiting', - emptied: 'handleReadyStateChange', - loadedmetadata: 'handleReadyStateChange', - loadeddata: 'handleReadyStateChange', - canplay: 'handleReadyStateChange', - canplaythrough: 'handleReadyStateChange', - timeupdate: 'handleTimeUpdate', - durationchange: 'handleDurationChange', - playing: 'handlePlay', - pause: 'handlePause', - progress: 'handleProgress', - volumechange: 'handleVolumeChange', - webkitfullscreenchange: 'handleFullscreenChange', - webkitbeginfullscreen: 'handleFullscreenChange', - webkitendfullscreen: 'handleFullscreenChange', - }, - HideControlsDelay: 4 * 1000, - RewindAmount: 30, - MaximumSeekRate: 8, - SeekDelay: 1500, - ClassNames: { - active: 'active', - exit: 'exit', - failed: 'failed', - hidden: 'hidden', - hiding: 'hiding', - hourLongTime: 'hour-long-time', - list: 'list', - muteBox: 'mute-box', - muted: 'muted', - paused: 'paused', - playing: 'playing', - selected: 'selected', - show: 'show', - thumbnail: 'thumbnail', - thumbnailImage: 'thumbnail-image', - thumbnailTrack: 'thumbnail-track', - volumeBox: 'volume-box', - noVideo: 'no-video', - down: 'down', - out: 'out', - }, - KeyCodes: { - enter: 13, - escape: 27, - space: 32, - pageUp: 33, - pageDown: 34, - end: 35, - home: 36, - left: 37, - up: 38, - right: 39, - down: 40 - }, - - extend: function(child) - { - for (var property in this) { - if (!child.hasOwnProperty(property)) - child[property] = this[property]; - } - }, - - UIString: function(developmentString, replaceString, replacementString) - { - var localized = UIStringTable[developmentString]; - if (replaceString && replacementString) - return localized.replace(replaceString, replacementString); - - if (localized) - return localized; - - console.error("Localization for string \"" + developmentString + "\" not found."); - return "LOCALIZED STRING NOT FOUND"; - }, - - listenFor: function(element, eventName, handler, useCapture) - { - if (typeof useCapture === 'undefined') - useCapture = false; - - if (!(this.listeners[eventName] instanceof Array)) - this.listeners[eventName] = []; - this.listeners[eventName].push({element:element, handler:handler, useCapture:useCapture}); - element.addEventListener(eventName, this, useCapture); - }, - - stopListeningFor: function(element, eventName, handler, useCapture) - { - if (typeof useCapture === 'undefined') - useCapture = false; - - if (!(this.listeners[eventName] instanceof Array)) - return; - - this.listeners[eventName] = this.listeners[eventName].filter(function(entry) { - return !(entry.element === element && entry.handler === handler && entry.useCapture === useCapture); - }); - element.removeEventListener(eventName, this, useCapture); - }, - - addVideoListeners: function() - { - for (var name in this.HandledVideoEvents) { - this.listenFor(this.video, name, this.HandledVideoEvents[name]); - }; - - /* text tracks */ - this.listenFor(this.video.textTracks, 'change', this.handleTextTrackChange); - this.listenFor(this.video.textTracks, 'addtrack', this.handleTextTrackAdd); - this.listenFor(this.video.textTracks, 'removetrack', this.handleTextTrackRemove); - - /* audio tracks */ - this.listenFor(this.video.audioTracks, 'change', this.updateHasAudio); - this.listenFor(this.video.audioTracks, 'addtrack', this.updateHasAudio); - this.listenFor(this.video.audioTracks, 'removetrack', this.updateHasAudio); - - /* video tracks */ - this.listenFor(this.video.videoTracks, 'change', this.updateHasVideo); - this.listenFor(this.video.videoTracks, 'addtrack', this.updateHasVideo); - this.listenFor(this.video.videoTracks, 'removetrack', this.updateHasVideo); - - /* controls attribute */ - this.controlsObserver = new MutationObserver(this.handleControlsChange.bind(this)); - this.controlsObserver.observe(this.video, { attributes: true, attributeFilter: ['controls'] }); - }, - - removeVideoListeners: function() - { - for (var name in this.HandledVideoEvents) { - this.stopListeningFor(this.video, name, this.HandledVideoEvents[name]); - }; - - /* text tracks */ - this.stopListeningFor(this.video.textTracks, 'change', this.handleTextTrackChange); - this.stopListeningFor(this.video.textTracks, 'addtrack', this.handleTextTrackAdd); - this.stopListeningFor(this.video.textTracks, 'removetrack', this.handleTextTrackRemove); - - /* audio tracks */ - this.stopListeningFor(this.video.audioTracks, 'change', this.updateHasAudio); - this.stopListeningFor(this.video.audioTracks, 'addtrack', this.updateHasAudio); - this.stopListeningFor(this.video.audioTracks, 'removetrack', this.updateHasAudio); - - /* video tracks */ - this.stopListeningFor(this.video.videoTracks, 'change', this.updateHasVideo); - this.stopListeningFor(this.video.videoTracks, 'addtrack', this.updateHasVideo); - this.stopListeningFor(this.video.videoTracks, 'removetrack', this.updateHasVideo); - - /* controls attribute */ - this.controlsObserver.disconnect(); - delete(this.controlsObserver); - }, - - handleEvent: function(event) - { - var preventDefault = false; - - try { - if (event.target === this.video) { - var handlerName = this.HandledVideoEvents[event.type]; - var handler = this[handlerName]; - if (handler && handler instanceof Function) - handler.call(this, event); - } - - if (!(this.listeners[event.type] instanceof Array)) - return; - - this.listeners[event.type].forEach(function(entry) { - if (entry.element === event.currentTarget && entry.handler instanceof Function) - preventDefault |= entry.handler.call(this, event); - }, this); - } catch(e) { - if (window.console) - console.error(e); - } - - if (preventDefault) { - event.stopPropagation(); - event.preventDefault(); - } - }, - - createBase: function() - { - var base = this.base = document.createElement('div'); - base.setAttribute('pseudo', '-webkit-media-controls'); - this.listenFor(base, 'mousemove', this.handleWrapperMouseMove); - this.listenFor(base, 'mouseout', this.handleWrapperMouseOut); - if (this.host.textTrackContainer) - base.appendChild(this.host.textTrackContainer); - }, - - shouldHaveAnyUI: function() - { - return this.shouldHaveControls() || (this.video.textTracks && this.video.textTracks.length); - }, - - shouldHaveControls: function() - { - return this.video.controls || this.isFullScreen(); - }, - - setNeedsTimelineMetricsUpdate: function() - { - this.timelineMetricsNeedsUpdate = true; - }, - - updateTimelineMetricsIfNeeded: function() - { - if (this.timelineMetricsNeedsUpdate) { - this.timelineLeft = this.controls.timeline.offsetLeft; - this.timelineWidth = this.controls.timeline.offsetWidth; - this.timelineHeight = this.controls.timeline.offsetHeight; - this.timelineMetricsNeedsUpdate = false; - } - }, - - updateBase: function() - { - if (this.shouldHaveAnyUI()) { - if (!this.base.parentNode) { - this.root.appendChild(this.base); - } - } else { - if (this.base.parentNode) { - this.base.parentNode.removeChild(this.base); - } - } - }, - - createControls: function() - { - var panelCompositedParent = this.controls.panelCompositedParent = document.createElement('div'); - panelCompositedParent.setAttribute('pseudo', '-webkit-media-controls-panel-composited-parent'); - - var panel = this.controls.panel = document.createElement('div'); - panel.setAttribute('pseudo', '-webkit-media-controls-panel'); - panel.setAttribute('aria-label', (this.isAudio() ? this.UIString('Audio Playback') : this.UIString('Video Playback'))); - panel.setAttribute('role', 'toolbar'); - this.listenFor(panel, 'mousedown', this.handlePanelMouseDown); - this.listenFor(panel, 'transitionend', this.handlePanelTransitionEnd); - this.listenFor(panel, 'click', this.handlePanelClick); - this.listenFor(panel, 'dblclick', this.handlePanelClick); - - var rewindButton = this.controls.rewindButton = document.createElement('button'); - rewindButton.setAttribute('pseudo', '-webkit-media-controls-rewind-button'); - rewindButton.setAttribute('aria-label', this.UIString('Rewind ##sec## Seconds', '##sec##', this.RewindAmount)); - this.listenFor(rewindButton, 'click', this.handleRewindButtonClicked); - - var seekBackButton = this.controls.seekBackButton = document.createElement('button'); - seekBackButton.setAttribute('pseudo', '-webkit-media-controls-seek-back-button'); - seekBackButton.setAttribute('aria-label', this.UIString('Rewind')); - this.listenFor(seekBackButton, 'mousedown', this.handleSeekBackMouseDown); - this.listenFor(seekBackButton, 'mouseup', this.handleSeekBackMouseUp); - - var seekForwardButton = this.controls.seekForwardButton = document.createElement('button'); - seekForwardButton.setAttribute('pseudo', '-webkit-media-controls-seek-forward-button'); - seekForwardButton.setAttribute('aria-label', this.UIString('Fast Forward')); - this.listenFor(seekForwardButton, 'mousedown', this.handleSeekForwardMouseDown); - this.listenFor(seekForwardButton, 'mouseup', this.handleSeekForwardMouseUp); - - var playButton = this.controls.playButton = document.createElement('button'); - playButton.setAttribute('pseudo', '-webkit-media-controls-play-button'); - playButton.setAttribute('aria-label', this.UIString('Play')); - this.listenFor(playButton, 'click', this.handlePlayButtonClicked); - - var statusDisplay = this.controls.statusDisplay = document.createElement('div'); - statusDisplay.setAttribute('pseudo', '-webkit-media-controls-status-display'); - statusDisplay.classList.add(this.ClassNames.hidden); - - var timelineBox = this.controls.timelineBox = document.createElement('div'); - timelineBox.setAttribute('pseudo', '-webkit-media-controls-timeline-container'); - - var currentTime = this.controls.currentTime = document.createElement('div'); - currentTime.setAttribute('pseudo', '-webkit-media-controls-current-time-display'); - currentTime.setAttribute('aria-label', this.UIString('Elapsed')); - currentTime.setAttribute('role', 'timer'); - - var timeline = this.controls.timeline = document.createElement('input'); - this.timelineID = ++Controller.gLastTimelineId; - timeline.setAttribute('pseudo', '-webkit-media-controls-timeline'); - timeline.setAttribute('aria-label', this.UIString('Duration')); - timeline.style.backgroundImage = '-webkit-canvas(timeline-' + this.timelineID + ')'; - timeline.type = 'range'; - timeline.value = 0; - this.listenFor(timeline, 'input', this.handleTimelineChange); - this.listenFor(timeline, 'mouseover', this.handleTimelineMouseOver); - this.listenFor(timeline, 'mouseout', this.handleTimelineMouseOut); - this.listenFor(timeline, 'mousemove', this.handleTimelineMouseMove); - this.listenFor(timeline, 'mousedown', this.handleTimelineMouseDown); - this.listenFor(timeline, 'mouseup', this.handleTimelineMouseUp); - timeline.step = .01; - - var thumbnailTrack = this.controls.thumbnailTrack = document.createElement('div'); - thumbnailTrack.classList.add(this.ClassNames.thumbnailTrack); - - var thumbnail = this.controls.thumbnail = document.createElement('div'); - thumbnail.classList.add(this.ClassNames.thumbnail); - - var thumbnailImage = this.controls.thumbnailImage = document.createElement('img'); - thumbnailImage.classList.add(this.ClassNames.thumbnailImage); - - var remainingTime = this.controls.remainingTime = document.createElement('div'); - remainingTime.setAttribute('pseudo', '-webkit-media-controls-time-remaining-display'); - remainingTime.setAttribute('aria-label', this.UIString('Remaining')); - remainingTime.setAttribute('role', 'timer'); - - var muteBox = this.controls.muteBox = document.createElement('div'); - muteBox.classList.add(this.ClassNames.muteBox); - - var muteButton = this.controls.muteButton = document.createElement('button'); - muteButton.setAttribute('pseudo', '-webkit-media-controls-mute-button'); - muteButton.setAttribute('aria-label', this.UIString('Mute')); - this.listenFor(muteButton, 'click', this.handleMuteButtonClicked); - - var minButton = this.controls.minButton = document.createElement('button'); - minButton.setAttribute('pseudo', '-webkit-media-controls-volume-min-button'); - minButton.setAttribute('aria-label', this.UIString('Minimum Volume')); - this.listenFor(minButton, 'click', this.handleMinButtonClicked); - - var maxButton = this.controls.maxButton = document.createElement('button'); - maxButton.setAttribute('pseudo', '-webkit-media-controls-volume-max-button'); - maxButton.setAttribute('aria-label', this.UIString('Maximum Volume')); - this.listenFor(maxButton, 'click', this.handleMaxButtonClicked); - - var volumeBox = this.controls.volumeBox = document.createElement('div'); - volumeBox.setAttribute('pseudo', '-webkit-media-controls-volume-slider-container'); - volumeBox.classList.add(this.ClassNames.volumeBox); - - var volume = this.controls.volume = document.createElement('input'); - volume.setAttribute('pseudo', '-webkit-media-controls-volume-slider'); - volume.setAttribute('aria-label', this.UIString('Volume')); - volume.type = 'range'; - volume.min = 0; - volume.max = 1; - volume.step = .01; - this.listenFor(volume, 'input', this.handleVolumeSliderInput); - - var captionButton = this.controls.captionButton = document.createElement('button'); - captionButton.setAttribute('pseudo', '-webkit-media-controls-toggle-closed-captions-button'); - captionButton.setAttribute('aria-label', this.UIString('Captions')); - captionButton.setAttribute('aria-haspopup', 'true'); - captionButton.setAttribute('aria-owns', 'audioTrackMenu'); - this.listenFor(captionButton, 'click', this.handleCaptionButtonClicked); - - var fullscreenButton = this.controls.fullscreenButton = document.createElement('button'); - fullscreenButton.setAttribute('pseudo', '-webkit-media-controls-fullscreen-button'); - fullscreenButton.setAttribute('aria-label', this.UIString('Display Full Screen')); - this.listenFor(fullscreenButton, 'click', this.handleFullscreenButtonClicked); - }, - - setControlsType: function(type) - { - if (type === this.controlsType) - return; - this.controlsType = type; - - this.reconnectControls(); - }, - - setIsLive: function(live) - { - if (live === this.isLive) - return; - this.isLive = live; - - this.updateStatusDisplay(); - - this.reconnectControls(); - }, - - reconnectControls: function() - { - this.disconnectControls(); - - if (this.controlsType === Controller.InlineControls) - this.configureInlineControls(); - else if (this.controlsType == Controller.FullScreenControls) - this.configureFullScreenControls(); - - if (this.shouldHaveControls()) - this.addControls(); - }, - - disconnectControls: function(event) - { - for (var item in this.controls) { - var control = this.controls[item]; - if (control && control.parentNode) - control.parentNode.removeChild(control); - } - }, - - configureInlineControls: function() - { - if (!this.isLive) - this.controls.panel.appendChild(this.controls.rewindButton); - this.controls.panel.appendChild(this.controls.playButton); - this.controls.panel.appendChild(this.controls.statusDisplay); - if (!this.isLive) { - this.controls.panel.appendChild(this.controls.timelineBox); - this.controls.timelineBox.appendChild(this.controls.currentTime); - this.controls.timelineBox.appendChild(this.controls.thumbnailTrack); - this.controls.thumbnailTrack.appendChild(this.controls.timeline); - this.controls.thumbnailTrack.appendChild(this.controls.thumbnail); - this.controls.thumbnail.appendChild(this.controls.thumbnailImage); - this.controls.timelineBox.appendChild(this.controls.remainingTime); - } - this.controls.panel.appendChild(this.controls.muteBox); - this.controls.muteBox.appendChild(this.controls.volumeBox); - this.controls.volumeBox.appendChild(this.controls.volume); - this.controls.muteBox.appendChild(this.controls.muteButton); - this.controls.panel.appendChild(this.controls.captionButton); - if (!this.isAudio()) - this.controls.panel.appendChild(this.controls.fullscreenButton); - - this.controls.panel.style.removeProperty('left'); - this.controls.panel.style.removeProperty('top'); - this.controls.panel.style.removeProperty('bottom'); - }, - - configureFullScreenControls: function() - { - this.controls.panel.appendChild(this.controls.volumeBox); - this.controls.volumeBox.appendChild(this.controls.minButton); - this.controls.volumeBox.appendChild(this.controls.volume); - this.controls.volumeBox.appendChild(this.controls.maxButton); - this.controls.panel.appendChild(this.controls.seekBackButton); - this.controls.panel.appendChild(this.controls.playButton); - this.controls.panel.appendChild(this.controls.seekForwardButton); - this.controls.panel.appendChild(this.controls.captionButton); - if (!this.isAudio()) - this.controls.panel.appendChild(this.controls.fullscreenButton); - if (!this.isLive) { - this.controls.panel.appendChild(this.controls.timelineBox); - this.controls.timelineBox.appendChild(this.controls.currentTime); - this.controls.timelineBox.appendChild(this.controls.thumbnailTrack); - this.controls.thumbnailTrack.appendChild(this.controls.timeline); - this.controls.thumbnailTrack.appendChild(this.controls.thumbnail); - this.controls.thumbnail.appendChild(this.controls.thumbnailImage); - this.controls.timelineBox.appendChild(this.controls.remainingTime); - } else - this.controls.panel.appendChild(this.controls.statusDisplay); - }, - - updateControls: function() - { - if (this.isFullScreen()) - this.setControlsType(Controller.FullScreenControls); - else - this.setControlsType(Controller.InlineControls); - - this.setNeedsTimelineMetricsUpdate(); - }, - - updateStatusDisplay: function(event) - { - if (this.video.error !== null) - this.controls.statusDisplay.innerText = this.UIString('Error'); - else if (this.isLive && this.video.readyState >= HTMLMediaElement.HAVE_CURRENT_DATA) - this.controls.statusDisplay.innerText = this.UIString('Live Broadcast'); - else if (this.video.networkState === HTMLMediaElement.NETWORK_LOADING) - this.controls.statusDisplay.innerText = this.UIString('Loading'); - else - this.controls.statusDisplay.innerText = ''; - - this.setStatusHidden(!this.isLive && this.video.readyState > HTMLMediaElement.HAVE_NOTHING && !this.video.error); - }, - - handleLoadStart: function(event) - { - this.updateStatusDisplay(); - this.updateProgress(); - }, - - handleError: function(event) - { - this.updateStatusDisplay(); - }, - - handleAbort: function(event) - { - this.updateStatusDisplay(); - }, - - handleSuspend: function(event) - { - this.updateStatusDisplay(); - }, - - handleStalled: function(event) - { - this.updateStatusDisplay(); - this.updateProgress(); - }, - - handleWaiting: function(event) - { - this.updateStatusDisplay(); - }, - - handleReadyStateChange: function(event) - { - this.hasVisualMedia = this.video.videoTracks && this.video.videoTracks.length > 0; - this.updateReadyState(); - this.updateDuration(); - this.updateCaptionButton(); - this.updateCaptionContainer(); - this.updateFullscreenButton(); - this.updateProgress(); - }, - - handleTimeUpdate: function(event) - { - if (!this.scrubbing) - this.updateTime(); - }, - - handleDurationChange: function(event) - { - this.updateDuration(); - this.updateTime(true); - this.updateProgress(true); - }, - - handlePlay: function(event) - { - this.setPlaying(true); - }, - - handlePause: function(event) - { - this.setPlaying(false); - }, - - handleProgress: function(event) - { - this.updateProgress(); - }, - - handleVolumeChange: function(event) - { - this.updateVolume(); - }, - - handleTextTrackChange: function(event) - { - this.updateCaptionContainer(); - }, - - handleTextTrackAdd: function(event) - { - var track = event.track; - - if (this.trackHasThumbnails(track) && track.mode === 'disabled') - track.mode = 'hidden'; - - this.updateThumbnail(); - this.updateCaptionButton(); - this.updateCaptionContainer(); - }, - - handleTextTrackRemove: function(event) - { - this.updateThumbnail(); - this.updateCaptionButton(); - this.updateCaptionContainer(); - }, - - isFullScreen: function() - { - return this.video.webkitDisplayingFullscreen; - }, - - handleFullscreenChange: function(event) - { - this.updateBase(); - this.updateControls(); - - if (this.isFullScreen()) { - this.controls.fullscreenButton.classList.add(this.ClassNames.exit); - this.controls.fullscreenButton.setAttribute('aria-label', this.UIString('Exit Full Screen')); - this.host.enteredFullscreen(); - } else { - this.controls.fullscreenButton.classList.remove(this.ClassNames.exit); - this.controls.fullscreenButton.setAttribute('aria-label', this.UIString('Display Full Screen')); - this.host.exitedFullscreen(); - } - }, - - handleWrapperMouseMove: function(event) - { - this.showControls(); - this.resetHideControlsTimer(); - - if (!this.isDragging) - return; - var delta = new WebKitPoint(event.clientX - this.initialDragLocation.x, event.clientY - this.initialDragLocation.y); - this.controls.panel.style.left = this.initialOffset.x + delta.x + 'px'; - this.controls.panel.style.top = this.initialOffset.y + delta.y + 'px'; - event.stopPropagation() - }, - - handleWrapperMouseOut: function(event) - { - this.hideControls(); - this.clearHideControlsTimer(); - }, - - handleWrapperMouseUp: function(event) - { - this.isDragging = false; - this.stopListeningFor(this.base, 'mouseup', 'handleWrapperMouseUp', true); - }, - - handlePanelMouseDown: function(event) - { - if (event.target != this.controls.panel) - return; - - if (!this.isFullScreen()) - return; - - this.listenFor(this.base, 'mouseup', this.handleWrapperMouseUp, true); - this.isDragging = true; - this.initialDragLocation = new WebKitPoint(event.clientX, event.clientY); - this.initialOffset = new WebKitPoint( - parseInt(this.controls.panel.style.left) | 0, - parseInt(this.controls.panel.style.top) | 0 - ); - }, - - handlePanelTransitionEnd: function(event) - { - var opacity = window.getComputedStyle(this.controls.panel).opacity; - if (parseInt(opacity) > 0) - this.controls.panel.classList.remove(this.ClassNames.hidden); - else - this.controls.panel.classList.add(this.ClassNames.hidden); - }, - - handlePanelClick: function(event) - { - // Prevent clicks in the panel from playing or pausing the video in a MediaDocument. - event.preventDefault(); - }, - - handleRewindButtonClicked: function(event) - { - var newTime = Math.max( - this.video.currentTime - this.RewindAmount, - this.video.seekable.start(0)); - this.video.currentTime = newTime; - return true; - }, - - canPlay: function() - { - return this.video.paused || this.video.ended || this.video.readyState < HTMLMediaElement.HAVE_METADATA; - }, - - handlePlayButtonClicked: function(event) - { - if (this.canPlay()) - this.video.play(); - else - this.video.pause(); - return true; - }, - - handleTimelineChange: function(event) - { - this.video.fastSeek(this.controls.timeline.value); - }, - - handleTimelineDown: function(event) - { - this.controls.thumbnail.classList.add(this.ClassNames.show); - }, - - handleTimelineUp: function(event) - { - this.controls.thumbnail.classList.remove(this.ClassNames.show); - }, - - handleTimelineMouseOver: function(event) - { - this.controls.thumbnail.classList.add(this.ClassNames.show); - }, - - handleTimelineMouseOut: function(event) - { - this.controls.thumbnail.classList.remove(this.ClassNames.show); - }, - - handleTimelineMouseMove: function(event) - { - if (this.controls.thumbnail.classList.contains(this.ClassNames.hidden)) - return; - - this.updateTimelineMetricsIfNeeded(); - this.controls.thumbnail.classList.add(this.ClassNames.show); - var localPoint = webkitConvertPointFromPageToNode(this.controls.timeline, new WebKitPoint(event.clientX, event.clientY)); - var percent = (localPoint.x - this.timelineLeft) / this.timelineWidth; - percent = Math.max(Math.min(1, percent), 0); - this.controls.thumbnail.style.left = percent * 100 + '%'; - - var thumbnailTime = percent * this.video.duration; - for (var i = 0; i < this.video.textTracks.length; ++i) { - var track = this.video.textTracks[i]; - if (!this.trackHasThumbnails(track)) - continue; - - if (!track.cues) - continue; - - for (var j = 0; j < track.cues.length; ++j) { - var cue = track.cues[j]; - if (thumbnailTime >= cue.startTime && thumbnailTime < cue.endTime) { - this.controls.thumbnailImage.src = cue.text; - return; - } - } - } - }, - - handleTimelineMouseDown: function(event) - { - this.scrubbing = true; - }, - - handleTimelineMouseUp: function(event) - { - this.scrubbing = false; - - // Do a precise seek when we lift the mouse: - this.video.currentTime = this.controls.timeline.value; - }, - - handleMuteButtonClicked: function(event) - { - this.video.muted = !this.video.muted; - if (this.video.muted) - this.controls.muteButton.setAttribute('aria-label', this.UIString('Unmute')); - return true; - }, - - handleMinButtonClicked: function(event) - { - if (this.video.muted) { - this.video.muted = false; - this.controls.muteButton.setAttribute('aria-label', this.UIString('Mute')); - } - this.video.volume = 0; - return true; - }, - - handleMaxButtonClicked: function(event) - { - if (this.video.muted) { - this.video.muted = false; - this.controls.muteButton.setAttribute('aria-label', this.UIString('Mute')); - } - this.video.volume = 1; - }, - - handleVolumeSliderInput: function(event) - { - if (this.video.muted) { - this.video.muted = false; - this.controls.muteButton.setAttribute('aria-label', this.UIString('Mute')); - } - this.video.volume = this.controls.volume.value; - }, - - handleCaptionButtonClicked: function(event) - { - if (this.captionMenu) - this.destroyCaptionMenu(); - else - this.buildCaptionMenu(); - return true; - }, - - updateFullscreenButton: function() - { - this.controls.fullscreenButton.classList.toggle(this.ClassNames.hidden, (!this.video.webkitSupportsFullscreen || !this.hasVisualMedia)); - }, - - handleFullscreenButtonClicked: function(event) - { - if (this.isFullScreen()) - this.video.webkitExitFullscreen(); - else - this.video.webkitEnterFullscreen(); - return true; - }, - - handleControlsChange: function() - { - try { - this.updateBase(); - - if (this.shouldHaveControls()) - this.addControls(); - else - this.removeControls(); - } catch(e) { - if (window.console) - console.error(e); - } - }, - - nextRate: function() - { - return Math.min(this.MaximumSeekRate, Math.abs(this.video.playbackRate * 2)); - }, - - handleSeekBackMouseDown: function(event) - { - this.actionAfterSeeking = (this.canPlay() ? Controller.PauseAfterSeeking : Controller.PlayAfterSeeking); - this.video.play(); - this.video.playbackRate = this.nextRate() * -1; - this.seekInterval = setInterval(this.seekBackFaster.bind(this), this.SeekDelay); - }, - - seekBackFaster: function() - { - this.video.playbackRate = this.nextRate() * -1; - }, - - handleSeekBackMouseUp: function(event) - { - this.video.playbackRate = this.video.defaultPlaybackRate; - if (this.actionAfterSeeking === Controller.PauseAfterSeeking) - this.video.pause(); - else if (this.actionAfterSeeking === Controller.PlayAfterSeeking) - this.video.play(); - if (this.seekInterval) - clearInterval(this.seekInterval); - }, - - handleSeekForwardMouseDown: function(event) - { - this.actionAfterSeeking = (this.canPlay() ? Controller.PauseAfterSeeking : Controller.PlayAfterSeeking); - this.video.play(); - this.video.playbackRate = this.nextRate(); - this.seekInterval = setInterval(this.seekForwardFaster.bind(this), this.SeekDelay); - }, - - seekForwardFaster: function() - { - this.video.playbackRate = this.nextRate(); - }, - - handleSeekForwardMouseUp: function(event) - { - this.video.playbackRate = this.video.defaultPlaybackRate; - if (this.actionAfterSeeking === Controller.PauseAfterSeeking) - this.video.pause(); - else if (this.actionAfterSeeking === Controller.PlayAfterSeeking) - this.video.play(); - if (this.seekInterval) - clearInterval(this.seekInterval); - }, - - updateDuration: function() - { - var duration = this.video.duration; - this.controls.timeline.min = 0; - this.controls.timeline.max = duration; - - this.setIsLive(duration === Number.POSITIVE_INFINITY); - - this.controls.currentTime.classList.toggle(this.ClassNames.hourLongTime, duration >= 60*60); - this.controls.remainingTime.classList.toggle(this.ClassNames.hourLongTime, duration >= 60*60); - }, - - progressFillStyle: function(context) - { - var height = this.timelineHeight; - var gradient = context.createLinearGradient(0, 0, 0, height); - gradient.addColorStop(0, 'rgb(2, 2, 2)'); - gradient.addColorStop(1, 'rgb(23, 23, 23)'); - return gradient; - }, - - updateProgress: function(forceUpdate) - { - if (!forceUpdate && this.controlsAreHidden()) - return; - - this.updateTimelineMetricsIfNeeded(); - - var width = this.timelineWidth; - var height = this.timelineHeight; - - var context = document.getCSSCanvasContext('2d', 'timeline-' + this.timelineID, width, height); - context.clearRect(0, 0, width, height); - - context.fillStyle = this.progressFillStyle(context); - - var duration = this.video.duration; - var buffered = this.video.buffered; - for (var i = 0, end = buffered.length; i < end; ++i) { - var startTime = buffered.start(i); - var endTime = buffered.end(i); - - var startX = width * startTime / duration; - var endX = width * endTime / duration; - context.fillRect(startX, 0, endX - startX, height); - } - }, - - formatTime: function(time) - { - if (isNaN(time)) - time = 0; - var absTime = Math.abs(time); - var intSeconds = Math.floor(absTime % 60).toFixed(0); - var intMinutes = Math.floor((absTime / 60) % 60).toFixed(0); - var intHours = Math.floor(absTime / (60 * 60)).toFixed(0); - var sign = time < 0 ? '-' : String(); - - if (intHours > 0) - return sign + intHours + ':' + String('00' + intMinutes).slice(-2) + ":" + String('00' + intSeconds).slice(-2); - - return sign + String('00' + intMinutes).slice(-2) + ":" + String('00' + intSeconds).slice(-2) - }, - - updatePlaying: function() - { - this.setPlaying(!this.canPlay()); - }, - - setPlaying: function(isPlaying) - { - if (this.isPlaying === isPlaying) - return; - this.isPlaying = isPlaying; - - if (!isPlaying) { - this.controls.panel.classList.add(this.ClassNames.paused); - this.controls.playButton.classList.add(this.ClassNames.paused); - this.controls.playButton.setAttribute('aria-label', this.UIString('Play')); - this.showControls(); - } else { - this.controls.panel.classList.remove(this.ClassNames.paused); - this.controls.playButton.classList.remove(this.ClassNames.paused); - this.controls.playButton.setAttribute('aria-label', this.UIString('Pause')); - - this.hideControls(); - this.resetHideControlsTimer(); - } - }, - - showControls: function() - { - this.controls.panel.classList.add(this.ClassNames.show); - this.controls.panel.classList.remove(this.ClassNames.hidden); - - this.updateTime(); - this.setNeedsTimelineMetricsUpdate(); - }, - - hideControls: function() - { - this.controls.panel.classList.remove(this.ClassNames.show); - }, - - controlsAreAlwaysVisible: function() - { - return this.controls.panel.classList.contains(this.ClassNames.noVideo); - }, - - controlsAreHidden: function() - { - if (this.controlsAreAlwaysVisible()) - return false; - - var panel = this.controls.panel; - return (!panel.classList.contains(this.ClassNames.show) || panel.classList.contains(this.ClassNames.hidden)) - && (panel.parentElement.querySelector(':hover') !== panel); - }, - - removeControls: function() - { - if (this.controls.panel.parentNode) - this.controls.panel.parentNode.removeChild(this.controls.panel); - this.destroyCaptionMenu(); - }, - - addControls: function() - { - this.base.appendChild(this.controls.panelCompositedParent); - this.controls.panelCompositedParent.appendChild(this.controls.panel); - this.setNeedsTimelineMetricsUpdate(); - }, - - updateTime: function(forceUpdate) - { - if (!forceUpdate && this.controlsAreHidden()) - return; - - var currentTime = this.video.currentTime; - var timeRemaining = currentTime - this.video.duration; - this.controls.currentTime.innerText = this.formatTime(currentTime); - this.controls.timeline.value = this.video.currentTime; - this.controls.remainingTime.innerText = this.formatTime(timeRemaining); - }, - - updateReadyState: function() - { - this.updateStatusDisplay(); - }, - - setStatusHidden: function(hidden) - { - if (this.statusHidden === hidden) - return; - - this.statusHidden = hidden; - - if (hidden) { - this.controls.statusDisplay.classList.add(this.ClassNames.hidden); - this.controls.currentTime.classList.remove(this.ClassNames.hidden); - this.controls.timeline.classList.remove(this.ClassNames.hidden); - this.controls.remainingTime.classList.remove(this.ClassNames.hidden); - this.setNeedsTimelineMetricsUpdate(); - } else { - this.controls.statusDisplay.classList.remove(this.ClassNames.hidden); - this.controls.currentTime.classList.add(this.ClassNames.hidden); - this.controls.timeline.classList.add(this.ClassNames.hidden); - this.controls.remainingTime.classList.add(this.ClassNames.hidden); - } - }, - - trackHasThumbnails: function(track) - { - return track.kind === 'thumbnails' || (track.kind === 'metadata' && track.label === 'thumbnails'); - }, - - updateThumbnail: function() - { - for (var i = 0; i < this.video.textTracks.length; ++i) { - var track = this.video.textTracks[i]; - if (this.trackHasThumbnails(track)) { - this.controls.thumbnail.classList.remove(this.ClassNames.hidden); - return; - } - } - - this.controls.thumbnail.classList.add(this.ClassNames.hidden); - }, - - updateCaptionButton: function() - { - if (this.video.webkitHasClosedCaptions) - this.controls.captionButton.classList.remove(this.ClassNames.hidden); - else - this.controls.captionButton.classList.add(this.ClassNames.hidden); - }, - - updateCaptionContainer: function() - { - if (!this.host.textTrackContainer) - return; - - var hasClosedCaptions = this.video.webkitHasClosedCaptions; - var hasHiddenClass = this.host.textTrackContainer.classList.contains(this.ClassNames.hidden); - - if (hasClosedCaptions && hasHiddenClass) - this.host.textTrackContainer.classList.remove(this.ClassNames.hidden); - else if (!hasClosedCaptions && !hasHiddenClass) - this.host.textTrackContainer.classList.add(this.ClassNames.hidden); - - this.updateBase(); - this.host.updateTextTrackContainer(); - }, - - buildCaptionMenu: function() - { - var tracks = this.host.sortedTrackListForMenu(this.video.textTracks); - if (!tracks || !tracks.length) - return; - - this.captionMenu = document.createElement('div'); - this.captionMenu.setAttribute('pseudo', '-webkit-media-controls-closed-captions-container'); - this.captionMenu.setAttribute('id', 'audioTrackMenu'); - this.base.appendChild(this.captionMenu); - this.captionMenuItems = []; - - var offItem = this.host.captionMenuOffItem; - var automaticItem = this.host.captionMenuAutomaticItem; - var displayMode = this.host.captionDisplayMode; - - var list = document.createElement('div'); - this.captionMenu.appendChild(list); - list.classList.add(this.ClassNames.list); - - var heading = document.createElement('h3'); - heading.id = 'webkitMediaControlsClosedCaptionsHeading'; // for AX menu label - list.appendChild(heading); - heading.innerText = this.UIString('Subtitles'); - - var ul = document.createElement('ul'); - ul.setAttribute('role', 'menu'); - ul.setAttribute('aria-labelledby', 'webkitMediaControlsClosedCaptionsHeading'); - list.appendChild(ul); - - for (var i = 0; i < tracks.length; ++i) { - var menuItem = document.createElement('li'); - menuItem.setAttribute('role', 'menuitemradio'); - menuItem.setAttribute('tabindex', '-1'); - this.captionMenuItems.push(menuItem); - this.listenFor(menuItem, 'click', this.captionItemSelected); - this.listenFor(menuItem, 'keyup', this.handleCaptionItemKeyUp); - ul.appendChild(menuItem); - - var track = tracks[i]; - menuItem.innerText = this.host.displayNameForTrack(track); - menuItem.track = track; - - if (track === offItem) { - var offMenu = menuItem; - continue; - } - - if (track === automaticItem) { - if (displayMode === 'automatic') { - menuItem.classList.add(this.ClassNames.selected); - menuItem.setAttribute('tabindex', '0'); - menuItem.setAttribute('aria-checked', 'true'); - } - continue; - } - - if (displayMode != 'automatic' && track.mode === 'showing') { - var trackMenuItemSelected = true; - menuItem.classList.add(this.ClassNames.selected); - menuItem.setAttribute('tabindex', '0'); - menuItem.setAttribute('aria-checked', 'true'); - } - - } - - if (offMenu && displayMode === 'forced-only' && !trackMenuItemSelected) { - offMenu.classList.add(this.ClassNames.selected); - menuItem.setAttribute('tabindex', '0'); - menuItem.setAttribute('aria-checked', 'true'); - } - - // focus first selected menuitem - for (var i = 0, c = this.captionMenuItems.length; i < c; i++) { - var item = this.captionMenuItems[i]; - if (item.classList.contains(this.ClassNames.selected)) { - item.focus(); - break; - } - } - - }, - - captionItemSelected: function(event) - { - this.host.setSelectedTextTrack(event.target.track); - this.destroyCaptionMenu(); - }, - - focusSiblingCaptionItem: function(event) - { - var currentItem = event.target; - var pendingItem = false; - switch(event.keyCode) { - case this.KeyCodes.left: - case this.KeyCodes.up: - pendingItem = currentItem.previousSibling; - break; - case this.KeyCodes.right: - case this.KeyCodes.down: - pendingItem = currentItem.nextSibling; - break; - } - if (pendingItem) { - currentItem.setAttribute('tabindex', '-1'); - pendingItem.setAttribute('tabindex', '0'); - pendingItem.focus(); - } - }, - - handleCaptionItemKeyUp: function(event) - { - switch (event.keyCode) { - case this.KeyCodes.enter: - case this.KeyCodes.space: - this.captionItemSelected(event); - break; - case this.KeyCodes.escape: - this.destroyCaptionMenu(); - break; - case this.KeyCodes.left: - case this.KeyCodes.up: - case this.KeyCodes.right: - case this.KeyCodes.down: - this.focusSiblingCaptionItem(event); - break; - default: - return; - } - // handled - event.stopPropagation(); - event.preventDefault(); - }, - - destroyCaptionMenu: function() - { - if (!this.captionMenu) - return; - - this.captionMenuItems.forEach(function(item){ - this.stopListeningFor(item, 'click', this.captionItemSelected); - this.stopListeningFor(item, 'keyup', this.handleCaptionItemKeyUp); - }, this); - - // FKA and AX: focus the trigger before destroying the element with focus - if (this.controls.captionButton) - this.controls.captionButton.focus(); - - if (this.captionMenu.parentNode) - this.captionMenu.parentNode.removeChild(this.captionMenu); - delete this.captionMenu; - delete this.captionMenuItems; - }, - - updateHasAudio: function() - { - if (this.video.audioTracks.length) - this.controls.muteBox.classList.remove(this.ClassNames.hidden); - else - this.controls.muteBox.classList.add(this.ClassNames.hidden); - }, - - updateHasVideo: function() - { - if (this.video.videoTracks.length) - this.controls.panel.classList.remove(this.ClassNames.noVideo); - else - this.controls.panel.classList.add(this.ClassNames.noVideo); - }, - - updateVolume: function() - { - if (this.video.muted || !this.video.volume) { - this.controls.muteButton.classList.add(this.ClassNames.muted); - this.controls.volume.value = 0; - } else { - this.controls.muteButton.classList.remove(this.ClassNames.muted); - this.controls.volume.value = this.video.volume; - } - }, - - isAudio: function() - { - return this.video instanceof HTMLAudioElement; - }, - - clearHideControlsTimer: function() - { - if (this.hideTimer) - clearTimeout(this.hideTimer); - this.hideTimer = null; - }, - - resetHideControlsTimer: function() - { - if (this.hideTimer) - clearTimeout(this.hideTimer); - this.hideTimer = setTimeout(this.hideControls.bind(this), this.HideControlsDelay); - }, -}; diff --git a/Source/WebCore/Modules/mediacontrols/mediaControlsGtk.js b/Source/WebCore/Modules/mediacontrols/mediaControlsGtk.js deleted file mode 100644 index bca7776c8..000000000 --- a/Source/WebCore/Modules/mediacontrols/mediaControlsGtk.js +++ /dev/null @@ -1,258 +0,0 @@ -function createControls(root, video, host) -{ - return new ControllerGtk(root, video, host); -}; - -function ControllerGtk(root, video, host) -{ - Controller.call(this, root, video, host); -}; - -function contains(list, obj) -{ - var i = list.length; - while (i--) - if (list[i] === obj) - return true; - return false; -}; - -ControllerGtk.prototype = { - - createControls: function() - { - Controller.prototype.createControls.apply(this); - - this.controls.currentTime.classList.add(this.ClassNames.hidden); - this.controls.remainingTime.classList.add(this.ClassNames.hidden); - - this.controls.volumeBox.classList.add(this.ClassNames.hiding); - - this.listenFor(this.controls.muteBox, 'mouseout', this.handleVolumeBoxMouseOut); - this.listenFor(this.controls.muteButton, 'mouseover', this.handleMuteButtonMouseOver); - this.listenFor(this.controls.volumeBox, 'mouseover', this.handleMuteButtonMouseOver); - this.listenFor(this.controls.volume, 'mouseover', this.handleMuteButtonMouseOver); - this.listenFor(this.controls.captionButton, 'mouseover', this.handleCaptionButtonMouseOver); - this.listenFor(this.controls.captionButton, 'mouseout', this.handleCaptionButtonMouseOut); - - var enclosure = this.controls.enclosure = document.createElement('div'); - enclosure.setAttribute('pseudo', '-webkit-media-controls-enclosure'); - }, - - configureInlineControls: function() - { - this.controls.panel.appendChild(this.controls.playButton); - this.controls.panel.appendChild(this.controls.timeline); - this.controls.panel.appendChild(this.controls.currentTime); - this.controls.panel.appendChild(this.controls.remainingTime); - this.controls.panel.appendChild(this.controls.captionButton); - this.controls.panel.appendChild(this.controls.fullscreenButton); - this.controls.panel.appendChild(this.controls.muteBox); - this.controls.muteBox.appendChild(this.controls.muteButton); - this.controls.muteBox.appendChild(this.controls.volumeBox); - this.controls.volumeBox.appendChild(this.controls.volume); - this.controls.enclosure.appendChild(this.controls.panel); - }, - - shouldHaveControls: function() - { - return this.video.controls || this.isFullScreen(); - }, - - reconnectControls: function() - { - Controller.prototype.disconnectControls.apply(this, arguments); - - this.configureInlineControls(); - - if (this.shouldHaveControls()) - this.addControls(); - }, - - setStatusHidden: function(hidden) - { - }, - - updateTime: function(forceUpdate) - { - if (!forceUpdate && this.controlsAreHidden()) - return; - - var currentTime = this.video.currentTime; - var duration = this.video.duration; - - this.controls.currentTime.innerText = this.formatTime(currentTime); - this.controls.timeline.value = currentTime; - if (duration === Infinity || duration === NaN) - this.controls.remainingTime.classList.add(this.ClassNames.hidden); - else { - this.controls.currentTime.innerText += " / " + this.formatTime(duration); - this.controls.remainingTime.innerText = this.formatTime(duration); - if (this.controls.currentTime.classList.contains(this.ClassNames.hidden)) - this.controls.remainingTime.classList.remove(this.ClassNames.hidden); - } - - if (currentTime > 0) - this.showCurrentTime(); - }, - - showCurrentTime: function() - { - this.controls.currentTime.classList.remove(this.ClassNames.hidden); - this.controls.remainingTime.classList.add(this.ClassNames.hidden); - }, - - handlePlay: function(event) - { - Controller.prototype.handlePlay.apply(this, arguments); - this.showCurrentTime(); - if (!this.isLive) - this.showCurrentTime(); - }, - - handleTimeUpdate: function(event) - { - this.updateTime(); - }, - - handleMuteButtonMouseOver: function(event) - { - if (this.video.offsetTop + this.controls.enclosure.offsetTop < 105) { - this.controls.volumeBox.classList.add(this.ClassNames.down); - this.controls.panel.classList.add(this.ClassNames.down); - } else { - this.controls.volumeBox.classList.remove(this.ClassNames.down); - this.controls.panel.classList.remove(this.ClassNames.down); - } - this.controls.volumeBox.classList.remove(this.ClassNames.hiding); - return true; - }, - - handleVolumeBoxMouseOut: function(event) - { - this.controls.volumeBox.classList.add(this.ClassNames.hiding); - return true; - }, - - removeControls: function() - { - if (this.controls.enclosure.parentNode) - this.controls.enclosure.parentNode.removeChild(this.controls.enclosure); - this.destroyCaptionMenu(); - }, - - addControls: function() - { - this.base.appendChild(this.controls.enclosure); - }, - - updateReadyState: function() - { - if (this.host.supportsFullscreen && this.video.videoTracks.length) - this.controls.fullscreenButton.classList.remove(this.ClassNames.hidden); - else - this.controls.fullscreenButton.classList.add(this.ClassNames.hidden); - this.updateVolume(); - }, - - updateDuration: function() - { - Controller.prototype.updateDuration.apply(this, arguments); - if (this.isLive) - this.controls.timeline.max = 0; - }, - - setIsLive: function(live) - { - Controller.prototype.setIsLive.apply(this, arguments); - this.controls.timeline.disabled = this.isLive; - }, - - updatePlaying: function() - { - Controller.prototype.updatePlaying.apply(this, arguments); - if (!this.canPlay()) - this.showControls(); - }, - - handleCaptionButtonClicked: function(event) - { - this.handleCaptionButtonShowMenu(event) - return true; - }, - - buildCaptionMenu: function() - { - Controller.prototype.buildCaptionMenu.apply(this, arguments); - - this.listenFor(this.captionMenu, 'mouseout', this.handleCaptionMouseOut); - this.listenFor(this.captionMenu, 'transitionend', this.captionMenuTransitionEnd); - - this.captionMenu.captionMenuTreeElements = this.captionMenu.getElementsByTagName("*"); - - // Caption menu has to be centered to the caption button. - var captionButtonCenter = this.controls.panel.offsetLeft + this.controls.captionButton.offsetLeft + - this.controls.captionButton.offsetWidth / 2; - var captionMenuLeft = (captionButtonCenter - this.captionMenu.offsetWidth / 2); - if (captionMenuLeft + this.captionMenu.offsetWidth > this.controls.panel.offsetLeft + this.controls.panel.offsetWidth) - this.captionMenu.classList.add(this.ClassNames.out); - this.captionMenu.style.left = captionMenuLeft + 'px'; - // As height is not in the css, it needs to be specified to animate it. - this.captionMenu.height = this.captionMenu.offsetHeight; - this.captionMenu.style.height = 0; - }, - - destroyCaptionMenu: function() - { - this.hideCaptionMenu(); - }, - - showCaptionMenu: function() - { - this.captionMenu.style.height = this.captionMenu.height + 'px'; - }, - - hideCaptionMenu: function() - { - this.captionMenu.style.height = 0; - }, - - captionMenuTransitionEnd: function(event) - { - if (this.captionMenu.offsetHeight === 0) - Controller.prototype.destroyCaptionMenu.apply(this, arguments); - }, - - handleCaptionButtonMouseOver: function(event) - { - this.handleCaptionButtonShowMenu(event); - return true; - }, - - handleCaptionButtonShowMenu: function(event) - { - if (!this.captionMenu) - this.buildCaptionMenu(); - if (!contains(this.captionMenu.captionMenuTreeElements, event.relatedTarget)) - this.showCaptionMenu(); - return true; - }, - - handleCaptionButtonMouseOut: function(event) - { - if (this.captionMenu && !contains(this.captionMenu.captionMenuTreeElements, event.relatedTarget)) - this.hideCaptionMenu(); - return true; - }, - - handleCaptionMouseOut: function(event) - { - if (event.relatedTarget != this.controls.captionButton && - !contains(this.captionMenu.captionMenuTreeElements, event.relatedTarget)) - this.hideCaptionMenu(); - return true; - }, -}; - -Object.create(Controller.prototype).extend(ControllerGtk.prototype); -Object.defineProperty(ControllerGtk.prototype, 'constructor', { enumerable:false, value:ControllerGtk }); diff --git a/Source/WebCore/Modules/mediacontrols/mediaControlsiOS.css b/Source/WebCore/Modules/mediacontrols/mediaControlsiOS.css deleted file mode 100644 index 87d861bd2..000000000 --- a/Source/WebCore/Modules/mediacontrols/mediaControlsiOS.css +++ /dev/null @@ -1,732 +0,0 @@ -/* - * Copyright (C) 2012, 2013, 2014, 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* You'll see a lot of !important rules in this file. This is because - the inheritance and specificity of Shadow DOM trees is slightly - tricky. The page might have accidentally set a style and we have - to make sure it is reset. */ - -audio { - min-width: 260px; - height: 39px; -} - -body:-webkit-full-page-media { - background-color: rgb(38, 38, 38); -} - -video:-webkit-full-page-media { - margin: auto; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; -} - -video:-webkit-full-page-media::-webkit-media-controls-panel { - bottom: 0px; -} - -::-webkit-media-controls { - width: inherit; - height: inherit; - position: relative; - display: -webkit-flex !important; - -webkit-align-items: stretch; - -webkit-justify-content: flex-end; - -webkit-flex-direction: column; - font-family: -apple-system; - overflow: hidden; -} - -video::-webkit-media-controls-panel input[type="button"], -audio::-webkit-media-controls-panel input[type="button"], -video::-webkit-media-controls-panel button, -audio::-webkit-media-controls-panel button { - padding: 0; - border: none; - -webkit-appearance: none; -} - -video::-webkit-media-controls-inline-playback-placeholder, -audio::-webkit-media-controls-inline-playback-placeholder { - display: block; - z-index: 0; - width: 100%; - height: 100%; - background-color: black; - background-repeat: no-repeat; - background-position: 50% 50%; - background-size: 100% 50%; -} - -video::-webkit-media-controls-inline-playback-placeholder.hidden, -audio::-webkit-media-controls-inline-playback-placeholder.hidden { - display: none; -} - -video::-webkit-media-text-track-container, -audio::-webkit-media-text-track-container { - position: relative; - -webkit-flex: 1 1 auto; -} - -video::-webkit-media-controls-panel-container { - -webkit-transform: translateZ(0); - width: 100%; - direction: ltr; - height: 50px; - position: absolute; - bottom: 0; - pointer-events: none; -} - -audio::-webkit-media-controls-panel-container { - width: 100%; - direction: ltr; - height: 39px; - position: absolute; - bottom: 0; -} - -video::-webkit-media-controls-panel-background { - -webkit-transform: translateZ(0); - width: 101%; /* Due to some rounding issues we make this a little bit wider than should be necessary. */ - height: 51px; /* And taller. */ - -webkit-appearance: media-controls-light-bar-background; - transition: opacity 0.25s linear; - opacity: 0; - pointer-events: none; - bottom: 0; - position: absolute; -} - -audio::-webkit-media-controls-panel-background { - display: none; -} - -video::-webkit-media-controls-panel-background.show, -video::-webkit-media-controls-panel-background.paused { - opacity: 1; -} - -audio::-webkit-media-show-controls { - display: none !important; -} -video::-webkit-media-show-controls { - position: absolute; - left: 0; - bottom: 0; - display: block; - margin: 0; - padding: 0; - width: 100%; - height: 10px; - opacity: 0; - border: 0; - background: none; - -webkit-appearance: none; -} - -audio::-webkit-media-controls-panel, -video::-webkit-media-controls-panel { - box-sizing: border-box; - position: absolute; - bottom: 0; - width: 100%; - padding: 0; - - -webkit-user-select: none; - - display: -webkit-flex; - -webkit-flex-direction: row; - -webkit-flex-wrap: nowrap; - -webkit-justify-content: flex-start; - -webkit-align-items: center; - - transition: opacity 0.25s linear; - -webkit-transform-origin: bottom left; -} - -video::-webkit-media-controls-panel .hidden, -audio::-webkit-media-controls-panel .hidden, -video::-webkit-media-controls-panel .dropped, -audio::-webkit-media-controls-panel .dropped { - display: none; -} - -video::-webkit-media-controls-panel { - height: 50px; - opacity: 0; - pointer-events: none; - -webkit-transform: translate3d(0, 0, 0); -} - -audio::-webkit-media-controls-panel { - height: 39px; - background-color: rgba(212, 212, 212, 1); -} - -video::-webkit-media-controls-panel.show, -video::-webkit-media-controls-panel.paused { - pointer-events: auto; - opacity: 1; -} - -video::-webkit-media-controls-panel.picture-in-picture { - pointer-events: none; -} - -video::-webkit-media-controls-rewind-button, -audio::-webkit-media-controls-rewind-button, -video::-webkit-media-controls-panel .mute-box, -audio::-webkit-media-controls-panel .mute-box, -video::-webkit-media-controls-mute-button, -audio::-webkit-media-controls-mute-button, -video::-webkit-media-controls-volume-max-button, -video::-webkit-media-controls-panel .volume-box, -audio::-webkit-media-controls-panel .volume-box, -audio::-webkit-media-controls-volume-slider, -video::-webkit-media-controls-volume-slider { - display: none !important; -} - -video::-webkit-media-controls-start-playback-button { - -webkit-appearance: none; - position: absolute; - width: 72px; - height: 72px; - left: calc(50% - 36px); - top: calc(50% - 36px); - -webkit-clip-path: circle(36px); - -webkit-transform: translate3d(0, 0, 0); -} - -video::-webkit-media-controls-start-playback-background { - -webkit-appearance: none; - position: absolute; - width: 72px; - height: 72px; - background-color: rgba(255, 255, 255, 0.2); - -webkit-backdrop-filter: blur(10px) saturate(200%); -} - -video::-webkit-media-controls-start-playback-tint { - -webkit-appearance: none; - position: absolute; - width: 72px; - height: 72px; - background-color: rgb(210, 210, 210); - mix-blend-mode: darken; -} - -video::-webkit-media-controls-start-playback-button .webkit-media-controls-start-playback-glyph { - -webkit-appearance: none; - position: absolute; - width: 72px; - height: 72px; - opacity: 0.45; - mix-blend-mode: plus-darker; - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIwAAACMCAMAAACZHrEMAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA/1BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD64ociAAAAVHRSTlMAtCT5hQzkWQHAMPuVEetoAs46/qMZ83UG2Uiw94QL4Ve/LZMQZM04oPFz1keuIfaDCVS+KpDqYsmdGO9yBNVEHn9Ru4znj+ZdpstAIIjpagNDtxJhxoj+AAAAAWJLR0QAiAUdSAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAdlJREFUeNrt2udSwkAYhWE09iCCsSv2rogdK2LvYjn3fy3mjwaUkqzZ3W+c817BM8yZDyYhkWCMMcYYY4wxxhhjjMVeS6ttQUVw2tptGwIM0NHZZVsRYIDuHtuMCgzcZK9tSIABUn1p25QAA2T6bVsqMPAGBuVggKHhETkYYHRMEAYYt3iSf2EwkZ2UgwGmpgVhgJlZQRi4c/NyMP5JXkjLwQCLS4Iw8JYNn2Q0bGXV6ElGk9bWBWGA3IYgDPKbW3Iw/kneFoQBdnYFYeDuGTjJYTHAfiEtBwMc6D7JUTDwDo/kYIDjk1M5GKB4Jgjjn+SSIAzy55pOsgrGP8kXgjDApY6TrIqBexX/SVbGANeFuB8y/QED3MjB3N6J+WTy2fgfTCpSvPtS7BRVzIOe72+lsej6ZSNjLIoYPWNRw2Qe9VEiYrSNJTpG41giY3JPminhMXrHEgmjeywRMM6zofdjYcZi7DG1jLGEw7yYGUsYjKPhd64qxtxYmmJMjqUJJlV+NW6pgzE9lkYY42Opjym+2aHUwKTKOh8HRcJYGktNjOU/sFSNxep75CqMzbH8wOh43KKKeTfybiAUxvpYAoyAsXxh3OSHbcN3MsbCGGOMMcYYY4wxxv57n0aw2iHhyI0VAAAAAElFTkSuQmCC'); - background-repeat: no-repeat; - background-position: 50% 50%; - background-size: 100% 100%; -} - -video::-webkit-media-controls-start-playback-button .webkit-media-controls-start-playback-background.active { - background-color: rgba(192, 192, 192, 0.2); -} - -video::-webkit-media-controls-start-playback-button .webkit-media-controls-start-playback-glyph.failed { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIwAAACMCAMAAACZHrEMAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAACMVBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACad/teAAAAunRSTlMAtCQ4MfmFDAXX+5US5FkBc+tpAsAwGPHOOxFC7v6kGWgUl/3zdgY6xdpIo1zmsXWK94TZJrfhWLBP278tCwl79JMQVx6oZUDTzQRs76Bkm/Izx9ZHrF+uIdUOjPaDcCq5VBadUd6+N32PYujqjkHJvJBScoFDH61F6X/wROCeF7rLcfpjYZG7NCt+VuffbtQjrw+pYKbcUKKcJzltCmZd2MYvP/WYatCLZx1M4raIs8J3/M89PLK1LgNpky35AAAAAWJLR0QAiAUdSAAAAAlwSFlzAAALEgAACxIB0t1+/AAABHZJREFUeNrtmvlfE0cYxlNIBBJLEmMh1sYYg9EiqS0ttBJLWouiGK1iNVKi2EIPsK222tN6YA/rra14Y1sPUEA8wGv+Omc3M2EnhNlssm/45f3+NiSfmSdv3ufZzbtYLAiCIAiCIAiCIAiCIAiCmM4LRYU7q9iq8wZim1FSIC2lZXbHTLkYQl4sdxZEjIue5Z7lkYshZPZLBdBSUame5Z2jI4bYHS+Di5n7SvIs3zy/XAyt33yPkZ1zIbAgmDyramFILobWbxF4cayL2VmvVuuIIb4lfoObG8ZZE2aHvZYpUoiWqqUhw/sbpOR1W/KsN2onRwoRebM6hwOM8VYdO6v+bR0xhLwDH8nLGthZkeU6Ymj93oVW0xh9j0XK+yvkYmj9PgAvTtNKHimrNJFCMpJePwCaV7Oz1hTriEmvHwQta2MsUtbxSCFT4V4PH8kfskje4ArJxQj1g2JjKztr00fKcrNEzUT9wHBu4ZEc30qXc9skcipd4JH8cTuL5MS2RtpI22MSOcn6gdKxg0fKJ3T1aWdQIketHyxdn7GzPu+gqy9aJWrU+sHS+GWCRUo3jRRPz06JHLV+sDRxJ33VQyNlxdd2iRy1frB8w520S4mUjt0SNfZv4SOZOynYWUGX39VL5Kj1gyXlpNieFtpIexMSObvgIznlpLbv6eqHuESNT60fHIKTfmyif/lJFslq/cD4WXBS4hcaKaWufRI5bb/CiUl30v4uuvIf8EnkxJvgxFAnHbRonHRIiZTiXokatX5AYmgnHNY66bd2pZF+d0vk1HfBiUl3UvgPJ22kP+0SOUcgIjm1u+ik1r/o6mhEosbebn4kazrhmNZJwc4AffW4LJJP9Jg9ZNLuflJwUuyU0ki1skjuBhST7qTTzXR15uxUUsI1kJVRnfS31kn/KI1UXZbR37XmDyYnf95zWiclorSRQq6q9Hf5+iCSL8NnFp10/gJd+S+KkdwLc/3O9A0ELwlOqrtMV1e8muJB3dlk7s3YVeqkfu4kWzttD881N1yzSMUQslpwUvhfpZEcdqhm0RHDnfQfW/2vzP2vR7w34KRIf/jfFJwUvKU0EuxtMJHRsMyicVJsAPIuT1dMupMGm6dVDLHdVpx0hznJ1zc0nWLYJUh1kkJVFHBIoi+GkEi/RXESb6Th6RQTT46pneUj7A93oebWulK8E01bUsuGTLZRmBDWkeIWL0NF93gjgTxKlFtp8n1udQN77b7eo1iTxcQz9UboAYvkh45A4cSMTZVw/j4Wye4Bk68OUzaLLPvHeSR7HxVAjE3nR5FnIBXJZs6ts28WkYCDP4p9YF4kZ5CS5dDDep+9v8G0R4nGmkXAWc7n/o9NimSDzSJSMsoj2Zz7YlHLE6MfsYg/ih0pN1lMWy5f/jCP5MhTE8Vk3ywioSiLZLsj3yEJl5LPuGUoFck1poipy28Q1TyY3GaWCWJyahaBlgFl7j/2LG8xuTaLSOBW0Dee5x5E75+ysscazXeHPJsFQRAEQRAEQRAEQRAEQbLiOSQmbq1EhbJeAAAAAElFTkSuQmCC'); -} - -/* ================== ALL INLINE BUTTONS ====================== */ - -video::-webkit-media-controls-play-button, -audio::-webkit-media-controls-play-button, -video::-webkit-media-controls-fullscreen-button, -audio::-webkit-media-controls-fullscreen-button, -video::-webkit-media-controls-wireless-playback-picker-button, -audio::-webkit-media-controls-wireless-playback-picker-button, -video::-webkit-media-controls-picture-in-picture-button, -audio::-webkit-media-controls-picture-in-picture-button { - -webkit-appearance: none; - display: block; - padding: 0; - border: 0; - -webkit-user-select: none; - background-repeat: no-repeat; - background-position: 50% 50%; - mix-blend-mode: plus-darker; - opacity: 0.55; - -webkit-mask-position: 50% 50%; - -webkit-mask-repeat: no-repeat; - -webkit-mask-origin: border-box; - background-color: black; - transition: background-color 250ms; -} - -video::-webkit-media-controls-play-button, -video::-webkit-media-controls-fullscreen-button, -video::-webkit-media-controls-wireless-playback-picker-button, -video::-webkit-media-controls-picture-in-picture-button { - -webkit-transform: translate3d(0, 0, 0); -} - -video::-webkit-media-controls-play-button:active, -audio::-webkit-media-controls-play-button:active, -video::-webkit-media-controls-fullscreen-button:active, -audio::-webkit-media-controls-fullscreen-button:active, -audio::-webkit-media-controls-wireless-playback-picker-button:active, -video::-webkit-media-controls-wireless-playback-picker-button:active, -video::-webkit-media-controls-picture-in-picture-button:active, -audio::-webkit-media-controls-picture-in-picture-button:active { - mix-blend-mode: normal; - opacity: 1; - background-color: white; - transition: background-color 0ms; -} - -/* ================== PLAY BUTTON ====================== */ - -audio::-webkit-media-controls-play-button, -video::-webkit-media-controls-play-button { - margin-left: 4px; - -webkit-mask-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAsCAYAAAANUxr1AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFVJREFUeNrs2bENgEAMA0AHsf/EIB5GcIGgOEvpIuf6TJIjXfZyv+qfe67ywJT7Vf+WnwUICAgICAgICAgICAgICAgICAgICAjoyzxvgvPlG1X/EmAASwgGTpkrSW0AAAAASUVORK5CYII='); - -webkit-mask-size: 18px 22px; - -webkit-order: 1; -} - -audio::-webkit-media-controls-play-button { - width: 42px; - height: 39px; -} - -video::-webkit-media-controls-play-button { - width: 44px; - height: 50px; -} - -audio::-webkit-media-controls-play-button.paused, -video::-webkit-media-controls-play-button.paused { - -webkit-mask-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACoAAAAsCAYAAAATmipGAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAUZJREFUeNrU2S8sRWEYgPFzD7PZbDYbQSAoBBKFwgQTmKRpJE3SaBKFRKJJJphiCslNt1AERRBsNpvN/DmeL7ybGfLzne3Xn517d873vqcsimIOtSKDq0Id0zmEhktM5hAazjGWQ2g4xUgOocknjjFkDw0fOMSAPfR78AH67KHhDXvotYeGV+yg2x4aXrCFLntoeMYGOuyh4QnraLeHhkesos0eGh6wglZ7aLjHMlrsoeEOi2i2h4ZbLKC0h4ZrzP8XXMk0MPvbeFRJXf0cjyq5NB5NlIX/qsX/1non6/afvvHXrsESeGN/PMUDv8n8Cl0yv0L1hxL9MU9/cE6jyJp5FNEPd2lc3kSneQGxbV5ApJXOLnqsK5137JuXZLF27Dcvco8waF7knmDYvBo/w6j5Y8MFxs2fb9LEN2UfnmaKDD4xfgkwANpCXZrruKGvAAAAAElFTkSuQmCC'); - -webkit-mask-size: 21px 22px; -} - -/* ================== FULLSCREEN BUTTON ====================== */ - -video::-webkit-media-controls-fullscreen-button { - width: 44px; - height: 50px; - -webkit-mask-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAO5JREFUeNrs2F8KwjAMBvAoXsID6GEUPIKPw2sLPiu+CCIYO1nFhf1pWkw+YR9kTyv8KCNpR0TEyjqSUZiZ5vQH+d6dZ6gDDIy5BbyjISVwi4aUQEJDdgGhkH1AGOQQEAI5BnRHpgBdkalAN2QEnpsiNGQEamKKzAFK5CPUCg0YkbdQe8QdjFkifoPmjRr+wDoBJ2Bh1r9uRaW4UzNxKsQ2sxFjsUID1tmVIK0adQ7y/QfDcpJokeZALdIFqEG6AVORrsAUpDtwDAkBHELCAPuQUMAuJBxQIj/AheUVI2eRJfCifP9aP2boV7uXAAMArhj6EAChbh4AAAAASUVORK5CYII='); - -webkit-mask-size: 20px 20px; - -webkit-order: 5; -} - -/* ================== AIRPLAY BUTTON ====================== */ - -audio::-webkit-media-controls-wireless-playback-picker-button, -video::-webkit-media-controls-wireless-playback-picker-button { - -webkit-mask-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACoAAAAkCAYAAAD/yagrAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAARlJREFUeNrsmDEOgjAUhtuYMLgwuTG6Mrt7AC/gCVycHLwBN+AEXIADuDO76ubm5OJgYnw+kldDiEb6aElJ3ku+gYSWL4/yl1QrpUCNoLSIehbVgfmBiIqoiIqoiIqoiIpoUKLmAhz+7u2QpUPRj5tL0TXyQm5IGqpo3cVHY64LkoQmmlIXocURiUMRnSHnL5KGAxK5Fu1CiUxooilSdRhTNBIlpk7bPtfq5orkFMmWFmOzRqcSWsNeRE/0mk3ljK5sOqzrn6Kc2jMka57IaqjdwmQlMLkjC9+S7azkckXmviRt15TtmndSnK/UNkV6Fzf3OLnMroh2FvBM3vcArRhA0rDlimYDSrIzdjOw5N+M1QCjOMdVbwEGAJbOn8QOMeI8AAAAAElFTkSuQmCC'); - -webkit-mask-size: 21px 18px; - -webkit-order: 3; -} - -audio::-webkit-media-controls-wireless-playback-picker-button { - width: 44px; - height: 39px; -} - -video::-webkit-media-controls-wireless-playback-picker-button { - width: 44px; - height: 50px; -} - -audio::-webkit-media-controls-wireless-playback-picker-button.playing, -video::-webkit-media-controls-wireless-playback-picker-button.playing { - opacity: 1; - mix-blend-mode: normal; - background-color: -apple-wireless-playback-target-active; -} - -/* ================== PICTURE IN PICTURE BUTTON ====================== */ - -video::-webkit-media-controls-picture-in-picture-button { - width: 35px; - height: 44px; - -webkit-order: 5; - -webkit-mask-size: 23px 18px; - -webkit-mask-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAAAkCAYAAAD2IghRAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAANhJREFUeNrslzEOwjAMRR2UA3AQ7sLKwsTEglg6sTIgLgs7qCZBRbIsWpDayHH1v/SHJmn0ZFutHYiIqX4F+cDMtCCncgseh1JiLJ5lxH+Br2qGZ2Gpa/IjeVMZ1/ur0ndgLdaeydsvF9/7LrYEz7oo+J0X8Kyz2GuT917As04K/uAFPKtR5xov4FnHLuIy+i7AqavxVr1jAh7H/HbRZE3QZGndBvaW1k1Z6VqdHtjzIBELZrHoKIfRzbpUxqY4IOJzLpWAiAMc4AAHOMAB/m9T9Bn1veklwACtBYmnlYBaIQAAAABJRU5ErkJggg=='); -} - -video::-webkit-media-controls-picture-in-picture-button.return-from-picture-in-picture { - -webkit-mask-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAAAkCAYAAAD2IghRAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAOZJREFUeNpiZGBg+M8w+AEjMuf///8MTAxDFAxZh7Pgi5IBBv+HZYgPS4f/JwJ/GA1xCjMnIfAejf9poHPvfyy5GFvS6KdjyYPLXeAKiFiH/0ZiT6GT46ni8CAg/onEn0WH/EEVh4OAL5rjFwIx81BwOAh4APE3JPGlNHQ8VR0OAs5A/BVJbjUQsw0Fh4OAHRB/RpLPG0wOJwSsoTXnfBolF5o5HARUBqL2pYbDB6bGBDqchYYlAk27cqPt8YFuHVIaxYyjIT6ckwrjaIiPOnzU4aMOH3X4qMNHHU5sowjWmxhqACDAAI3lmdvpn4aTAAAAAElFTkSuQmCC'); -} - -/* ================== SPACER ====================== */ - -video::-webkit-media-controls-spacer, -audio::-webkit-media-controls-spacer { - -webkit-appearance: none !important; - -webkit-flex: 1 1 0; /* Should be the same as the timeline container. */ - -webkit-order: 2; - height: 8px; - margin: 0; - background-color: transparent !important; -} - -/* ================== TIMELINE ====================== */ - -video::-webkit-media-controls-timeline, -audio::-webkit-media-controls-timeline { - -webkit-appearance: none !important; - -webkit-flex: 1 1 0; - height: 8px; - margin: 0; - background-color: transparent !important; - background-size: 100% 100%; - border: none !important; - border-radius: 0 !important; - box-sizing: content-box !important; -} - -video::-webkit-media-controls-timeline { - -webkit-transform: translate3d(0, 0, 0); - mix-blend-mode: plus-darker; -} - -audio::-webkit-media-controls-timeline::-webkit-slider-runnable-track, -video::-webkit-media-controls-timeline::-webkit-slider-runnable-track { - -webkit-appearance: none !important; - background: none !important; - border: none !important; -} - -video::-webkit-media-controls-timeline::-webkit-slider-thumb, -audio::-webkit-media-controls-timeline::-webkit-slider-thumb { - -webkit-appearance: none !important; - width: 15px; - height: 50px; - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAiCAYAAABIiGl0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAxNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDE0IDc5LjE1Njc5NywgMjAxNC8wOC8yMC0wOTo1MzowMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iUGl4ZWxtYXRvciAyLjIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTkwQ0UwODdBQTcxMTFFNEE5QTZGQTVGMjFBNkUxN0UiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTkwQ0UwODhBQTcxMTFFNEE5QTZGQTVGMjFBNkUxN0UiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1OTBDRTA4NUFBNzExMUU0QTlBNkZBNUYyMUE2RTE3RSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1OTBDRTA4NkFBNzExMUU0QTlBNkZBNUYyMUE2RTE3RSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pofoz4wAAAJGSURBVHjaxJfNTsJAEMfbLmoNaKIhIE18A+LReOXmi/gQnnwSLz6Fnjh4Id4kHElI5EDwpIkgImWdf/Nfs5ISCrR1kkmg7c5vZz/mw3WSy66oL7ojqqiQkPotOhGdaq1XGnMTvC+KlprN5kW9Xr8sFotnhUKhCsUHs9lsCB2NRu1Op3PfaDRa8vhDdCSqnQ0E3lX7/f6NGH7RCQXfYgzG0sZacthut6/G4/Gj3lAwFjZgKyn0qNfrXYdh+Ka3FNiALdhc6Sk+1CkL4Us997E0aXga5zmX3Y87vdVt9jTJnvPA/blJJZxEnbHwtJds8Mk6V2ZTAQMsAD1EJAQHpdSpk7GAARaYAPuISE5OQpYfeYwwmBeYrMhjZeJuHkKWAtj7B7DnJchQaQsylgvwHGktL6qwXsH0TE7NETw091gjiecFFtYzmNFSo3LICyysBzBxsI5xoWUJWllHL8lSfTnViFyTyGO4PhgMbrP2lgxNpnPAdBXkkBYDsg48lqbRDLrd7t18Pn9P21PYhG3zl8yoXsY+1zCjDEufgIxjMqPCHMm5wpdBBsVeQK2QpUzZs8dKsGY+SrG8DSxvj8j6DdOKHUPZhkO3KOiDBWiZDGW3MC4f7FPVYvKQyuE8YQvzFJMUcJg+qfit3YVKc4clqB8H3zAThWzmJmzstGN1fI511LVJXYzl7hZQ00F+2dA4sH3P7Am4a0zAeDklEODZYueoVgz+DS4rWk5tTdj2cmqt4tr9sccJFqyG3N4CGxrSu3AZ0MiPAAMAZrLkuVVmRJsAAAAASUVORK5CYII='); - background-repeat: no-repeat; - background-size: 15px 17px; - background-position: 0px 18px; - background-color: transparent !important; - border: none !important; - -webkit-transform: rotateZ(0deg); -} - -video::-webkit-media-controls-timeline::-webkit-slider-thumb:active, -audio::-webkit-media-controls-timeline::-webkit-slider-thumb:active { - background-color: transparent !important; -} - -audio::-webkit-media-controls-timeline::-webkit-slider-thumb { - height: 39px; - background-position: 0px 12px; -} - -video::-webkit-media-controls-current-time-display, -video::-webkit-media-controls-time-remaining-display, -audio::-webkit-media-controls-current-time-display, -audio::-webkit-media-controls-time-remaining-display { - -webkit-user-select: none; - -webkit-flex: 0 0 0; - display: -webkit-flex; - -webkit-align-items: center; - overflow-y: hidden; - overflow-x: hidden; - letter-spacing: normal; - word-spacing: normal; - line-height: normal; - text-transform: none; - text-indent: 0px; - text-decoration: none; - color: black; - mix-blend-mode: plus-darker; - opacity: 0.55; - height: 50px; - font-size: 13px; - font-family: -apple-system-monospaced-numbers; -} - -audio::-webkit-media-controls-current-time-display, -video::-webkit-media-controls-current-time-display { - min-width: 32px; - -webkit-justify-content: flex-end; - padding-right: 6px; -} - -audio::-webkit-media-controls-time-remaining-display, -video::-webkit-media-controls-time-remaining-display { - min-width: 38px; - -webkit-justify-content: flex-start; - padding-left: 6px; - margin-right: 6px; -} - -video::-webkit-media-controls-timeline-container, -audio::-webkit-media-controls-timeline-container { - display: -webkit-flex; - -webkit-flex-direction: row; - -webkit-align-items: center; - -webkit-user-select: none; - -webkit-flex: 1 1 0; /* Any changes here should also be made on the spacer. */ - position: relative; - padding: 0; - -webkit-order: 2; - -webkit-text-size-adjust: auto; -} - -audio::-webkit-media-controls-timeline-container { - padding-right: 10px; -} - -audio::-webkit-media-controls-current-time-display.three-digit-time, -video::-webkit-media-controls-current-time-display.three-digit-time { - min-width: 31px; -} - -audio::-webkit-media-controls-time-remaining-display.three-digit-time, -video::-webkit-media-controls-time-remaining-display.three-digit-time { - min-width: 40px; -} - -audio::-webkit-media-controls-current-time-display.four-digit-time, -video::-webkit-media-controls-current-time-display.four-digit-time { - min-width: 40px; -} - -audio::-webkit-media-controls-time-remaining-display.four-digit-time, -video::-webkit-media-controls-time-remaining-display.four-digit-time { - min-width: 49px; -} - -audio::-webkit-media-controls-current-time-display.five-digit-time, -video::-webkit-media-controls-current-time-display.five-digit-time { - min-width: 51px; -} - -audio::-webkit-media-controls-time-remaining-display.five-digit-time, -video::-webkit-media-controls-time-remaining-display.five-digit-time { - min-width: 60px; -} - -audio::-webkit-media-controls-current-time-display.six-digit-time, -video::-webkit-media-controls-current-time-display.six-digit-time { - min-width: 60px; -} - -audio::-webkit-media-controls-time-remaining-display.six-digit-time, -video::-webkit-media-controls-time-remaining-display.six-digit-time { - min-width: 69px; -} - -/* ================== STATUS DISPLAY ====================== */ - -video::-webkit-media-controls-status-display, -audio::-webkit-media-controls-status-display { - - overflow: hidden; - font-family: -apple-system; - letter-spacing: normal; - word-spacing: normal; - line-height: normal; - text-transform: none; - text-indent: 0px; - text-decoration: none; - color: black; - mix-blend-mode: plus-darker; - opacity: 0.55; - -webkit-order: 2; -} - -/* ================== CAPTIONS ====================== */ - -video::-webkit-media-text-track-container { - position: relative; - width: 100%; - overflow: hidden; - padding-bottom: 5px; - z-index: 0; - - text-align: center; - color: rgba(255, 255, 255, 1); - - letter-spacing: normal; - word-spacing: normal; - text-transform: none; - text-indent: 0; - text-decoration: none; - pointer-events: none; - -webkit-user-select: none; - word-break: break-word; - - -webkit-flex: 1 1; - - -webkit-line-box-contain: block inline-box replaced; -} - -video::cue { - background-color: rgba(0, 0, 0, 0.8); -} - -video::-webkit-media-text-track-display { - position: absolute; - overflow: hidden; - white-space: pre-wrap; - -webkit-box-sizing: border-box; - font: 22px sans-serif; -} - -video::-webkit-media-text-track-display-backdrop { - display: inline-block; -} - -video::cue(:future) { - color: gray; -} - -video::-webkit-media-text-track-container b { - font-weight: bold; -} - -video::-webkit-media-text-track-container u { - text-decoration: underline; -} - -video::-webkit-media-text-track-container i { - font-style: italic; -} - -/* ==================== PLAYBACK PLACARD ==================== */ - -video::-webkit-media-controls-wireless-playback-status, -audio::-webkit-media-controls-wireless-playback-status { - display: block; - position: absolute; - left: 0px; - top: 0px; - width: 100%; - height: 100%; - background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 131 90"><g fill="none" stroke="-apple-system-gray" stroke-width="4"><rect x="2" y="2" width="127" height="76"/><line x1="30" y1="88" x2="101" y2="88"/></g></svg>'); - background-color: rgb(51, 51, 53); - background-repeat: no-repeat; - background-position: 50% calc(.5 * (100% - 25px) - 21pt); - background-size: 131px auto; - color: -apple-system-gray; - font: -apple-system; - font-weight: 400; - vertical-align: text-bottom; -} - -video::-webkit-media-controls-wireless-playback-text, -audio::-webkit-media-controls-wireless-playback-text { - cursor: default; - position: absolute; - width: 100%; - top: calc(.5 * (100% - 25px) + (.5 * (90px + 42pt) - 42pt)); - -webkit-user-select: none; - margin: 0px; - height: 42pt; -} - -video::-webkit-media-controls-wireless-playback-text-top, -audio::-webkit-media-controls-wireless-playback-text-top { - position: absolute; - top: 15pt; - width: 100%; - line-height: 12pt; - height: 12pt; - font-size: 12pt; - text-align: center; - margin: 0px; - color: -apple-system-gray; -} - -video::-webkit-media-controls-wireless-playback-text-bottom, -audio::-webkit-media-controls-wireless-playback-text-bottom { - position: absolute; - bottom: 0; - left: 5%; - width: 90%; - line-height: 10pt; - height: 10pt; - font-size: 10pt; - text-align: center; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - margin: 0px; -} - -video::-webkit-media-controls-wireless-playback-status.small, -audio::-webkit-media-controls-wireless-playback-status.small { - background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 62 43"><g fill="none" stroke="rgb(146,146,146)" stroke-width="2"><rect x="1" y="1" width="60" height="36"/><line x1="14" y1="42" x2="48" y2="42"/></g></svg>'); - background-position: 50% calc(.5 * (100% - 25px) - 5pt); - background-size: 62px auto; -} - -video::-webkit-media-controls-wireless-playback-text-top.small, -audio::-webkit-media-controls-wireless-playback-text-top.small { - top: 4pt; -} - -video::-webkit-media-controls-wireless-playback-text-bottom.small, -audio::-webkit-media-controls-wireless-playback-text-bottom.small { - display: none; -} - -video::-webkit-media-controls-wireless-playback-status.picture-in-picture, -audio::-webkit-media-controls-wireless-playback-status.picture-in-picture -{ - background-size: 304px auto; - background-position: 50% calc(.5 * (100% - 25px)); - background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 304 150"><g fill="none" stroke="-apple-system-gray" stroke-width="3"><path d="m 172,106 -81,0 c -3.5,0 -6,-2.5 -6,-6 l 0,-89 c 0,-3.5 2.5,-6 6,-6 l 122,0 c 3.5,0 6,2.5 6,6 l 0,57" /><path d="m 233,119 -53,0 c -3,0 -3,-0 -3,-3 l 0,-40 c 0,-3 0,-3 3,-3 l 53,0 c 3,0 3,0 3,3 l 0,40 c 0,3 0,3 -3,3 z" /></g></svg>'); -} - -video::-webkit-media-controls-wireless-playback-text-top.picture-in-picture, -audio::-webkit-media-controls-wireless-playback-text-top.picture-in-picture { - top: initial; - bottom: 0; -} - -video::-webkit-media-controls-wireless-playback-text-bottom.picture-in-picture, -audio::-webkit-media-controls-wireless-playback-text-bottom.picture-in-picture { - display: none; -} - -video::-webkit-media-controls-wireless-playback-status.hidden, -audio::-webkit-media-controls-wireless-playback-status.hidden { - display: none; -} - -/* When PiP is active, we don't want the controls container showing. */ -video::-webkit-media-controls-panel-container.picture-in-picture { - opacity: 0; - pointer-events: none; -} - diff --git a/Source/WebCore/Modules/mediacontrols/mediaControlsiOS.js b/Source/WebCore/Modules/mediacontrols/mediaControlsiOS.js deleted file mode 100644 index ccede22ba..000000000 --- a/Source/WebCore/Modules/mediacontrols/mediaControlsiOS.js +++ /dev/null @@ -1,616 +0,0 @@ -function createControls(root, video, host) -{ - return new ControllerIOS(root, video, host); -}; - -function ControllerIOS(root, video, host) -{ - this.doingSetup = true; - this._pageScaleFactor = 1; - - this.timelineContextName = "_webkit-media-controls-timeline-" + host.generateUUID(); - - Controller.call(this, root, video, host); - - this.setNeedsTimelineMetricsUpdate(); - - this._timelineIsHidden = false; - this._currentDisplayWidth = 0; - this.scheduleUpdateLayoutForDisplayedWidth(); - - host.controlsDependOnPageScaleFactor = true; - this.doingSetup = false; -}; - -/* Enums */ -ControllerIOS.StartPlaybackControls = 2; - -ControllerIOS.prototype = { - /* Constants */ - MinimumTimelineWidth: 200, - ButtonWidth: 42, - - get idiom() - { - return "ios"; - }, - - createBase: function() { - Controller.prototype.createBase.call(this); - - var startPlaybackButton = this.controls.startPlaybackButton = document.createElement('div'); - startPlaybackButton.setAttribute('pseudo', '-webkit-media-controls-start-playback-button'); - startPlaybackButton.setAttribute('aria-label', this.UIString('Start Playback')); - startPlaybackButton.setAttribute('role', 'button'); - - var startPlaybackBackground = document.createElement('div'); - startPlaybackBackground.setAttribute('pseudo', '-webkit-media-controls-start-playback-background'); - startPlaybackBackground.classList.add('webkit-media-controls-start-playback-background'); - startPlaybackButton.appendChild(startPlaybackBackground); - - var startPlaybackTint = document.createElement('div'); - startPlaybackTint.setAttribute('pseudo', '-webkit-media-controls-start-playback-tint'); - startPlaybackButton.appendChild(startPlaybackTint); - - var startPlaybackGlyph = document.createElement('div'); - startPlaybackGlyph.setAttribute('pseudo', '-webkit-media-controls-start-playback-glyph'); - startPlaybackGlyph.classList.add('webkit-media-controls-start-playback-glyph'); - startPlaybackButton.appendChild(startPlaybackGlyph); - - this.listenFor(this.base, 'gesturestart', this.handleBaseGestureStart); - this.listenFor(this.base, 'gesturechange', this.handleBaseGestureChange); - this.listenFor(this.base, 'gestureend', this.handleBaseGestureEnd); - this.listenFor(this.base, 'touchstart', this.handleWrapperTouchStart); - this.stopListeningFor(this.base, 'mousemove', this.handleWrapperMouseMove); - this.stopListeningFor(this.base, 'mouseout', this.handleWrapperMouseOut); - - this.listenFor(document, 'visibilitychange', this.handleVisibilityChange); - }, - - shouldHaveStartPlaybackButton: function() { - var allowsInline = this.host.allowsInlineMediaPlayback; - - if (this.isPlaying || (this.hasPlayed && allowsInline)) - return false; - - if (this.isAudio() && allowsInline) - return false; - - if (this.doingSetup) - return true; - - if (this.isFullScreen()) - return false; - - if (!this.video.currentSrc && this.video.error) - return false; - - if (!this.video.controls && allowsInline) - return false; - - if (this.video.currentSrc && this.video.error) - return true; - - return true; - }, - - shouldHaveControls: function() { - if (this.shouldHaveStartPlaybackButton()) - return false; - - return Controller.prototype.shouldHaveControls.call(this); - }, - - shouldHaveAnyUI: function() { - return this.shouldHaveStartPlaybackButton() || Controller.prototype.shouldHaveAnyUI.call(this) || this.currentPlaybackTargetIsWireless(); - }, - - createControls: function() { - Controller.prototype.createControls.call(this); - - var panelContainer = this.controls.panelContainer = document.createElement('div'); - panelContainer.setAttribute('pseudo', '-webkit-media-controls-panel-container'); - - var wirelessTargetPicker = this.controls.wirelessTargetPicker; - this.listenFor(wirelessTargetPicker, 'touchstart', this.handleWirelessPickerButtonTouchStart); - this.listenFor(wirelessTargetPicker, 'touchend', this.handleWirelessPickerButtonTouchEnd); - this.listenFor(wirelessTargetPicker, 'touchcancel', this.handleWirelessPickerButtonTouchCancel); - - this.listenFor(this.controls.startPlaybackButton, 'touchstart', this.handleStartPlaybackButtonTouchStart); - this.listenFor(this.controls.startPlaybackButton, 'touchend', this.handleStartPlaybackButtonTouchEnd); - this.listenFor(this.controls.startPlaybackButton, 'touchcancel', this.handleStartPlaybackButtonTouchCancel); - - this.listenFor(this.controls.panel, 'touchstart', this.handlePanelTouchStart); - this.listenFor(this.controls.panel, 'touchend', this.handlePanelTouchEnd); - this.listenFor(this.controls.panel, 'touchcancel', this.handlePanelTouchCancel); - this.listenFor(this.controls.playButton, 'touchstart', this.handlePlayButtonTouchStart); - this.listenFor(this.controls.playButton, 'touchend', this.handlePlayButtonTouchEnd); - this.listenFor(this.controls.playButton, 'touchcancel', this.handlePlayButtonTouchCancel); - this.listenFor(this.controls.fullscreenButton, 'touchstart', this.handleFullscreenTouchStart); - this.listenFor(this.controls.fullscreenButton, 'touchend', this.handleFullscreenTouchEnd); - this.listenFor(this.controls.fullscreenButton, 'touchcancel', this.handleFullscreenTouchCancel); - this.listenFor(this.controls.pictureInPictureButton, 'touchstart', this.handlePictureInPictureTouchStart); - this.listenFor(this.controls.pictureInPictureButton, 'touchend', this.handlePictureInPictureTouchEnd); - this.listenFor(this.controls.pictureInPictureButton, 'touchcancel', this.handlePictureInPictureTouchCancel); - this.listenFor(this.controls.timeline, 'touchstart', this.handleTimelineTouchStart); - this.stopListeningFor(this.controls.playButton, 'click', this.handlePlayButtonClicked); - - this.controls.timeline.style.backgroundImage = '-webkit-canvas(' + this.timelineContextName + ')'; - }, - - setControlsType: function(type) { - if (type === this.controlsType) - return; - Controller.prototype.setControlsType.call(this, type); - - if (type === ControllerIOS.StartPlaybackControls) - this.addStartPlaybackControls(); - else - this.removeStartPlaybackControls(); - }, - - addStartPlaybackControls: function() { - this.base.appendChild(this.controls.startPlaybackButton); - }, - - removeStartPlaybackControls: function() { - if (this.controls.startPlaybackButton.parentNode) - this.controls.startPlaybackButton.parentNode.removeChild(this.controls.startPlaybackButton); - }, - - reconnectControls: function() - { - Controller.prototype.reconnectControls.call(this); - - if (this.controlsType === ControllerIOS.StartPlaybackControls) - this.addStartPlaybackControls(); - }, - - configureInlineControls: function() { - this.controls.inlinePlaybackPlaceholder.appendChild(this.controls.inlinePlaybackPlaceholderText); - this.controls.inlinePlaybackPlaceholderText.appendChild(this.controls.inlinePlaybackPlaceholderTextTop); - this.controls.inlinePlaybackPlaceholderText.appendChild(this.controls.inlinePlaybackPlaceholderTextBottom); - this.controls.panel.appendChild(this.controls.playButton); - this.controls.panel.appendChild(this.controls.statusDisplay); - this.controls.panel.appendChild(this.controls.timelineBox); - this.controls.panel.appendChild(this.controls.wirelessTargetPicker); - if (!this.isLive) { - this.controls.timelineBox.appendChild(this.controls.currentTime); - this.controls.timelineBox.appendChild(this.controls.timeline); - this.controls.timelineBox.appendChild(this.controls.remainingTime); - } - if (this.isAudio()) { - // Hide the scrubber on audio until the user starts playing. - this.controls.timelineBox.classList.add(this.ClassNames.hidden); - } else { - this.updatePictureInPictureButton(); - this.controls.panel.appendChild(this.controls.fullscreenButton); - } - }, - - configureFullScreenControls: function() { - // Explicitly do nothing to override base-class behavior. - }, - - controlsAreHidden: function() - { - // Controls are only ever actually hidden when they are removed from the tree - return !this.controls.panelContainer.parentElement; - }, - - addControls: function() { - this.base.appendChild(this.controls.inlinePlaybackPlaceholder); - this.base.appendChild(this.controls.panelContainer); - this.controls.panelContainer.appendChild(this.controls.panelBackground); - this.controls.panelContainer.appendChild(this.controls.panel); - this.setNeedsTimelineMetricsUpdate(); - }, - - updateControls: function() { - if (this.shouldHaveStartPlaybackButton()) - this.setControlsType(ControllerIOS.StartPlaybackControls); - else if (this.presentationMode() === "fullscreen") - this.setControlsType(Controller.FullScreenControls); - else - this.setControlsType(Controller.InlineControls); - - this.updateLayoutForDisplayedWidth(); - this.setNeedsTimelineMetricsUpdate(); - }, - - drawTimelineBackground: function() { - var width = this.timelineWidth * window.devicePixelRatio; - var height = this.timelineHeight * window.devicePixelRatio; - - if (!width || !height) - return; - - var played = this.video.currentTime / this.video.duration; - var buffered = 0; - var bufferedRanges = this.video.buffered; - if (bufferedRanges && bufferedRanges.length) - buffered = Math.max(bufferedRanges.end(bufferedRanges.length - 1), buffered); - - buffered /= this.video.duration; - buffered = Math.max(buffered, played); - - var ctx = document.getCSSCanvasContext('2d', this.timelineContextName, width, height); - - ctx.clearRect(0, 0, width, height); - - var midY = height / 2; - - // 1. Draw the buffered part and played parts, using - // solid rectangles that are clipped to the outside of - // the lozenge. - ctx.save(); - ctx.beginPath(); - this.addRoundedRect(ctx, 1, midY - 3, width - 2, 6, 3); - ctx.closePath(); - ctx.clip(); - ctx.fillStyle = "white"; - ctx.fillRect(0, 0, Math.round(width * played) + 2, height); - ctx.fillStyle = "rgba(0, 0, 0, 0.55)"; - ctx.fillRect(Math.round(width * played) + 2, 0, Math.round(width * (buffered - played)) + 2, height); - ctx.restore(); - - // 2. Draw the outline with a clip path that subtracts the - // middle of a lozenge. This produces a better result than - // stroking. - ctx.save(); - ctx.beginPath(); - this.addRoundedRect(ctx, 1, midY - 3, width - 2, 6, 3); - this.addRoundedRect(ctx, 2, midY - 2, width - 4, 4, 2); - ctx.closePath(); - ctx.clip("evenodd"); - ctx.fillStyle = "rgba(0, 0, 0, 0.55)"; - ctx.fillRect(Math.round(width * buffered) + 2, 0, width, height); - ctx.restore(); - }, - - formatTime: function(time) { - if (isNaN(time)) - time = 0; - var absTime = Math.abs(time); - var intSeconds = Math.floor(absTime % 60).toFixed(0); - var intMinutes = Math.floor((absTime / 60) % 60).toFixed(0); - var intHours = Math.floor(absTime / (60 * 60)).toFixed(0); - var sign = time < 0 ? '-' : String(); - - if (intHours > 0) - return sign + intHours + ':' + String('0' + intMinutes).slice(-2) + ":" + String('0' + intSeconds).slice(-2); - - return sign + String('0' + intMinutes).slice(intMinutes >= 10 ? -2 : -1) + ":" + String('0' + intSeconds).slice(-2); - }, - - handlePlayButtonTouchStart: function() { - this.controls.playButton.classList.add('active'); - }, - - handlePlayButtonTouchEnd: function(event) { - this.controls.playButton.classList.remove('active'); - - if (this.canPlay()) { - this.video.play(); - this.showControls(); - } else - this.video.pause(); - - return true; - }, - - handlePlayButtonTouchCancel: function(event) { - this.controls.playButton.classList.remove('active'); - return true; - }, - - handleBaseGestureStart: function(event) { - this.gestureStartTime = new Date(); - // If this gesture started with two fingers inside the video, then - // don't treat it as a potential zoom, unless we're still waiting - // to play. - if (this.mostRecentNumberOfTargettedTouches == 2 && this.controlsType != ControllerIOS.StartPlaybackControls) - event.preventDefault(); - }, - - handleBaseGestureChange: function(event) { - if (!this.video.controls || this.isAudio() || this.isFullScreen() || this.gestureStartTime === undefined || this.controlsType == ControllerIOS.StartPlaybackControls) - return; - - var scaleDetectionThreshold = 0.2; - if (event.scale > 1 + scaleDetectionThreshold || event.scale < 1 - scaleDetectionThreshold) - delete this.lastDoubleTouchTime; - - if (this.mostRecentNumberOfTargettedTouches == 2 && event.scale >= 1.0) - event.preventDefault(); - - var currentGestureTime = new Date(); - var duration = (currentGestureTime - this.gestureStartTime) / 1000; - if (!duration) - return; - - var velocity = Math.abs(event.scale - 1) / duration; - - var pinchOutVelocityThreshold = 2; - var pinchOutGestureScaleThreshold = 1.25; - if (velocity < pinchOutVelocityThreshold || event.scale < pinchOutGestureScaleThreshold) - return; - - delete this.gestureStartTime; - this.video.webkitEnterFullscreen(); - }, - - handleBaseGestureEnd: function(event) { - delete this.gestureStartTime; - }, - - handleWrapperTouchStart: function(event) { - if (event.target != this.base && event.target != this.controls.inlinePlaybackPlaceholder) - return; - - this.mostRecentNumberOfTargettedTouches = event.targetTouches.length; - - if (this.controlsAreHidden() || !this.controls.panel.classList.contains(this.ClassNames.show)) { - this.showControls(); - this.resetHideControlsTimer(); - } else if (!this.canPlay()) - this.hideControls(); - }, - - handlePanelTouchStart: function(event) { - this.video.style.webkitUserSelect = 'none'; - }, - - handlePanelTouchEnd: function(event) { - this.video.style.removeProperty('-webkit-user-select'); - }, - - handlePanelTouchCancel: function(event) { - this.video.style.removeProperty('-webkit-user-select'); - }, - - handleVisibilityChange: function(event) { - this.updateShouldListenForPlaybackTargetAvailabilityEvent(); - }, - - handlePanelTransitionEnd: function(event) - { - var opacity = window.getComputedStyle(this.controls.panel).opacity; - if (!parseInt(opacity) && !this.controlsAlwaysVisible()) { - this.base.removeChild(this.controls.inlinePlaybackPlaceholder); - this.base.removeChild(this.controls.panelContainer); - } - }, - - handleFullscreenButtonClicked: function(event) { - if ('webkitSetPresentationMode' in this.video) { - if (this.presentationMode() === 'fullscreen') - this.video.webkitSetPresentationMode('inline'); - else - this.video.webkitSetPresentationMode('fullscreen'); - - return; - } - - if (this.isFullScreen()) - this.video.webkitExitFullscreen(); - else - this.video.webkitEnterFullscreen(); - }, - - handleFullscreenTouchStart: function() { - this.controls.fullscreenButton.classList.add('active'); - }, - - handleFullscreenTouchEnd: function(event) { - this.controls.fullscreenButton.classList.remove('active'); - - this.handleFullscreenButtonClicked(); - - return true; - }, - - handleFullscreenTouchCancel: function(event) { - this.controls.fullscreenButton.classList.remove('active'); - return true; - }, - - handlePictureInPictureTouchStart: function() { - this.controls.pictureInPictureButton.classList.add('active'); - }, - - handlePictureInPictureTouchEnd: function(event) { - this.controls.pictureInPictureButton.classList.remove('active'); - - this.handlePictureInPictureButtonClicked(); - - return true; - }, - - handlePictureInPictureTouchCancel: function(event) { - this.controls.pictureInPictureButton.classList.remove('active'); - return true; - }, - - handleStartPlaybackButtonTouchStart: function(event) { - this.controls.startPlaybackButton.classList.add('active'); - this.controls.startPlaybackButton.querySelector('.webkit-media-controls-start-playback-background').classList.add('active'); - }, - - handleStartPlaybackButtonTouchEnd: function(event) { - this.controls.startPlaybackButton.classList.remove('active'); - this.controls.startPlaybackButton.querySelector('.webkit-media-controls-start-playback-background').classList.remove('active'); - - if (this.video.error) - return true; - - this.video.play(); - this.updateControls(); - - return true; - }, - - handleStartPlaybackButtonTouchCancel: function(event) { - this.controls.startPlaybackButton.classList.remove('active'); - return true; - }, - - handleTimelineTouchStart: function(event) { - this.scrubbing = true; - this.listenFor(this.controls.timeline, 'touchend', this.handleTimelineTouchEnd); - this.listenFor(this.controls.timeline, 'touchcancel', this.handleTimelineTouchEnd); - }, - - handleTimelineTouchEnd: function(event) { - this.stopListeningFor(this.controls.timeline, 'touchend', this.handleTimelineTouchEnd); - this.stopListeningFor(this.controls.timeline, 'touchcancel', this.handleTimelineTouchEnd); - this.scrubbing = false; - }, - - handleWirelessPickerButtonTouchStart: function() { - if (!this.video.error) - this.controls.wirelessTargetPicker.classList.add('active'); - }, - - handleWirelessPickerButtonTouchEnd: function(event) { - this.controls.wirelessTargetPicker.classList.remove('active'); - return this.handleWirelessPickerButtonClicked(); - }, - - handleWirelessPickerButtonTouchCancel: function(event) { - this.controls.wirelessTargetPicker.classList.remove('active'); - return true; - }, - - updateShouldListenForPlaybackTargetAvailabilityEvent: function() { - if (this.controlsType === ControllerIOS.StartPlaybackControls) { - this.setShouldListenForPlaybackTargetAvailabilityEvent(false); - return; - } - - Controller.prototype.updateShouldListenForPlaybackTargetAvailabilityEvent.call(this); - }, - - updateWirelessTargetPickerButton: function() { - }, - - updateStatusDisplay: function(event) - { - this.controls.startPlaybackButton.classList.toggle(this.ClassNames.failed, this.video.error !== null); - this.controls.startPlaybackButton.querySelector(".webkit-media-controls-start-playback-glyph").classList.toggle(this.ClassNames.failed, this.video.error !== null); - Controller.prototype.updateStatusDisplay.call(this, event); - }, - - setPlaying: function(isPlaying) - { - Controller.prototype.setPlaying.call(this, isPlaying); - - this.updateControls(); - - if (isPlaying && this.isAudio()) - this.controls.timelineBox.classList.remove(this.ClassNames.hidden); - - if (isPlaying) - this.hasPlayed = true; - else - this.showControls(); - }, - - showControls: function() - { - this.updateShouldListenForPlaybackTargetAvailabilityEvent(); - if (!this.video.controls) - return; - - this.updateForShowingControls(); - if (this.shouldHaveControls() && !this.controls.panelContainer.parentElement) { - this.base.appendChild(this.controls.inlinePlaybackPlaceholder); - this.base.appendChild(this.controls.panelContainer); - } - }, - - setShouldListenForPlaybackTargetAvailabilityEvent: function(shouldListen) - { - if (shouldListen && (this.shouldHaveStartPlaybackButton() || this.video.error)) - return; - - Controller.prototype.setShouldListenForPlaybackTargetAvailabilityEvent.call(this, shouldListen); - }, - - handlePresentationModeChange: function(event) - { - var presentationMode = this.presentationMode(); - - switch (presentationMode) { - case 'inline': - this.controls.panelContainer.classList.remove(this.ClassNames.pictureInPicture); - break; - case 'picture-in-picture': - this.controls.panelContainer.classList.add(this.ClassNames.pictureInPicture); - break; - default: - this.controls.panelContainer.classList.remove(this.ClassNames.pictureInPicture); - break; - } - - Controller.prototype.handlePresentationModeChange.call(this, event); - }, - - // Due to the bad way we are faking inheritance here, in particular the extends method - // on Controller.prototype, we don't copy getters and setters from the prototype. This - // means we have to implement them again, here in the subclass. - // FIXME: Use ES6 classes! - - get scrubbing() - { - return Object.getOwnPropertyDescriptor(Controller.prototype, "scrubbing").get.call(this); - }, - - set scrubbing(flag) - { - Object.getOwnPropertyDescriptor(Controller.prototype, "scrubbing").set.call(this, flag); - }, - - get pageScaleFactor() - { - return this._pageScaleFactor; - }, - - set pageScaleFactor(newScaleFactor) - { - if (!newScaleFactor || this._pageScaleFactor === newScaleFactor) - return; - - this._pageScaleFactor = newScaleFactor; - - var scaleValue = 1 / newScaleFactor; - var scaleTransform = "scale(" + scaleValue + ")"; - if (this.controls.startPlaybackButton) - this.controls.startPlaybackButton.style.webkitTransform = scaleTransform; - if (this.controls.panel) { - if (scaleValue > 1) { - this.controls.panel.style.width = "100%"; - this.controls.panel.style.zoom = scaleValue; - this.controls.panel.style.webkitTransform = "scale(1)"; - this.controls.timelineBox.style.webkitTextSizeAdjust = (100 * scaleValue) + "%"; - } else { - var bottomAligment = -2 * scaleValue; - this.controls.panel.style.bottom = bottomAligment + "px"; - this.controls.panel.style.paddingBottom = -(newScaleFactor * bottomAligment) + "px"; - this.controls.panel.style.width = Math.round(newScaleFactor * 100) + "%"; - this.controls.panel.style.webkitTransform = scaleTransform; - this.controls.timelineBox.style.webkitTextSizeAdjust = "auto"; - this.controls.panel.style.zoom = 1; - } - this.controls.panelBackground.style.height = (50 * scaleValue) + "px"; - - this.setNeedsTimelineMetricsUpdate(); - this.updateProgress(); - this.scheduleUpdateLayoutForDisplayedWidth(); - } - }, - -}; - -Object.create(Controller.prototype).extend(ControllerIOS.prototype); -Object.defineProperty(ControllerIOS.prototype, 'constructor', { enumerable: false, value: ControllerIOS }); |
