From 407f1370953633300f2891a031e62d793c5281b5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 3 Jan 2017 01:51:36 -0500 Subject: [PATCH] unify video osd --- dashboard-ui/components/apphost.js | 8 + .../components/dockedtabs/dockedtabs.js | 2 +- dashboard-ui/components/playerselection.js | 42 +- dashboard-ui/components/remotecontrol.js | 336 ++-- .../components/remotecontrolautoplay.js | 13 +- dashboard-ui/css/librarybrowser.css | 13 +- dashboard-ui/css/nowplayingbar.css | 5 + dashboard-ui/index.html | 8 + dashboard-ui/scripts/chromecast.js | 891 --------- dashboard-ui/scripts/htmlmediarenderer.js | 866 --------- dashboard-ui/scripts/indexpage.js | 6 +- dashboard-ui/scripts/itemdetailpage.js | 18 +- dashboard-ui/scripts/librarymenu.js | 23 +- dashboard-ui/scripts/mediacontroller.js | 854 +-------- dashboard-ui/scripts/mediaplayer-video.js | 1312 -------------- dashboard-ui/scripts/mediaplayer.js | 1614 ----------------- dashboard-ui/scripts/moviesrecommended.js | 6 +- dashboard-ui/scripts/mypreferencescommon.js | 2 +- dashboard-ui/scripts/nowplayingbar.js | 378 ++-- dashboard-ui/scripts/remotecontrol.js | 400 ---- dashboard-ui/scripts/site.js | 201 +- dashboard-ui/scripts/tvrecommended.js | 6 +- dashboard-ui/scripts/videoosd.js | 22 +- dashboard-ui/videoosd.html | 153 +- 24 files changed, 713 insertions(+), 6466 deletions(-) delete mode 100644 dashboard-ui/scripts/chromecast.js delete mode 100644 dashboard-ui/scripts/htmlmediarenderer.js delete mode 100644 dashboard-ui/scripts/mediaplayer-video.js delete mode 100644 dashboard-ui/scripts/mediaplayer.js delete mode 100644 dashboard-ui/scripts/remotecontrol.js diff --git a/dashboard-ui/components/apphost.js b/dashboard-ui/components/apphost.js index d4e88df7ba..4d988b34a1 100644 --- a/dashboard-ui/components/apphost.js +++ b/dashboard-ui/components/apphost.js @@ -153,6 +153,14 @@ define(['appStorage', 'browser'], function (appStorage, browser) { features.push('imageanalysis'); } + if (Dashboard.isConnectMode()) { + features.push('multiserver'); + } + + if (browser.tv || browser.xboxOne || browser.ps4 || browser.mobile) { + features.push('physicalvolumecontrol'); + } + return features; }(); diff --git a/dashboard-ui/components/dockedtabs/dockedtabs.js b/dashboard-ui/components/dockedtabs/dockedtabs.js index 7d55601620..da57c5337f 100644 --- a/dashboard-ui/components/dockedtabs/dockedtabs.js +++ b/dashboard-ui/components/dockedtabs/dockedtabs.js @@ -124,7 +124,7 @@ }); } - if (Dashboard.isConnectMode()) { + if (appHost.supports('multiserver')) { commands.push({ name: globalize.translate('HeaderSelectServer'), id: 'selectserver' diff --git a/dashboard-ui/components/playerselection.js b/dashboard-ui/components/playerselection.js index d6f8e24615..e9963cbabb 100644 --- a/dashboard-ui/components/playerselection.js +++ b/dashboard-ui/components/playerselection.js @@ -1,47 +1,53 @@ -define(['appSettings', 'events', 'browser', 'libraryMenu', 'loading'], function (appSettings, events, browser, libraryMenu, loading) { +define(['appSettings', 'events', 'browser', 'libraryMenu', 'loading', 'playbackManager'], function (appSettings, events, browser, libraryMenu, loading, playbackManager) { 'use strict'; var currentDisplayInfo; - function mirrorItem(info) { + function mirrorItem(info, player) { var item = info.item; - MediaController.getCurrentPlayer().displayContent({ + playbackManager.displayContent({ ItemName: item.Name, ItemId: item.Id, ItemType: item.Type, Context: info.context - }); + }, player); } function mirrorIfEnabled(info) { info = info || currentDisplayInfo; - if (info && MediaController.enableDisplayMirroring()) { + if (info && playbackManager.enableDisplayMirroring()) { - var player = MediaController.getPlayerInfo(); + var player = playbackManager.getPlayerInfo(); - if (!player.isLocalPlayer && player.supportedCommands.indexOf('DisplayContent') != -1) { - mirrorItem(info); + if (player) { + if (!player.isLocalPlayer && player.supportedCommands.indexOf('DisplayContent') != -1) { + mirrorItem(info, player); + } } } } function showPlayerSelection(button, enableHistory) { - var playerInfo = MediaController.getPlayerInfo(); + var currentPlayerInfo = playbackManager.getPlayerInfo(); - if (!playerInfo.isLocalPlayer) { - showActivePlayerMenu(playerInfo); - return; + if (currentPlayerInfo) { + if (!currentPlayerInfo.isLocalPlayer) { + showActivePlayerMenu(currentPlayerInfo); + return; + } } + var currentPlayerId = currentPlayerInfo ? currentPlayerInfo.id : null; + loading.show(); - MediaController.getTargets().then(function (targets) { + playbackManager.getTargets().then(function (targets) { var menuItems = targets.map(function (t) { @@ -54,7 +60,7 @@ return { name: name, id: t.id, - selected: playerInfo.id == t.id + selected: currentPlayerId === t.id }; }); @@ -84,7 +90,7 @@ return t.id == id; })[0]; - MediaController.trySetActivePlayer(target.playerName, target); + playbackManager.trySetActivePlayer(target.playerName, target); mirrorIfEnabled(); @@ -127,7 +133,7 @@ if (playerInfo.supportedCommands.indexOf('DisplayContent') != -1) { html += ''; @@ -162,7 +168,7 @@ } dlg.querySelector('.btnDisconnect').addEventListener('click', function () { - MediaController.disconnectFromPlayer(); + playbackManager.disconnectFromPlayer(); dialogHelper.close(dlg); }); @@ -178,7 +184,7 @@ } function onMirrorChange() { - MediaController.enableDisplayMirroring(this.checked); + playbackManager.enableDisplayMirroring(this.checked); } function onCastButtonClicked() { diff --git a/dashboard-ui/components/remotecontrol.js b/dashboard-ui/components/remotecontrol.js index 54cf846430..56ced61a72 100644 --- a/dashboard-ui/components/remotecontrol.js +++ b/dashboard-ui/components/remotecontrol.js @@ -1,4 +1,4 @@ -define(['browser', 'datetime', 'libraryBrowser', 'listView', 'userdataButtons', 'imageLoader', 'cardStyle'], function (browser, datetime, libraryBrowser, listView, userdataButtons, imageLoader) { +define(['browser', 'datetime', 'libraryBrowser', 'listView', 'userdataButtons', 'imageLoader', 'playbackManager', 'nowPlayingHelper', 'events', 'apphost', 'cardStyle'], function (browser, datetime, libraryBrowser, listView, userdataButtons, imageLoader, playbackManager, nowPlayingHelper, events, appHost) { 'use strict'; function showSlideshowMenu(context) { @@ -16,24 +16,8 @@ var menuItems = streams.map(function (s) { - var name = (s.Codec || '').toUpperCase(); - - if (s.Profile) { - name += ' ' + s.Profile; - } - - if (s.Language) { - name += ' · ' + s.Language; - } - if (s.Layout) { - name += ' · ' + s.Layout; - } - else if (s.Channels) { - name += ' · ' + s.Channels + ' ch'; - } - var menuItem = { - name: s.DisplayTitle || name, + name: s.DisplayTitle, id: s.Index }; @@ -67,24 +51,8 @@ var menuItems = streams.map(function (s) { - var name = (s.Language || Globalize.translate('LabelUnknownLanguage')); - - if (s.IsDefault && s.IsForced) { - name += ' · ' + Globalize.translate('LabelDefaultForcedStream'); - } - else if (s.IsDefault) { - name += ' · ' + Globalize.translate('LabelDefaultStream'); - } - else if (s.IsForced) { - name += ' · ' + Globalize.translate('LabelForcedStream'); - } - - if (s.Codec) { - name += ' · ' + s.Codec.toUpperCase(); - } - var menuItem = { - name: s.DisplayTitle || name, + name: s.DisplayTitle, id: s.Index }; @@ -129,11 +97,22 @@ }).length > 0; } + function getNowPlayingNameHtml(nowPlayingItem, includeNonNameInfo) { + + var names = nowPlayingHelper.getNowPlayingNames(nowPlayingItem, includeNonNameInfo); + + return names.map(function (i) { + + return i.text; + + }).join('
'); + } + var currentImgUrl; function updateNowPlayingInfo(context, state) { var item = state.NowPlayingItem; - var displayName = item ? MediaController.getNowPlayingNameHtml(item).replace('
', ' - ') : ''; + var displayName = item ? getNowPlayingNameHtml(item).replace('
', ' - ') : ''; context.querySelector('.nowPlayingPageTitle').innerHTML = displayName; @@ -248,25 +227,27 @@ var dlg; var currentPlayer; + var currentPlayerSupportedCommands = []; var lastPlayerState; var lastUpdateTime = 0; + var currentRuntimeTicks = 0; var self = this; var playlistNeedsRefresh = true; function toggleRepeat(player) { - + if (player && lastPlayerState) { var state = lastPlayerState; switch ((state.PlayState || {}).RepeatMode) { case 'RepeatNone': - player.setRepeatMode('RepeatAll'); + playbackManager.setRepeatMode('RepeatAll', player); break; case 'RepeatAll': - player.setRepeatMode('RepeatOne'); + playbackManager.setRepeatMode('RepeatOne', player); break; case 'RepeatOne': - player.setRepeatMode('RepeatNone'); + playbackManager.setRepeatMode('RepeatNone', player); break; } } @@ -278,7 +259,7 @@ var item = state.NowPlayingItem; - var playerInfo = MediaController.getPlayerInfo(); + var playerInfo = playbackManager.getPlayerInfo(); var supportedCommands = playerInfo.supportedCommands; var playState = state.PlayState || {}; @@ -310,53 +291,16 @@ buttonEnabled(context.querySelector('.btnNextTrack'), item != null); buttonEnabled(context.querySelector('.btnPreviousTrack'), item != null); - var btnPause = context.querySelector('.btnPause'); - var btnPlay = context.querySelector('.btnPlay'); - - buttonEnabled(btnPause, item != null); - buttonEnabled(btnPlay, item != null); - - if (playState.IsPaused) { - - hideButton(btnPause); - showButton(btnPlay); - - } else { - - showButton(btnPause); - hideButton(btnPlay); - } - var positionSlider = context.querySelector('.nowPlayingPositionSlider'); - - if (!positionSlider.dragging) { - - if (item && item.RunTimeTicks) { - - var pct = playState.PositionTicks / item.RunTimeTicks; - pct *= 100; - - positionSlider.value = pct; - - } else { - - positionSlider.value = 0; - } - + if (positionSlider && !positionSlider.dragging) { positionSlider.disabled = !playState.CanSeek; } - if (playState.PositionTicks == null) { - context.querySelector('.positionTime').innerHTML = '--:--'; - } else { - context.querySelector('.positionTime').innerHTML = datetime.getDisplayRunningTime(playState.PositionTicks); - } + updatePlayPauseState(playState.IsPaused, item != null); - if (item && item.RunTimeTicks != null) { - context.querySelector('.runtime').innerHTML = datetime.getDisplayRunningTime(item.RunTimeTicks); - } else { - context.querySelector('.runtime').innerHTML = '--:--'; - } + var runtimeTicks = item ? item.RunTimeTicks : null; + updateTimeDisplay(playState.PositionTicks, runtimeTicks); + updatePlayerVolumeState(playState.IsMuted, playState.VolumeLevel); if (item && item.MediaType == 'Video') { context.classList.remove('hideVideoButtons'); @@ -364,7 +308,7 @@ context.classList.add('hideVideoButtons'); } - if (playerInfo.isLocalPlayer && AppInfo.hasPhysicalVolumeButtons) { + if (playerInfo.isLocalPlayer && appHost.supports('physicalvolumecontrol')) { context.classList.add('hideVolumeButtons'); } else { context.classList.remove('hideVolumeButtons'); @@ -393,6 +337,65 @@ updateNowPlayingInfo(context, state); } + function updatePlayerVolumeState(isMuted, volumeLevel) { + + } + + function updatePlayPauseState(isPaused, isActive) { + + var context = dlg; + + var btnPause = context.querySelector('.btnPause'); + var btnPlay = context.querySelector('.btnPlay'); + + buttonEnabled(btnPause, isActive); + buttonEnabled(btnPlay, isActive); + + if (isPaused) { + + hideButton(btnPause); + showButton(btnPlay); + + } else { + + showButton(btnPause); + hideButton(btnPlay); + } + } + + function updateTimeDisplay(positionTicks, runtimeTicks) { + + // See bindEvents for why this is necessary + var context = dlg; + var positionSlider = context.querySelector('.nowPlayingPositionSlider'); + + if (positionSlider && !positionSlider.dragging) { + if (runtimeTicks) { + + var pct = positionTicks / runtimeTicks; + pct *= 100; + + positionSlider.value = pct; + + } else { + + positionSlider.value = 0; + } + } + + if (positionTicks == null) { + context.querySelector('.positionTime').innerHTML = '--:--'; + } else { + context.querySelector('.positionTime').innerHTML = datetime.getDisplayRunningTime(positionTicks); + } + + if (runtimeTicks != null) { + context.querySelector('.runtime').innerHTML = datetime.getDisplayRunningTime(runtimeTicks); + } else { + context.querySelector('.runtime').innerHTML = '--:--'; + } + } + function loadPlaylist(context) { var html = ''; @@ -420,7 +423,7 @@ //}); html += listView.getListViewHtml({ - items: MediaController.playlist(), + items: playbackManager.playlist(), smallIcon: true, action: 'setplaylistindex' }); @@ -435,7 +438,7 @@ itemsContainer.innerHTML = html; - var index = MediaController.currentPlaylistIndex(); + var index = playbackManager.currentPlaylistIndex(); if (index != -1) { @@ -452,27 +455,12 @@ }); } - function onStateChanged(e, state) { - - if (e.type == 'positionchange') { - // Try to avoid hammering the document with changes - var now = new Date().getTime(); - if ((now - lastUpdateTime) < 700) { - - return; - } - lastUpdateTime = now; - } - - updatePlayerState(dlg, state); - } - function onPlaybackStart(e, state) { + console.log('remotecontrol event: ' + e.type); + var player = this; - - player.beginPlayerUpdates(); - + playbackManager.beginPlayerUpdates(player); onStateChanged.call(player, e, state); loadPlaylist(dlg); @@ -480,26 +468,66 @@ function onPlaybackStopped(e, state) { + console.log('remotecontrol event: ' + e.type); var player = this; - player.endPlayerUpdates(); - - onStateChanged.call(player, e, {}); + playbackManager.endPlayerUpdates(player); loadPlaylist(dlg); } + function onPlayPauseStateChanged(e) { + + var player = this; + updatePlayPauseState(player.paused(), true); + } + + function onStateChanged(event, state) { + + //console.log('nowplaying event: ' + e.type); + var player = this; + + updatePlayerState(dlg, state); + } + + function onTimeUpdate(e) { + + // Try to avoid hammering the document with changes + var now = new Date().getTime(); + if ((now - lastUpdateTime) < 700) { + + return; + } + lastUpdateTime = now; + + var player = this; + var state = lastPlayerState; + var nowPlayingItem = state.NowPlayingItem || {}; + currentRuntimeTicks = playbackManager.duration(player); + updateTimeDisplay(playbackManager.currentTime(player), currentRuntimeTicks); + } + + function onVolumeChanged(e) { + + var player = this; + + updatePlayerVolumeState(player.isMuted(), player.getVolume()); + } + function releaseCurrentPlayer() { - if (currentPlayer) { + var player = currentPlayer; - Events.off(currentPlayer, 'playbackstart', onPlaybackStart); - Events.off(currentPlayer, 'playbackstop', onPlaybackStopped); - Events.off(currentPlayer, 'volumechange', onStateChanged); - Events.off(currentPlayer, 'playstatechange', onStateChanged); - Events.off(currentPlayer, 'positionchange', onStateChanged); + if (player) { - currentPlayer.endPlayerUpdates(); + events.off(player, 'playbackstart', onPlaybackStart); + events.off(player, 'playbackstop', onPlaybackStopped); + events.off(player, 'volumechange', onVolumeChanged); + events.off(player, 'pause', onPlayPauseStateChanged); + events.off(player, 'playing', onPlayPauseStateChanged); + events.off(player, 'timeupdate', onTimeUpdate); + + playbackManager.endPlayerUpdates(player); currentPlayer = null; } } @@ -510,67 +538,58 @@ currentPlayer = player; - player.getPlayerState().then(function (state) { + if (!player) { + return; + } + + playbackManager.getPlayerState(player).then(function (state) { if (state.NowPlayingItem) { - player.beginPlayerUpdates(); + playbackManager.beginPlayerUpdates(player); } onStateChanged.call(player, { type: 'init' }, state); }); - Events.on(player, 'playbackstart', onPlaybackStart); - Events.on(player, 'playbackstop', onPlaybackStopped); - Events.on(player, 'volumechange', onStateChanged); - Events.on(player, 'playstatechange', onStateChanged); - Events.on(player, 'positionchange', onStateChanged); + events.on(player, 'playbackstart', onPlaybackStart); + events.on(player, 'playbackstop', onPlaybackStopped); + events.on(player, 'volumechange', onVolumeChanged); + events.on(player, 'pause', onPlayPauseStateChanged); + events.on(player, 'playing', onPlayPauseStateChanged); + events.on(player, 'timeupdate', onTimeUpdate); - var playerInfo = MediaController.getPlayerInfo(); + var playerInfo = playbackManager.getPlayerInfo(); var supportedCommands = playerInfo.supportedCommands; + currentPlayerSupportedCommands = supportedCommands; updateSupportedCommands(context, supportedCommands); } function updateCastIcon(context) { - var info = MediaController.getPlayerInfo(); + var info = playbackManager.getPlayerInfo(); var btnCast = context.querySelector('.nowPlayingCastIcon'); - if (info.isLocalPlayer) { - - btnCast.querySelector('i').innerHTML = 'cast'; - btnCast.classList.remove('btnActiveCast'); - context.querySelector('.nowPlayingSelectedPlayer').innerHTML = ''; - - } else { + if (info && !info.isLocalPlayer) { btnCast.querySelector('i').innerHTML = 'cast_connected'; btnCast.classList.add('btnActiveCast'); context.querySelector('.nowPlayingSelectedPlayer').innerHTML = info.deviceName || info.name; + } else { + btnCast.querySelector('i').innerHTML = 'cast'; + btnCast.classList.remove('btnActiveCast'); + context.querySelector('.nowPlayingSelectedPlayer').innerHTML = ''; } } - function parentWithClass(elem, className) { - - while (!elem.classList || !elem.classList.contains(className)) { - elem = elem.parentNode; - - if (!elem) { - return null; - } - } - - return elem; - } - function onBtnCommandClick() { if (currentPlayer) { if (this.classList.contains('repeatToggleButton')) { toggleRepeat(currentPlayer); } else { - MediaController.sendCommand({ + playbackManager.sendCommand({ Name: this.getAttribute('data-command') }, currentPlayer); @@ -588,7 +607,7 @@ context.querySelector('.btnToggleFullscreen').addEventListener('click', function (e) { if (currentPlayer) { - MediaController.sendCommand({ + playbackManager.sendCommand({ Name: e.target.getAttribute('data-command') }, currentPlayer); @@ -625,7 +644,7 @@ context.querySelector('.btnStop').addEventListener('click', function () { if (currentPlayer) { - currentPlayer.stop(); + playbackManager.stop(currentPlayer); } }); @@ -646,14 +665,14 @@ context.querySelector('.btnNextTrack').addEventListener('click', function () { if (currentPlayer) { - currentPlayer.nextTrack(); + playbackManager.nextTrack(currentPlayer); } }); context.querySelector('.btnPreviousTrack').addEventListener('click', function () { if (currentPlayer) { - currentPlayer.previousTrack(); + playbackManager.previousTrack(currentPlayer); } }); @@ -661,11 +680,10 @@ var value = this.value; - if (currentPlayer && lastPlayerState) { + if (currentPlayer) { var newPercent = parseFloat(value); - var newPositionTicks = (newPercent / 100) * lastPlayerState.NowPlayingItem.RunTimeTicks; - currentPlayer.seek(Math.floor(newPositionTicks)); + playbackManager.seekPercent(newPercent, currentPlayer); } }); @@ -673,11 +691,11 @@ var state = lastPlayerState; - if (!state || !state.NowPlayingItem || !state.NowPlayingItem.RunTimeTicks) { + if (!state || !state.NowPlayingItem || !currentRuntimeTicks) { return '--:--'; } - var ticks = state.NowPlayingItem.RunTimeTicks; + var ticks = currentRuntimeTicks; ticks /= 100; ticks *= value; @@ -689,14 +707,14 @@ var context = dlg; updateCastIcon(context); - bindToPlayer(context, MediaController.getCurrentPlayer()); + bindToPlayer(context, playbackManager.getCurrentPlayer()); } function onMessageSubmit(e) { var form = e.target; - MediaController.sendCommand({ + playbackManager.sendCommand({ Name: 'DisplayMessage', Arguments: { @@ -720,7 +738,7 @@ var form = e.target; - MediaController.sendCommand({ + playbackManager.sendCommand({ Name: 'SendString', Arguments: { @@ -774,14 +792,14 @@ } }); - Events.on(MediaController, 'playerchange', onPlayerChange); + events.on(playbackManager, 'playerchange', onPlayerChange); } function onDialogClosed(e) { releaseCurrentPlayer(); - Events.off(MediaController, 'playerchange', onPlayerChange); + events.off(playbackManager, 'playerchange', onPlayerChange); lastPlayerState = null; } @@ -790,7 +808,7 @@ currentImgUrl = null; - bindToPlayer(context, MediaController.getCurrentPlayer()); + bindToPlayer(context, playbackManager.getCurrentPlayer()); updateCastIcon(context); } diff --git a/dashboard-ui/components/remotecontrolautoplay.js b/dashboard-ui/components/remotecontrolautoplay.js index 900dc46596..de7bd8b445 100644 --- a/dashboard-ui/components/remotecontrolautoplay.js +++ b/dashboard-ui/components/remotecontrolautoplay.js @@ -1,7 +1,7 @@ -define(['events'], function (events) { +define(['events', 'playbackManager'], function (events, playbackManager) { 'use strict'; - function transferPlayback(oldPlayer) { + function transferPlayback(oldPlayer, newPlayer) { oldPlayer.getPlayerState().then(function (state) { @@ -18,7 +18,7 @@ var itemId = item.Id; var resumePositionTicks = playState.PositionTicks || 0; - MediaController.play({ + playbackManager.play({ ids: [itemId], startPositionTicks: resumePositionTicks }); @@ -26,10 +26,9 @@ }); } - events.on(MediaController, 'playerchange', function (e, newPlayer, newTarget, oldPlayer) { + events.on(playbackManager, 'playerchange', function (e, newPlayer, newTarget, oldPlayer) { - if (!oldPlayer) { - console.log('Skipping remote control autoplay because oldPlayer is null'); + if (!oldPlayer || !newPlayer) { return; } @@ -45,7 +44,7 @@ // If playback is playing locally and a new player is activated, transfer the media to that player if (oldPlayer.isPlaying()) { - transferPlayback(oldPlayer); + transferPlayback(oldPlayer, newPlayer); } }); diff --git a/dashboard-ui/css/librarybrowser.css b/dashboard-ui/css/librarybrowser.css index 050819752c..253f6d248f 100644 --- a/dashboard-ui/css/librarybrowser.css +++ b/dashboard-ui/css/librarybrowser.css @@ -13,7 +13,7 @@ .background-theme-b .backgroundContainer.withBackdrop { background-color: rgba(6, 6, 6, .94) !important; - background: linear-gradient(to right, rgba(0, 0, 0, .99), rgba(0, 0, 0, .92), rgba(0, 0, 0, .5)) !important; + background: linear-gradient(to right, rgba(0, 0, 0, .99), rgba(0, 0, 0, .94), rgba(0, 0, 0, .5)) !important; } .ui-body-b { @@ -797,17 +797,10 @@ span.itemCommunityRating:not(:empty) + .userDataIcons { } .mediaInfoText { - background: rgba(31,31,31,.7); - padding: .3em .5em; - border-radius: .25em; - color: #ddd; + padding: .3em .5em !important; margin-right: .5em; margin-bottom: .5em; - font-size: 94%; - background: rgba(170,170,190, .2); - display: flex; - align-items: center; - white-space: nowrap; + font-size: 94% !important; } .mediaInfoText-upper { diff --git a/dashboard-ui/css/nowplayingbar.css b/dashboard-ui/css/nowplayingbar.css index b7055e0512..2d2112726d 100644 --- a/dashboard-ui/css/nowplayingbar.css +++ b/dashboard-ui/css/nowplayingbar.css @@ -54,6 +54,11 @@ will-change: transform; contain: layout style; font-size: 90%; + transition: transform 200ms ease-out; +} + +.nowPlayingBar-hidden { + transform: translate3d(0,100%,0); } .hiddenNowPlayingBar .nowPlayingBar { diff --git a/dashboard-ui/index.html b/dashboard-ui/index.html index 5610bf04c7..4701232462 100644 --- a/dashboard-ui/index.html +++ b/dashboard-ui/index.html @@ -2,6 +2,14 @@ Emby + + +
diff --git a/dashboard-ui/scripts/chromecast.js b/dashboard-ui/scripts/chromecast.js deleted file mode 100644 index 3ac9a14e80..0000000000 --- a/dashboard-ui/scripts/chromecast.js +++ /dev/null @@ -1,891 +0,0 @@ -define(['appSettings'], function (appSettings) { - 'use strict'; - - // Based on https://github.com/googlecast/CastVideos-chrome/blob/master/CastVideos.js - var currentResolve; - var currentReject; - - var PlayerName = 'Chromecast'; - - function sendConnectionResult(isOk) { - - var resolve = currentResolve; - var reject = currentReject; - - currentResolve = null; - currentReject = null; - - if (isOk) { - if (resolve) { - resolve(); - } - } else { - if (reject) { - reject(); - } else { - MediaController.removeActivePlayer(PlayerName); - } - } - } - - /** - * Constants of states for Chromecast device - **/ - var DEVICE_STATE = { - 'IDLE': 0, - 'ACTIVE': 1, - 'WARNING': 2, - 'ERROR': 3 - }; - - /** - * Constants of states for CastPlayer - **/ - var PLAYER_STATE = { - 'IDLE': 'IDLE', - 'LOADING': 'LOADING', - 'LOADED': 'LOADED', - 'PLAYING': 'PLAYING', - 'PAUSED': 'PAUSED', - 'STOPPED': 'STOPPED', - 'SEEKING': 'SEEKING', - 'ERROR': 'ERROR' - }; - - var applicationID = "2D4B1DA3"; - - // This is the beta version used for testing new changes - - //applicationID = '27C4EB5B'; - - var messageNamespace = 'urn:x-cast:com.connectsdk'; - - var CastPlayer = function () { - - /* device variables */ - // @type {DEVICE_STATE} A state for device - this.deviceState = DEVICE_STATE.IDLE; - - /* Cast player variables */ - // @type {Object} a chrome.cast.media.Media object - this.currentMediaSession = null; - - // @type {string} a chrome.cast.Session object - this.session = null; - // @type {PLAYER_STATE} A state for Cast media player - this.castPlayerState = PLAYER_STATE.IDLE; - - this.hasReceivers = false; - - // bind once - commit 2ebffc2271da0bc5e8b13821586aee2a2e3c7753 - this.errorHandler = this.onError.bind(this); - this.mediaStatusUpdateHandler = this.onMediaStatusUpdate.bind(this); - - this.initializeCastPlayer(); - }; - - /** - * Initialize Cast media player - * Initializes the API. Note that either successCallback and errorCallback will be - * invoked once the API has finished initialization. The sessionListener and - * receiverListener may be invoked at any time afterwards, and possibly more than once. - */ - CastPlayer.prototype.initializeCastPlayer = function () { - - var chrome = window.chrome; - - if (!chrome) { - return; - } - - if (!chrome.cast || !chrome.cast.isAvailable) { - - setTimeout(this.initializeCastPlayer.bind(this), 1000); - return; - } - - // request session - var sessionRequest = new chrome.cast.SessionRequest(applicationID); - var apiConfig = new chrome.cast.ApiConfig(sessionRequest, - this.sessionListener.bind(this), - this.receiverListener.bind(this), - "origin_scoped"); - - console.log('chromecast.initialize'); - - chrome.cast.initialize(apiConfig, this.onInitSuccess.bind(this), this.errorHandler); - - }; - - /** - * Callback function for init success - */ - CastPlayer.prototype.onInitSuccess = function () { - this.isInitialized = true; - console.log("chromecast init success"); - }; - - /** - * Generic error callback function - */ - CastPlayer.prototype.onError = function () { - console.log("chromecast error"); - }; - - /** - * @param {!Object} e A new session - * This handles auto-join when a page is reloaded - * When active session is detected, playback will automatically - * join existing session and occur in Cast mode and media - * status gets synced up with current media of the session - */ - CastPlayer.prototype.sessionListener = function (e) { - - this.session = e; - if (this.session) { - - console.log('sessionListener ' + JSON.stringify(e)); - - if (this.session.media[0]) { - this.onMediaDiscovered('activeSession', this.session.media[0]); - } - - this.onSessionConnected(e); - } - }; - - CastPlayer.prototype.messageListener = function (namespace, message) { - - if (typeof (message) === 'string') { - message = JSON.parse(message); - } - - if (message.type == 'playbackerror') { - - var errorCode = message.data; - - setTimeout(function () { - Dashboard.alert({ - message: Globalize.translate('MessagePlaybackError' + errorCode), - title: Globalize.translate('HeaderPlaybackError') - }); - }, 300); - - } - else if (message.type == 'connectionerror') { - - setTimeout(function () { - Dashboard.alert({ - message: Globalize.translate('MessageChromecastConnectionError'), - title: Globalize.translate('HeaderError') - }); - }, 300); - - } - else if (message.type) { - Events.trigger(this, message.type, [message.data]); - } - }; - - /** - * @param {string} e Receiver availability - * This indicates availability of receivers but - * does not provide a list of device IDs - */ - CastPlayer.prototype.receiverListener = function (e) { - - if (e === 'available') { - console.log("chromecast receiver found"); - this.hasReceivers = true; - } - else { - console.log("chromecast receiver list empty"); - this.hasReceivers = false; - } - }; - - /** - * session update listener - */ - CastPlayer.prototype.sessionUpdateListener = function (isAlive) { - - console.log('sessionUpdateListener alive: ' + isAlive); - - if (isAlive) { - } - else { - this.session = null; - this.deviceState = DEVICE_STATE.IDLE; - this.castPlayerState = PLAYER_STATE.IDLE; - - console.log('sessionUpdateListener: setting currentMediaSession to null'); - this.currentMediaSession = null; - - sendConnectionResult(false); - } - }; - - /** - * Requests that a receiver application session be created or joined. By default, the SessionRequest - * passed to the API at initialization time is used; this may be overridden by passing a different - * session request in opt_sessionRequest. - */ - CastPlayer.prototype.launchApp = function () { - console.log("chromecast launching app..."); - chrome.cast.requestSession(this.onRequestSessionSuccess.bind(this), this.onLaunchError.bind(this)); - }; - - /** - * Callback function for request session success - * @param {Object} e A chrome.cast.Session object - */ - CastPlayer.prototype.onRequestSessionSuccess = function (e) { - - console.log("chromecast session success: " + e.sessionId); - this.onSessionConnected(e); - }; - - CastPlayer.prototype.onSessionConnected = function (session) { - - this.session = session; - - this.deviceState = DEVICE_STATE.ACTIVE; - - this.session.addMessageListener(messageNamespace, this.messageListener.bind(this)); - this.session.addMediaListener(this.sessionMediaListener.bind(this)); - this.session.addUpdateListener(this.sessionUpdateListener.bind(this)); - - Events.trigger(this, 'connect'); - - this.sendMessage({ - options: {}, - command: 'Identify' - }); - }; - - /** - * session update listener - */ - CastPlayer.prototype.sessionMediaListener = function (e) { - - console.log('sessionMediaListener'); - this.currentMediaSession = e; - this.currentMediaSession.addUpdateListener(this.mediaStatusUpdateHandler); - }; - - /** - * Callback function for launch error - */ - CastPlayer.prototype.onLaunchError = function () { - console.log("chromecast launch error"); - this.deviceState = DEVICE_STATE.ERROR; - - sendConnectionResult(false); - }; - - /** - * Stops the running receiver application associated with the session. - */ - CastPlayer.prototype.stopApp = function () { - - if (this.session) { - this.session.stop(this.onStopAppSuccess.bind(this, 'Session stopped'), - this.errorHandler); - } - - }; - - /** - * Callback function for stop app success - */ - CastPlayer.prototype.onStopAppSuccess = function (message) { - console.log(message); - this.deviceState = DEVICE_STATE.IDLE; - this.castPlayerState = PLAYER_STATE.IDLE; - - console.log('onStopAppSuccess: setting currentMediaSession to null'); - this.currentMediaSession = null; - }; - - /** - * Loads media into a running receiver application - * @param {Number} mediaIndex An index number to indicate current media content - */ - CastPlayer.prototype.loadMedia = function (options, command) { - - if (!this.session) { - console.log("no session"); - return Promise.reject(); - } - - // Convert the items to smaller stubs to send the minimal amount of information - options.items = options.items.map(function (i) { - - return { - Id: i.Id, - Name: i.Name, - Type: i.Type, - MediaType: i.MediaType, - IsFolder: i.IsFolder - }; - }); - - return this.sendMessage({ - options: options, - command: command - }); - }; - - CastPlayer.prototype.sendMessage = function (message) { - - var player = this; - - var receiverName = null; - - if (castPlayer.session && castPlayer.session.receiver && castPlayer.session.receiver.friendlyName) { - receiverName = castPlayer.session.receiver.friendlyName; - } - - message = Object.assign(message, { - userId: Dashboard.getCurrentUserId(), - deviceId: ApiClient.deviceId(), - accessToken: ApiClient.accessToken(), - serverAddress: ApiClient.serverAddress(), - receiverName: receiverName - }); - - var bitrateSetting = appSettings.maxChromecastBitrate(); - if (bitrateSetting) { - message.maxBitrate = bitrateSetting; - } - - return new Promise(function (resolve, reject) { - - require(['chromecasthelpers'], function (chromecasthelpers) { - - chromecasthelpers.getServerAddress(ApiClient).then(function (serverAddress) { - message.serverAddress = serverAddress; - player.sendMessageInternal(message).then(resolve, reject); - - }, reject); - }); - }); - }; - - CastPlayer.prototype.sendMessageInternal = function (message) { - - message = JSON.stringify(message); - //console.log(message); - - this.session.sendMessage(messageNamespace, message, this.onPlayCommandSuccess.bind(this), this.errorHandler); - return Promise.resolve(); - }; - - CastPlayer.prototype.onPlayCommandSuccess = function () { - console.log('Message was sent to receiver ok.'); - }; - - /** - * Callback function for loadMedia success - * @param {Object} mediaSession A new media object. - */ - CastPlayer.prototype.onMediaDiscovered = function (how, mediaSession) { - - console.log("chromecast new media session ID:" + mediaSession.mediaSessionId + ' (' + how + ')'); - this.currentMediaSession = mediaSession; - - if (how == 'loadMedia') { - this.castPlayerState = PLAYER_STATE.PLAYING; - } - - if (how == 'activeSession') { - this.castPlayerState = mediaSession.playerState; - } - - this.currentMediaSession.addUpdateListener(this.mediaStatusUpdateHandler); - }; - - /** - * Callback function for media status update from receiver - * @param {!Boolean} e true/false - */ - CastPlayer.prototype.onMediaStatusUpdate = function (e) { - - if (e == false) { - this.castPlayerState = PLAYER_STATE.IDLE; - } - console.log("chromecast updating media: " + e); - }; - - /** - * Set media volume in Cast mode - * @param {Boolean} mute A boolean - */ - CastPlayer.prototype.setReceiverVolume = function (mute, vol) { - - if (!this.currentMediaSession) { - console.log('this.currentMediaSession is null'); - return; - } - - if (!mute) { - - this.session.setReceiverVolumeLevel((vol || 1), - this.mediaCommandSuccessCallback.bind(this), - this.errorHandler); - } - else { - this.session.setReceiverMuted(true, - this.mediaCommandSuccessCallback.bind(this), - this.errorHandler); - } - }; - - /** - * Mute CC - */ - CastPlayer.prototype.mute = function () { - this.setReceiverVolume(true); - }; - - /** - * Callback function for media command success - */ - CastPlayer.prototype.mediaCommandSuccessCallback = function (info, e) { - console.log(info); - }; - - // Create Cast Player - var castPlayer; - - function chromecastPlayer() { - - var self = this; - - // MediaController needs this - self.name = PlayerName; - - self.getItemsForPlayback = function (query) { - - var userId = Dashboard.getCurrentUserId(); - - if (query.Ids && query.Ids.split(',').length == 1) { - return ApiClient.getItem(userId, query.Ids.split(',')).then(function (item) { - return { - Items: [item], - TotalRecordCount: 1 - }; - }); - } - else { - - query.Limit = query.Limit || 100; - query.ExcludeLocationTypes = "Virtual"; - - return ApiClient.getItems(userId, query); - } - }; - - Events.on(castPlayer, "connect", function (e) { - - if (currentResolve) { - sendConnectionResult(true); - } else { - MediaController.setActivePlayer(PlayerName, self.getCurrentTargetInfo()); - } - - console.log('cc: connect'); - // Reset this so the next query doesn't make it appear like content is playing. - self.lastPlayerData = {}; - }); - - Events.on(castPlayer, "playbackstart", function (e, data) { - - console.log('cc: playbackstart'); - - castPlayer.initializeCastPlayer(); - - var state = self.getPlayerStateInternal(data); - Events.trigger(self, "playbackstart", [state]); - }); - - Events.on(castPlayer, "playbackstop", function (e, data) { - - console.log('cc: playbackstop'); - var state = self.getPlayerStateInternal(data); - - Events.trigger(self, "playbackstop", [state]); - - // Reset this so the next query doesn't make it appear like content is playing. - self.lastPlayerData = {}; - }); - - Events.on(castPlayer, "playbackprogress", function (e, data) { - - console.log('cc: positionchange'); - var state = self.getPlayerStateInternal(data); - - Events.trigger(self, "positionchange", [state]); - }); - - Events.on(castPlayer, "volumechange", function (e, data) { - - console.log('cc: volumechange'); - var state = self.getPlayerStateInternal(data); - - Events.trigger(self, "volumechange", [state]); - }); - - Events.on(castPlayer, "playstatechange", function (e, data) { - - console.log('cc: playstatechange'); - var state = self.getPlayerStateInternal(data); - - Events.trigger(self, "playstatechange", [state]); - }); - - self.play = function (options) { - - return Dashboard.getCurrentUser().then(function (user) { - - if (options.items) { - - return self.playWithCommand(options, 'PlayNow'); - - } else { - - return self.getItemsForPlayback({ - - Ids: options.ids.join(',') - - }).then(function (result) { - - options.items = result.Items; - return self.playWithCommand(options, 'PlayNow'); - - }); - } - - }); - - }; - - self.playWithCommand = function (options, command) { - - if (!options.items) { - return ApiClient.getItem(Dashboard.getCurrentUserId(), options.ids[0]).then(function (item) { - - options.items = [item]; - return self.playWithCommand(options, command); - }); - } - - return castPlayer.loadMedia(options, command); - }; - - self.unpause = function () { - castPlayer.sendMessage({ - options: {}, - command: 'Unpause' - }); - }; - - self.pause = function () { - castPlayer.sendMessage({ - options: {}, - command: 'Pause' - }); - }; - - self.shuffle = function (id) { - - var userId = Dashboard.getCurrentUserId(); - - ApiClient.getItem(userId, id).then(function (item) { - - self.playWithCommand({ - - items: [item] - - }, 'Shuffle'); - - }); - - }; - - self.instantMix = function (id) { - - var userId = Dashboard.getCurrentUserId(); - - ApiClient.getItem(userId, id).then(function (item) { - - self.playWithCommand({ - - items: [item] - - }, 'InstantMix'); - - }); - - }; - - self.canQueueMediaType = function (mediaType) { - return mediaType == "Audio"; - }; - - self.queue = function (options) { - self.playWithCommand(options, 'PlayLast'); - }; - - self.queueNext = function (options) { - self.playWithCommand(options, 'PlayNext'); - }; - - self.stop = function () { - castPlayer.sendMessage({ - options: {}, - command: 'Stop' - }); - }; - - self.displayContent = function (options) { - - castPlayer.sendMessage({ - options: options, - command: 'DisplayContent' - }); - }; - - self.mute = function () { - castPlayer.sendMessage({ - options: {}, - command: 'Mute' - }); - //castPlayer.mute(); - }; - - self.unMute = function () { - self.setVolume(getCurrentVolume() + 2); - }; - - self.setRepeatMode = function (mode) { - castPlayer.sendMessage({ - options: { - RepeatMode: mode - }, - command: 'SetRepeatMode' - }); - }; - - self.toggleMute = function () { - - var state = self.lastPlayerData || {}; - state = state.PlayState || {}; - - if (state.IsMuted) { - self.unMute(); - } else { - self.mute(); - } - }; - - self.getTargets = function () { - - var targets = []; - - if (castPlayer.hasReceivers) { - targets.push(self.getCurrentTargetInfo()); - } - - return Promise.resolve(targets); - }; - - self.getCurrentTargetInfo = function () { - - var appName = null; - - if (castPlayer.session && castPlayer.session.receiver && castPlayer.session.receiver.friendlyName) { - appName = castPlayer.session.receiver.friendlyName; - } - - return { - name: PlayerName, - id: PlayerName, - playerName: PlayerName, - playableMediaTypes: ["Audio", "Video"], - isLocalPlayer: false, - appName: PlayerName, - deviceName: appName, - supportedCommands: ["VolumeUp", - "VolumeDown", - "Mute", - "Unmute", - "ToggleMute", - "SetVolume", - "SetAudioStreamIndex", - "SetSubtitleStreamIndex", - "DisplayContent", - "SetRepeatMode", - "EndSession"] - }; - }; - - self.seek = function (position) { - - position = parseInt(position); - - position = position / 10000000; - - castPlayer.sendMessage({ - options: { - position: position - }, - command: 'Seek' - }); - }; - - self.setAudioStreamIndex = function (index) { - castPlayer.sendMessage({ - options: { - index: index - }, - command: 'SetAudioStreamIndex' - }); - }; - - self.setSubtitleStreamIndex = function (index) { - castPlayer.sendMessage({ - options: { - index: index - }, - command: 'SetSubtitleStreamIndex' - }); - }; - - self.nextTrack = function () { - castPlayer.sendMessage({ - options: {}, - command: 'NextTrack' - }); - }; - - self.previousTrack = function () { - castPlayer.sendMessage({ - options: {}, - command: 'PreviousTrack' - }); - }; - - self.beginPlayerUpdates = function () { - // Setup polling here - }; - - self.endPlayerUpdates = function () { - // Stop polling here - }; - - function getCurrentVolume() { - var state = self.lastPlayerData || {}; - state = state.PlayState || {}; - - return state.VolumeLevel == null ? 100 : state.VolumeLevel; - } - - self.volumeDown = function () { - - castPlayer.sendMessage({ - options: {}, - command: 'VolumeDown' - }); - }; - - self.endSession = function () { - - self.stop(); - setTimeout(function () { - castPlayer.stopApp(); - }, 1000); - }; - - self.volumeUp = function () { - - castPlayer.sendMessage({ - options: {}, - command: 'VolumeUp' - }); - }; - - self.setVolume = function (vol) { - - vol = Math.min(vol, 100); - vol = Math.max(vol, 0); - - //castPlayer.setReceiverVolume(false, (vol / 100)); - castPlayer.sendMessage({ - options: { - volume: vol - }, - command: 'SetVolume' - }); - }; - - self.getPlayerState = function () { - - var result = self.getPlayerStateInternal(); - return Promise.resolve(result); - }; - - self.lastPlayerData = {}; - - self.getPlayerStateInternal = function (data) { - - data = data || self.lastPlayerData; - self.lastPlayerData = data; - - console.log(JSON.stringify(data)); - return data; - }; - - self.tryPair = function (target) { - - if (castPlayer.deviceState != DEVICE_STATE.ACTIVE && castPlayer.isInitialized) { - - return new Promise(function (resolve, reject) { - currentResolve = resolve; - currentReject = reject; - - castPlayer.launchApp(); - }); - } else { - - currentResolve = null; - currentReject = null; - - return Promise.reject(); - } - }; - } - - function initializeChromecast() { - - castPlayer = new CastPlayer(); - - var registeredPlayer = new chromecastPlayer(); - window.CCastPlayer = registeredPlayer; - MediaController.registerPlayer(registeredPlayer); - - // To allow the native android app to override - document.dispatchEvent(new CustomEvent("chromecastloaded", { - detail: { - player: registeredPlayer - } - })); - } - - var fileref = document.createElement('script'); - fileref.setAttribute("type", "text/javascript"); - fileref.onload = initializeChromecast; - fileref.setAttribute("src", "https://www.gstatic.com/cv/js/sender/v1/cast_sender.js"); - document.querySelector('head').appendChild(fileref); - -}); \ No newline at end of file diff --git a/dashboard-ui/scripts/htmlmediarenderer.js b/dashboard-ui/scripts/htmlmediarenderer.js deleted file mode 100644 index 04dcefd39e..0000000000 --- a/dashboard-ui/scripts/htmlmediarenderer.js +++ /dev/null @@ -1,866 +0,0 @@ -define(['browser'], function (browser) { - 'use strict'; - - var supportsTextTracks; - var hlsPlayer; - var requiresSettingStartTimeOnStart; - var subtitleTrackIndexToSetOnPlaying; - var currentTrackList; - var currentPlayOptions; - - function htmlMediaRenderer(options) { - - var mediaElement; - var self = this; - - function onEnded() { - destroyCustomTrack(this); - Events.trigger(self, 'ended'); - } - - function onTimeUpdate() { - - //if (isViblastStarted) { - - // // This is a workaround for viblast not stopping playback at the end - // var time = this.currentTime; - // var duration = this.duration; - - // if (duration) { - // if (time >= (duration - 1)) { - - // //onEnded(); - // return; - // } - // } - //} - - if (options.type == 'video') { - // Get the player position + the transcoding offset - var timeMs = this.currentTime * 1000; - timeMs += ((currentPlayOptions.startTimeTicksOffset || 0) / 10000); - updateSubtitleText(timeMs); - } - Events.trigger(self, 'timeupdate'); - } - - function onVolumeChange() { - Events.trigger(self, 'volumechange'); - } - - function onOneAudioPlaying(e) { - - var elem = e.target; - elem.removeEventListener('playing', onOneAudioPlaying); - document.querySelector('.mediaPlayerAudioContainer').classList.add('hide'); - } - - function onPlaying() { - Events.trigger(self, 'playing'); - } - - function onPlay() { - Events.trigger(self, 'play'); - } - - function onPause() { - Events.trigger(self, 'pause'); - } - - function onClick() { - Events.trigger(self, 'click'); - } - - function onDblClick() { - Events.trigger(self, 'dblclick'); - } - - function onError(e) { - - destroyCustomTrack(this); - - var elem = e.target; - var errorCode = elem.error ? elem.error.code : ''; - console.log('Media element error code: ' + errorCode); - - Events.trigger(self, 'error'); - } - - function onLoadedMetadata(e) { - - var elem = e.target; - - elem.removeEventListener('loadedmetadata', onLoadedMetadata); - - if (!hlsPlayer) { - elem.play(); - } - } - - function requireHlsPlayer(callback) { - require(['hlsjs'], function (hls) { - window.Hls = hls; - callback(); - }); - } - - function onOneVideoPlaying(e) { - - var element = e.target; - element.removeEventListener('playing', onOneVideoPlaying); - - self.setCurrentTrackElement(subtitleTrackIndexToSetOnPlaying); - - var requiresNativeControls = !self.enableCustomVideoControls(); - - if (requiresNativeControls) { - element.setAttribute('controls', 'controls'); - } - - if (requiresSettingStartTimeOnStart) { - - var startPositionInSeekParam = currentPlayOptions.startPositionInSeekParam; - - // Appending #t=xxx to the query string doesn't seem to work with HLS - if (startPositionInSeekParam && currentSrc.indexOf('.m3u8') != -1) { - - var delay = browser.safari ? 2500 : 0; - if (delay) { - setTimeout(function () { - element.currentTime = startPositionInSeekParam; - }, delay); - } else { - element.currentTime = startPositionInSeekParam; - } - } - } - } - - function createAudioElement() { - - var elem = document.querySelector('.mediaPlayerAudio'); - - if (!elem) { - var html = ''; - - var requiresControls = !MediaPlayer.canAutoPlayAudio(); - - if (requiresControls) { - html += '
';; - } else { - html += '
';; - } - - html += '
'; - - document.body.insertAdjacentHTML('beforeend', html); - - elem = document.querySelector('.mediaPlayerAudio'); - } - - elem.addEventListener('playing', onOneAudioPlaying); - elem.addEventListener('timeupdate', onTimeUpdate); - elem.addEventListener('ended', onEnded); - elem.addEventListener('volumechange', onVolumeChange); - elem.addEventListener('error', onError); - elem.addEventListener('pause', onPause); - elem.addEventListener('play', onPlay); - elem.addEventListener('playing', onPlaying); - - return elem; - } - - function enableHlsPlayer(src, item, mediaSource) { - - if (src) { - if (src.indexOf('.m3u8') == -1) { - return false; - } - } - - if (MediaPlayer.canPlayHls()) { - - if (window.MediaSource == null) { - return false; - } - - if (MediaPlayer.canPlayNativeHls()) { - - // simple playback should use the native support - if (mediaSource.RunTimeTicks) { - return false; - } - - //return false; - } - - // hls.js is only in beta. needs more testing. - if (browser.safari && !browser.osx) { - return false; - } - - return true; - } - - return false; - } - - function getCrossOriginValue(mediaSource) { - - return 'anonymous'; - } - - function createVideoElement() { - - var html = ''; - - var requiresNativeControls = !self.enableCustomVideoControls(); - - // Safari often displays the poster under the video and it doesn't look good - var poster = !browser.safari && options.poster ? (' poster="' + options.poster + '"') : ''; - - // playsinline new for iOS 10 - // https://developer.apple.com/library/content/releasenotes/General/WhatsNewInSafari/Articles/Safari_10_0.html - - // Can't autoplay in these browsers so we need to use the full controls - if (requiresNativeControls && AppInfo.isNativeApp && browser.android) { - html += '