diff options
author | MaZderMind | 2016-12-22 20:59:50 +0100 |
---|---|---|
committer | MaZderMind | 2016-12-22 20:59:50 +0100 |
commit | e9f3659fe8bdcd7256bdef9083e28eac6633ddd7 (patch) | |
tree | 34439f1096351e82940b1db3d8f566492025f81b | |
parent | d00fda4353e943c249354edf6e11cccfdc089d83 (diff) |
add controls to dash-player
Diffstat (limited to '')
-rw-r--r-- | assets/dashjs/ControlBar.js | 690 | ||||
-rw-r--r-- | assets/dashjs/controlbar.css | 268 | ||||
-rw-r--r-- | assets/dashjs/icomoon.ttf | bin | 0 -> 4688 bytes | |||
-rw-r--r-- | template/assemblies/player/dash.phtml | 81 |
4 files changed, 1031 insertions, 8 deletions
diff --git a/assets/dashjs/ControlBar.js b/assets/dashjs/ControlBar.js new file mode 100644 index 0000000..ee52fc6 --- /dev/null +++ b/assets/dashjs/ControlBar.js @@ -0,0 +1,690 @@ +/** + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and contributor + * rights, including patent rights, and no such rights are granted under this license. + * + * Copyright (c) 2013, Dash Industry Forum. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Dash Industry Forum nor the names of its + * contributors may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 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 THE COPYRIGHT HOLDER 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. + */ +var ControlBar = function (dashjsMediaPlayer) { + + var player = dashjsMediaPlayer, + video, + videoContainer, + captionMenu = null, + bitrateListMenu = null, + trackSwitchMenu = null, + menuHandlersList = [], + lastVolumeLevel = NaN, + seeking = false, + videoControllerVisibleTimeout = 0, + videoController = document.getElementById("videoController"), + playPauseBtn = document.getElementById("playPauseBtn"), + bitrateListBtn = document.getElementById("bitrateListBtn"), + captionBtn = document.getElementById("captionBtn"), + trackSwitchBtn = document.getElementById("trackSwitchBtn"), + seekbar = document.getElementById("seekbar"), + muteBtn = document.getElementById("muteBtn"), + volumebar = document.getElementById("volumebar"), + fullscreenBtn = document.getElementById("fullscreenBtn"), + timeDisplay = document.getElementById("videoTime"), + durationDisplay = document.getElementById("videoDuration"), + +//************************************************************************************ +// PLAYBACK +//************************************************************************************ + + togglePlayPauseBtnState = function () { + var span = document.getElementById('iconPlayPause'); + if (player.isPaused()) { + span.classList.remove('icon-pause') + span.classList.add('icon-play'); + } else { + span.classList.remove('icon-play'); + span.classList.add('icon-pause'); + } + }, + + onPlayPauseClick = function (e) { + togglePlayPauseBtnState.call(this); + player.isPaused() ? player.play() : player.pause(); + }, + + onPlaybackPaused = function (e) { + togglePlayPauseBtnState(); + }, + + onPlayStart = function (e) { + setTime(player.time()); + updateDuration(); + togglePlayPauseBtnState(); + }, + + onPlayTimeUpdate = function (e) { + updateDuration(); + if (!seeking) { + setTime(player.time()); + seekbar.value = player.time(); + } + }, + +//************************************************************************************ +// VOLUME +//************************************************************************************ + + toggleMuteBtnState = function () { + var span = document.getElementById('iconMute'); + if (player.isMuted()) { + span.classList.remove('icon-mute-off'); + span.classList.add('icon-mute-on'); + } else { + span.classList.remove('icon-mute-on') + span.classList.add('icon-mute-off'); + } + }, + + onMuteClick = function (e) { + if (player.isMuted() && !isNaN(lastVolumeLevel)) { + setVolume(lastVolumeLevel); + } else { + lastVolumeLevel = parseFloat(volumebar.value); + setVolume(0); + } + player.setMute(player.getVolume() === 0); + toggleMuteBtnState(); + }, + + setVolume = function (value) { + if (typeof value === "number") { + volumebar.value = value; + } + player.setVolume(volumebar.value); + player.setMute(player.getVolume() === 0); + if (isNaN(lastVolumeLevel)) { + lastVolumeLevel = player.getVolume(); + } + toggleMuteBtnState(); + }, + +//************************************************************************************ +// SEEKING +// ************************************************************************************ + + onSeekBarChange = function (e) { + player.seek(parseFloat(seekbar.value)); + }, + + onSeeking = function (e) { + //TODO Add call to seek in trick-mode once implemented. Preview Frames. + seeking = true; + setTime(parseFloat(seekbar.value)); + }, + + onSeeked = function (e) { + seeking = false; + }, + +//************************************************************************************ +// TIME/DURATION +//************************************************************************************ + + setDuration = function (value) { + if (!isNaN(value)) { + durationDisplay.textContent = player.convertToTimeCode(value); + } + }, + + setTime = function (value) { + if (!isNaN(value)) { + timeDisplay.textContent = player.convertToTimeCode(value); + } + }, + + updateDuration = function () { + var duration = player.duration(); + if (duration !== parseFloat(seekbar.max)) { //check if duration changes for live streams.. + setDuration(duration); + seekbar.max = duration; + } + }, + +//************************************************************************************ +// FULLSCREEN +//************************************************************************************ + + onFullScreenChange = function (e) { + if (isFullscreen()) { + enterFullscreen(); + var icon = fullscreenBtn.querySelector(".icon-fullscreen-enter") + icon.classList.remove("icon-fullscreen-enter"); + icon.classList.add("icon-fullscreen-exit"); + } else { + exitFullscreen(); + var icon = fullscreenBtn.querySelector(".icon-fullscreen-exit") + icon.classList.remove("icon-fullscreen-exit"); + icon.classList.add("icon-fullscreen-enter"); + } + }, + + isFullscreen = function () { + return document.fullscreenElement || document.msFullscreenElement || document.mozFullScreen || document.webkitIsFullScreen; + }, + + enterFullscreen = function () { + var element = videoContainer || video; + + if (element.requestFullscreen) { + element.requestFullscreen(); + } else if (element.msRequestFullscreen) { + element.msRequestFullscreen(); + } else if (element.mozRequestFullScreen) { + element.mozRequestFullScreen(); + } else { + element.webkitRequestFullScreen(); + } + videoController.classList.add('video-controller-fullscreen'); + window.addEventListener("mousemove", onFullScreenMouseMove); + onFullScreenMouseMove(); + }, + + onFullScreenMouseMove = function () { + clearFullscreenState(); + videoControllerVisibleTimeout = setTimeout(function () { + videoController.classList.add("hide"); + }, 4000); + }, + + clearFullscreenState = function () { + clearTimeout(videoControllerVisibleTimeout); + videoController.classList.remove("hide"); + }, + + exitFullscreen = function () { + window.removeEventListener("mousemove", onFullScreenMouseMove); + clearFullscreenState(); + + if (document.exitFullscreen) { + document.exitFullscreen(); + } else if (document.mozCancelFullScreen) { + document.mozCancelFullScreen(); + } else if (document.msExitFullscreen) { + document.msExitFullscreen(); + } else { + document.webkitCancelFullScreen(); + } + videoController.classList.remove('video-controller-fullscreen'); + }, + + onFullscreenClick = function (e) { + if (!isFullscreen()) { + enterFullscreen(); + } else { + exitFullscreen(); + } + if (captionMenu) { + captionMenu.classList.add("hide"); + } + if (bitrateListMenu) { + bitrateListMenu.classList.add("hide"); + } + if (trackSwitchMenu) { + trackSwitchMenu.classList.add("hide"); + } + }, + +//************************************************************************************ +// Audio Video MENU +//************************************************************************************ + + onTracksAdded = function (e) { + // Subtitles/Captions Menu //XXX we need to add two layers for captions & subtitles if present. + if (!captionMenu) { + var contentFunc = function (element, index) { + return isNaN(index) ? "OFF" : element.lang + " : " + element.kind; + } + captionMenu = createMenu({menuType: 'caption', arr: e.tracks}, contentFunc); + + var func = function () { + onMenuClick(captionMenu, captionBtn); + } + menuHandlersList.push(func); + captionBtn.addEventListener("click", func); + captionBtn.classList.remove("hide"); + } + }, + + onStreamInitialized = function (e) { + + var contentFunc; + //Bitrate Menu + if (bitrateListBtn) { + destroyBitrateMenu(); + + var availableBitrates = {menuType: 'bitrate'}; + availableBitrates.audio = player.getBitrateInfoListFor("audio") || []; + availableBitrates.video = player.getBitrateInfoListFor("video") || []; + + if (availableBitrates.audio.length > 1 || availableBitrates.video.length > 1) { + + contentFunc = function (element, index) { + return isNaN(index) ? " Auto Switch" : Math.floor(element.bitrate / 1000) + " kbps"; + } + bitrateListMenu = createMenu(availableBitrates, contentFunc); + var func = function () { + onMenuClick(bitrateListMenu, bitrateListBtn); + }; + menuHandlersList.push(func); + bitrateListBtn.addEventListener("click", func); + bitrateListBtn.classList.remove("hide"); + + } else { + bitrateListBtn.classList.add("hide"); + } + } + + //Track Switch Menu + if (!trackSwitchMenu && trackSwitchBtn) { + var availableTracks = {menuType: "track"}; + availableTracks.audio = player.getTracksFor("audio"); + availableTracks.video = player.getTracksFor("video"); // these return empty arrays so no need to cehck for null + + if (availableTracks.audio.length > 1 || availableTracks.video.length > 1) { + contentFunc = function (element) { + return 'Language: ' + element.lang + ' - Role: ' + element.roles[0]; + } + trackSwitchMenu = createMenu(availableTracks, contentFunc); + var func = function () { + onMenuClick(trackSwitchMenu, trackSwitchBtn); + }; + menuHandlersList.push(func); + trackSwitchBtn.addEventListener("click", func); + trackSwitchBtn.classList.remove("hide"); + } + } + + }, + + createMenu = function (info, contentFunc) { + + var menuType = info.menuType; + var el = document.createElement("div"); + el.id = menuType + "Menu"; + el.classList.add("menu"); + el.classList.add("hide"); + el.classList.add("unselectable"); + el.classList.add("menu-item-unselected"); + videoController.appendChild(el); + + switch (menuType) { + case 'caption' : + el.appendChild(document.createElement("ul")); + el = createMenuContent(el, getMenuContent(menuType, info.arr, contentFunc), 'caption', menuType + '-list'); + setMenuItemsState(1, menuType + '-list'); // Should not be harcoded. get initial index or state from dash.js - not available yet in dash.js + break; + case 'track' : + case 'bitrate' : + if (info.video.length > 1) { + el.appendChild(createMediaTypeMenu("video")); + el = createMenuContent(el, getMenuContent(menuType, info.video, contentFunc), 'video', 'video-' + menuType + '-list'); + setMenuItemsState(getMenuInitialIndex(info.video, menuType, 'video'), 'video-' + menuType + '-list'); + } + if (info.audio.length > 1) { + el.appendChild(createMediaTypeMenu("audio")); + el = createMenuContent(el, getMenuContent(menuType, info.audio, contentFunc), 'audio', 'audio-' + menuType + '-list'); + setMenuItemsState(getMenuInitialIndex(info.audio, menuType, 'audio'), 'audio-' + menuType + '-list'); + } + break; + } + + window.addEventListener("resize", handleMenuPositionOnResize, true); + return el; + }, + + getMenuInitialIndex = function(info, menuType, mediaType) { + if (menuType === 'track') { + + var mediaInfo = player.getCurrentTrackFor(mediaType); + var idx = 0 + info.some(function(element, index){ + if (isTracksEqual(element, mediaInfo)) { + idx = index; + return true; + } + }) + return idx; + + } else if (menuType === "bitrate") { + return player.getAutoSwitchQualityFor(mediaType) ? 0 : player.getQualityFor(mediaType); + } + }, + + isTracksEqual = function (t1, t2) { + var sameId = t1.id === t2.id; + var sameViewpoint = t1.viewpoint === t2.viewpoint; + var sameLang = t1.lang === t2.lang; + var sameRoles = t1.roles.toString() === t2.roles.toString(); + var sameAccessibility = t1.accessibility.toString() === t2.accessibility.toString(); + var sameAudioChannelConfiguration = t1.audioChannelConfiguration.toString() === t2.audioChannelConfiguration.toString(); + + return (sameId && sameViewpoint && sameLang && sameRoles && sameAccessibility && sameAudioChannelConfiguration); + }, + + getMenuContent = function (type, arr, contentFunc) { + + var content = []; + arr.forEach(function (element, index) { + content.push(contentFunc(element, index)); + }) + if (type !== 'track') { + content.unshift(contentFunc(null, NaN)); + } + return content; + }, + + createMediaTypeMenu = function (type) { + + var div = document.createElement("div"); + var title = document.createElement("div"); + var content = document.createElement("ul"); + + div.id = type; + + title.textContent = type === 'video' ? 'Video' : 'Audio'; + title.classList.add('menu-sub-menu-title'); + + content.id = type + "Content"; + content.classList.add(type + "-menu-content"); + + div.appendChild(title); + div.appendChild(content); + + return div; + }, + + createMenuContent = function (menu, arr, mediaType, name) { + + for (var i = 0; i < arr.length; i++) { + + var item = document.createElement("li"); + item.id = name + "Item_" + i; + item.index = i; + item.mediaType = mediaType; + item.name = name; + item.selected = false; + item.textContent = arr[i]; + + item.onmouseover = function (e) { + if (this.selected !== true) { + this.classList.add("menu-item-over"); + } + }; + item.onmouseout = function (e) { + this.classList.remove("menu-item-over"); + }; + item.onclick = setMenuItemsState.bind(item); + + var el; + if (mediaType === 'caption') { + el = menu.querySelector("ul"); + } else { + el = menu.querySelector('.' + mediaType + "-menu-content"); + } + + el.appendChild(item); + } + + return menu; + }, + + + onMenuClick = function (menu, btn) { + + if (menu.classList.contains("hide")) { + menu.classList.remove("hide"); + menu.onmouseleave = function (e) { + this.classList.add("hide"); + }; + } else { + menu.classList.add("hide"); + } + menu.style.position = isFullscreen() ? "fixed" : "absolute"; + positionMenu(menu, btn); + }, + + + setMenuItemsState = function (value, type) { + + var self = typeof value === 'number' ? document.getElementById(type + "Item_" + value) : this, + nodes = self.parentElement.children; + + for (var i = 0; i < nodes.length; i++) { + nodes[i].selected = false; + nodes[i].classList.remove("menu-item-selected"); + nodes[i].classList.add("menu-item-unselected"); + } + self.selected = true; + self.classList.remove("menu-item-over"); + self.classList.remove("menu-item-unselected"); + self.classList.add("menu-item-selected"); + + + if (type === undefined) { // User clicked so type is part of item binding. + switch (self.name) { + case 'video-bitrate-list': + case 'audio-bitrate-list': + if (self.index > 0) { + if (player.getAutoSwitchQualityFor(self.mediaType)) { + player.setAutoSwitchQualityFor(self.mediaType, false); + } + player.setQualityFor(self.mediaType, self.index - 1); + } else { + player.setAutoSwitchQualityFor(self.mediaType, true); + } + break; + case 'caption-list' : + player.setTextTrack(self.index - 1); + break + case 'video-track-list' : + case 'audio-track-list' : + player.setCurrentTrack(player.getTracksFor(self.mediaType)[self.index]); + break; + } + } + }, + + handleMenuPositionOnResize = function (e) { + if (captionMenu) { + positionMenu(captionMenu, captionBtn); + } + if (bitrateListMenu) { + positionMenu(bitrateListMenu, bitrateListBtn); + } + if (trackSwitchMenu) { + positionMenu(trackSwitchMenu, trackSwitchBtn); + } + }, + + positionMenu = function (menu, btn) { + var menu_y = videoController.offsetTop - menu.offsetHeight; + menu.style.top = menu_y + "px"; + menu.style.left = btn.offsetLeft + "px"; + }, + + destroyBitrateMenu = function () { + if (bitrateListMenu) { + menuHandlersList.forEach(function (item) { + bitrateListBtn.removeEventListener("click", item); + }) + videoController.removeChild(bitrateListMenu); + bitrateListMenu = null; + } + }, + +//************************************************************************************ +//IE FIX +//************************************************************************************ + + coerceIEInputAndChangeEvents = function (slider, addChange) { + var fireChange = function (e) { + var changeEvent = document.createEvent('Event'); + changeEvent.initEvent('change', true, true); + changeEvent.forceChange = true; + slider.dispatchEvent(changeEvent); + }; + + this.addEventListener('change', function (e) { + var inputEvent; + if (!e.forceChange && e.target.getAttribute('type') === 'range') { + e.stopPropagation(); + inputEvent = document.createEvent('Event'); + inputEvent.initEvent('input', true, true); + e.target.dispatchEvent(inputEvent); + if (addChange) { + e.target.removeEventListener('mouseup', fireChange);//TODO can not clean up this event on destroy. refactor needed! + e.target.addEventListener('mouseup', fireChange); + } + } + + }, true); + }, + + isIE = function () { + return !!navigator.userAgent.match(/Trident.*rv[ :]*11\./) + }; + + +//************************************************************************************ +// PUBLIC API +//************************************************************************************ + + return { + setVolume: setVolume, + setDuration: setDuration, + setTime: setTime, + + initialize: function () { + + if (!player) { + throw new Error("Please pass an instance of MediaPlayer.js when instantiating the ControlBar Object"); + } + video = player.getVideoElement(); + if (!video) { + throw new Error("Please call initialize after you have called attachView on MediaPlayer.js"); + } + + video.controls = false; + videoContainer = player.getVideoContainer(); + captionBtn.classList.add("hide"); + if (trackSwitchBtn) { + trackSwitchBtn.classList.add("hide"); + } + + player.on(dashjs.MediaPlayer.events.PLAYBACK_STARTED, onPlayStart, this); + player.on(dashjs.MediaPlayer.events.PLAYBACK_PAUSED, onPlaybackPaused, this); + player.on(dashjs.MediaPlayer.events.PLAYBACK_TIME_UPDATED, onPlayTimeUpdate, this); + player.on(dashjs.MediaPlayer.events.PLAYBACK_SEEKED, onSeeked, this); + player.on(dashjs.MediaPlayer.events.TEXT_TRACKS_ADDED, onTracksAdded, this); + player.on(dashjs.MediaPlayer.events.STREAM_INITIALIZED, onStreamInitialized, this); + + playPauseBtn.addEventListener("click", onPlayPauseClick); + muteBtn.addEventListener("click", onMuteClick); + fullscreenBtn.addEventListener("click", onFullscreenClick); + seekbar.addEventListener("change", onSeekBarChange, true); + seekbar.addEventListener("input", onSeeking, true); + volumebar.addEventListener("input", setVolume, true); + document.addEventListener("fullscreenchange", onFullScreenChange, false); + document.addEventListener("MSFullscreenChange", onFullScreenChange, false); + document.addEventListener("mozfullscreenchange", onFullScreenChange, false); + document.addEventListener("webkitfullscreenchange", onFullScreenChange, false); + + //IE 11 Input Fix. + if (isIE()) { + coerceIEInputAndChangeEvents(seekbar, true); + coerceIEInputAndChangeEvents(volumebar, false); + } + }, + + show: function () { + videoController.classList.remove("hide"); + }, + + hide: function () { + videoController.classList.add("hide"); + }, + + disable: function () { + videoController.classList.add("disable"); + }, + + enable: function () { + videoController.classList.remove("disable"); + }, + + reset: function () { + window.removeEventListener("resize", handleMenuPositionOnResize); + destroyBitrateMenu(); + menuHandlersList.forEach(function (item) { + if (trackSwitchBtn) trackSwitchBtn.removeEventListener("click", item); + if (captionBtn) captionBtn.removeEventListener("click", item); + }) + if (captionMenu) { + videoController.removeChild(captionMenu); + captionMenu = null; + captionBtn.classList.add("hide"); + } + if (trackSwitchMenu) { + videoController.removeChild(trackSwitchMenu); + trackSwitchMenu = null; + trackSwitchBtn.classList.add("hide"); + } + menuHandlersList = []; + seeking = false; + }, + + destroy: function () { + + reset(); + + playPauseBtn.removeEventListener("click", onPlayPauseClick); + muteBtn.removeEventListener("click", onMuteClick); + fullscreenBtn.removeEventListener("click", onFullscreenClick); + seekbar.removeEventListener("change", onSeekBarChange); + seekbar.removeEventListener("input", onSeeking); + volumebar.removeEventListener("input", setVolume); + + player.off(dashjs.MediaPlayer.events.PLAYBACK_STARTED, onPlayStart, this); + player.off(dashjs.MediaPlayer.events.PLAYBACK_PAUSED, onPlaybackPaused, this); + player.off(dashjs.MediaPlayer.events.PLAYBACK_TIME_UPDATED, onPlayTimeUpdate, this); + player.off(dashjs.MediaPlayer.events.PLAYBACK_SEEKED, onSeeked, this); + player.off(dashjs.MediaPlayer.events.TEXT_TRACKS_ADDED, onTracksAdded, this); + player.off(dashjs.MediaPlayer.events.STREAM_INITIALIZED, onStreamInitialized, this); + + document.removeEventListener("fullscreenchange", onFullScreenChange); + document.removeEventListener("MSFullscreenChange", onFullScreenChange); + document.removeEventListener("mozfullscreenchange", onFullScreenChange); + document.removeEventListener("webkitfullscreenchange", onFullScreenChange); + } + } +} diff --git a/assets/dashjs/controlbar.css b/assets/dashjs/controlbar.css new file mode 100644 index 0000000..080d93d --- /dev/null +++ b/assets/dashjs/controlbar.css @@ -0,0 +1,268 @@ +/**************************************************/ +/*Control bar*/ +/**************************************************/ +.hide{ + display: none; +} + +.disable { + pointer-events:none; +} + +.unselectable { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +:-webkit-full-screen { + position: fixed; + width: 100%; + height: 100%; + top:0; + z-index: -100; + background: none; +} + +:-ms-fullscreen { + width: auto; + height: auto; + margin: auto; +} + +.time-display, +.duration-display{ + padding:11px; + color: white; + font-weight: normal; + font-size: .9em; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; +} + +.time-display{ + float:left; +} + +.duration-display{ + float: right; +} + +.btn-play-pause{ + float: left; + padding:9px 10px; + cursor: pointer; +} + +.control-icon-layout + { + float: right; + padding:9px 10px; + cursor: pointer; +} + +.btn-fullscreen { + margin-right: 10px; +} + +.volumebar { + float: right; + width: 70px; +} + +.video-controller { + min-height:35px; + z-index: 2147483646; +} + +.video-controller-fullscreen { + position: fixed; + z-index:2147483647; + width: 100%; + bottom: 0; + left: 0; +} + +.menu, +.video-controller { + background-color: black; +} + +.menu-item-unselected, +.menu-item-selected{ + font-weight: normal; + font-size: .9em; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; +} + +.menu-item-unselected { + color: white; +} + +.menu-item-over, +.menu-item-selected { + background-color: white; + color: black; +} + +.menu-sub-menu-title { + background-color: #191919; + padding-left: 2px; + font-weight: bold; + font-size: 1.0em; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + +} + +.menu-item-selected { + opacity: .7; +} + +.menu ul{ + list-style-type: none; + padding:0; + margin:0; +} + +.menu li{ + padding:0 10px; + cursor: pointer; +} + +.menu { + position: absolute; +} + +@font-face { + font-family: 'icomoon'; + src: url("icomoon.ttf") format("truetype"); + font-weight: normal; + font-style: normal; +} + +.icon-play, +.icon-pause, +.icon-caption, +.icon-mute-off, +.icon-mute-on, +.icon-fullscreen-enter, +.icon-fullscreen-exit, +.icon-tracks, +.icon-bitrate { + font-family: 'icomoon'; + font-size: 20px; + color: white; + text-shadow: none; + -webkit-font-smoothing: antialiased; +} + +.icon-fullscreen-enter:before { + content: "\e90b"; +} +.icon-fullscreen-exit:before { + content: "\e90c"; +} +.icon-play:before { + content: "\e910"; +} +.icon-pause:before { + content: "\e911"; +} +.icon-mute-on:before { + content: "\e909"; +} +.icon-mute-off:before { + content: "\e918"; +} +.icon-caption:before { + content: "\e901"; +} +.icon-bitrate:before { + content: "\e905"; +} +.icon-tracks:before { + content: "\e90a"; +} + +.seekContainer { + overflow: auto; + padding-right: 10px; + overflow-y: hidden; + overflow-x: hidden; +} + +.seekbar { + position: relative; + width: 100%; +} + +input[type="range"] { + -webkit-appearance: none; + -webkit-tap-highlight-color: rgba(255, 255, 255, 0); + height: 14px; + border: none; + margin:12px 5px; + padding: 1px 2px; + border-radius: 5px; + background: #232528; + box-shadow: inset 0 1px 0 0 #0d0e0f, inset 0 -1px 0 0 #3a3d42; + -webkit-box-shadow: inset 0 1px 0 0 #0d0e0f, inset 0 -1px 0 0 #3a3d42; + outline: none; /* no focus outline */ +} + +input[type=range]::-moz-focus-outer { + border: 0; +} + +input[type="range"]::-moz-range-track { + border: inherit; + background: transparent; +} + +input[type="range"]::-ms-track { + border: inherit; + color: transparent; /* don't drawn vertical reference line */ + background: transparent; +} + +input[type="range"]::-ms-fill-lower, +input[type="range"]::-ms-fill-upper { + background: transparent; +} + +input[type="range"]::-ms-tooltip { + display: none; +} + +/* thumb */ +input[type="range"]::-webkit-slider-thumb { + -webkit-appearance: none; + width: 15px; + height: 8px; + border: none; + border-radius: 2px; + background-color:rgb(0, 150, 215); +} +input[type="range"]::-moz-range-thumb { + width: 15px; + height: 8px; + border: none; + border-radius: 2px; + background-color:rgb(0, 150, 215); +} + +input[type="range"]::-ms-thumb { + width: 15px; + height: 8px; + border: none; + border-radius: 2px; + background-color:rgb(0, 150, 215); +} + +div#videoController input[type="range"]{ + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +}
\ No newline at end of file diff --git a/assets/dashjs/icomoon.ttf b/assets/dashjs/icomoon.ttf Binary files differnew file mode 100644 index 0000000..e31162f --- /dev/null +++ b/assets/dashjs/icomoon.ttf diff --git a/template/assemblies/player/dash.phtml b/template/assemblies/player/dash.phtml index 081537a..7129b30 100644 --- a/template/assemblies/player/dash.phtml +++ b/template/assemblies/player/dash.phtml @@ -1,10 +1,75 @@ <script type="text/javascript" src="<?=h($assets)?>dashjs/dash.all.debug.js"></script> +<script type="text/javascript" src="<?=h($assets)?>dashjs/ControlBar.js"></script> +<link type="text/css" rel="stylesheet" href="<?=h($assets)?>dashjs/controlbar.css" /> -<!-- working example: src="http://dash.edgesuite.net/envivio/EnvivioDash3/manifest.mpd" --> -<video - data-dashjs-player - autoplay - src="<?=h($room->getDashManifestUrl())?>" - controls="true" - style="width: 100%" -/> +<div class="dashContainer"> + <!-- working example: src="http://dash.edgesuite.net/envivio/EnvivioDash3/manifest.mpd" --> + <video + preload="auto" autoplay="true" + src="<?=h($room->getDashManifestUrl())?>" + style="width: 100%" + > + <div class="well">DASH does not seem to work for you. Sorry :/</div> + </video> + + <div id="videoController" class="video-controller unselectable"> + <div id="playPauseBtn" class="btn-play-pause" title="Play/Pause"> + <span id="iconPlayPause" class="icon-play"></span> + </div> + <span id="videoTime" class="time-display">00:00:00</span> + <div id="fullscreenBtn" class="btn-fullscreen control-icon-layout" title="Fullscreen"> + <span class="icon-fullscreen-enter"></span> + </div> + <div id="bitrateListBtn" class="control-icon-layout" title="Bitrate List"> + <span class="icon-bitrate"></span> + </div> + <input type="range" id="volumebar" class="volumebar" value="1" min="0" max="1" step=".01"/> + <div id="muteBtn" class="btn-mute control-icon-layout" title="Mute"> + <span id="iconMute" class="icon-mute-off"></span> + </div> + <div id="trackSwitchBtn" class="control-icon-layout" title="A/V Tracks"> + <span class="icon-tracks"></span> + </div> + <div id="captionBtn" class="btn-caption control-icon-layout" title="Closed Caption"> + <span class="icon-caption"></span> + </div> + <span id="videoDuration" class="duration-display">00:00:00</span> + <div class="seekContainer"> + <input type="range" id="seekbar" value="0" class="seekbar" min="0" step="0.01"/> + </div> + </div> +</div> + + +<!-- + this is an experimental hack, trying to protect the remaining page from + interference with the new dash-player. +--> +<script type="text/javascript"> +$(function() { + var $videoElement = $(".dashContainer video"); + var player = dashjs.MediaPlayer().create(); + player.initialize( + $videoElement.get(0), + $videoElement.prop('src'), + true + ); + + var controlbar = new ControlBar(player); + controlbar.initialize(); +}); +</script> +<style type="text/css"> +.dashContainer video { + display: block; +} +.dashContainer { + line-height: 1; +} +.dashContainer .volumebar { + width: 70px; +} +body.room .player-wrap.tab-content { + padding: 0; +} +</style> |