diff --git a/dashboard-ui/css/icons.css b/dashboard-ui/css/icons.css index 8867b17585..d61b8ff8e8 100644 --- a/dashboard-ui/css/icons.css +++ b/dashboard-ui/css/icons.css @@ -131,3 +131,18 @@ .ui-nosvg .ui-icon-expand:after { background-image: url("images/icons/expand.png"); } + +.ui-icon-play-circle-o:after { + background-image: url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%20Tiny%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11-tiny.dtd%22%3E%3Csvg%20version%3D%221.1%22%20baseProfile%3D%22tiny%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20width%3D%2216px%22%20height%3D%2216px%22%20viewBox%3D%220%200%20500%20500%22%20xml%3Aspace%3D%22preserve%22%3E%20%3Cpath%20d%3D%22M330.357%20250q0%2010.324-8.929%2015.346l-151.786%2089.286q-4.185%202.511-8.929%202.511-4.464%200-8.929-2.232-8.929-5.301-8.929-15.625v-178.571q0-10.324%208.929-15.625%209.208-5.022%2017.857%200.279l151.786%2089.286q8.929%205.022%208.929%2015.346zM366.071%20250q0-41.294-20.368-76.172t-55.246-55.246-76.172-20.368-76.172%2020.368-55.246%2055.246-20.368%2076.172%2020.368%2076.172%2055.246%2055.246%2076.172%2020.368%2076.172-20.368%2055.246-55.246%2020.368-76.172zM428.571%20250q0%2058.315-28.739%20107.562t-77.985%2077.985-107.562%2028.739-107.562-28.739-77.985-77.985-28.739-107.562%2028.739-107.562%2077.985-77.985%20107.562-28.739%20107.562%2028.739%2077.985%2077.985%2028.739%20107.562z%22%20fill%3D%22%23ffffff%22%20%2F%3E%3C%2Fsvg%3E"); + background-repeat: no-repeat; +} + +/* Fallback */ + +.ui-icon-tablet:after { + background-image: url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%20Tiny%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11-tiny.dtd%22%3E%3Csvg%20version%3D%221.1%22%20baseProfile%3D%22tiny%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20width%3D%2216px%22%20height%3D%2216px%22%20viewBox%3D%220%200%20500%20500%22%20xml%3Aspace%3D%22preserve%22%3E%20%3Cpath%20d%3D%22M178.571%20392.857q0-7.254-5.301-12.556t-12.556-5.301-12.556%205.301-5.301%2012.556%205.301%2012.556%2012.556%205.301%2012.556-5.301%205.301-12.556zM285.714%20348.214v-267.857q0-3.627-2.651-6.278t-6.278-2.651h-232.143q-3.627%200-6.278%202.651t-2.651%206.278v267.857q0%203.627%202.651%206.278t6.278%202.651h232.143q3.627%200%206.278-2.651t2.651-6.278zM321.429%2080.357v303.571q0%2018.415-13.114%2031.529t-31.529%2013.114h-232.143q-18.415%200-31.529-13.114t-13.114-31.529v-303.571q0-18.415%2013.114-31.529t31.529-13.114h232.143q18.415%200%2031.529%2013.114t13.114%2031.529z%22%20fill%3D%22%23ffffff%22%20%2F%3E%3C%2Fsvg%3E"); + background-repeat: no-repeat; + background-position: 6px 3px; +} + +/* Fallback */ diff --git a/dashboard-ui/css/images/favicon.ico b/dashboard-ui/css/images/favicon.ico new file mode 100644 index 0000000000..4acd8f9219 Binary files /dev/null and b/dashboard-ui/css/images/favicon.ico differ diff --git a/dashboard-ui/css/librarybrowser.css b/dashboard-ui/css/librarybrowser.css index 61a020ae19..88f436edda 100644 --- a/dashboard-ui/css/librarybrowser.css +++ b/dashboard-ui/css/librarybrowser.css @@ -1217,6 +1217,68 @@ a.itemTag:hover { } } -.nowPlayingPage .btnCommand { - font-size: 19px; +.nowPlayingPage .btnCommand, .nowPlayingPage .btnPlayStateCommand { + font-size: 30px; +} + +.nowPlayingPageImage img { + height: 300px; +} + +.nowPlayingPage .positionSliderContainer { + width: 350px; +} + +.nowPlayingNavButtonContainer { + width: 400px; +} + +@media all and (max-width: 600px) { + + .nowPlayingPage .btnCommand, .nowPlayingPage .btnPlayStateCommand { + font-size: 26px; + } + + .nowPlayingPageImage img { + height: 200px; + } + + .nowPlayingPage .positionSliderContainer { + width: 300px; + } +} + + +@media all and (max-width: 500px) { + + .nowPlayingPage .btnCommand, .nowPlayingPage .btnPlayStateCommand { + font-size: 22px; + } + + .nowPlayingPageImage img { + height: 200px; + } + + .nowPlayingPage .positionSliderContainer { + width: 300px; + } +} + +@media all and (max-width: 400px) { + + .nowPlayingPage .btnCommand, .nowPlayingPage .btnPlayStateCommand { + font-size: 19px; + } + + .nowPlayingPageImage img { + height: 200px; + } + + .nowPlayingPage .positionSliderContainer { + width: 220px; + } + + .nowPlayingNavButtonContainer { + width: 300px; + } } diff --git a/dashboard-ui/css/mediaplayer-video.css b/dashboard-ui/css/mediaplayer-video.css index 5adb5b0eb2..9775745218 100644 --- a/dashboard-ui/css/mediaplayer-video.css +++ b/dashboard-ui/css/mediaplayer-video.css @@ -102,14 +102,12 @@ max-height: 100%; } -#mediaPlayer .ui-slider-track, .nowPlayingBar .ui-slider-track { +#mediaPlayer .ui-slider-track, .nowPlayingBar .ui-slider-track, .nowPlayingPage .ui-slider-track { border-color: #2ad !important; height: 2px!important; } -#mediaPlayer .ui-slider-handle, .nowPlayingBar .ui-slider-handle { - height: 10px !important; - margin-top: -6px !important; +#mediaPlayer .ui-slider-handle, .nowPlayingBar .ui-slider-handle, .nowPlayingPage .ui-slider-handle { } #videoPlayer.fullscreenVideo #videoControls { diff --git a/dashboard-ui/css/mediaplayer.css b/dashboard-ui/css/mediaplayer.css index 4ac5da63f2..2c6c47525b 100644 --- a/dashboard-ui/css/mediaplayer.css +++ b/dashboard-ui/css/mediaplayer.css @@ -163,4 +163,4 @@ input[type="range"]::-ms-fill-upper { .mediaPlayerAudioContainerInner { padding: 1em; background: #222; -} +} \ No newline at end of file diff --git a/dashboard-ui/nowplaying.html b/dashboard-ui/nowplaying.html index bbb33a9aae..a18caf80fb 100644 --- a/dashboard-ui/nowplaying.html +++ b/dashboard-ui/nowplaying.html @@ -6,36 +6,52 @@
-
+
- +

+
+
+
+
+
+ +
+
+
+
- - - - - + + + + +
- - - - + + + + +
+
+ + + +
-
+
+
diff --git a/dashboard-ui/scripts/librarymenu.js b/dashboard-ui/scripts/librarymenu.js index 137888046e..3efbfae9d5 100644 --- a/dashboard-ui/scripts/librarymenu.js +++ b/dashboard-ui/scripts/librarymenu.js @@ -16,7 +16,7 @@ html += ''; - html += ''; + html += 'Remote Control'; if (user.Configuration.IsAdministrator) { html += 'Metadata Manager'; diff --git a/dashboard-ui/scripts/mediaplayer.js b/dashboard-ui/scripts/mediaplayer.js index 1c3be5bdf3..9c50994c4b 100644 --- a/dashboard-ui/scripts/mediaplayer.js +++ b/dashboard-ui/scripts/mediaplayer.js @@ -107,26 +107,24 @@ var currentSrc = element.currentSrc; + var transcodingExtension = self.getTranscodingExtension(); + var isStatic; + if (currentItem.MediaType == "Video") { + if (params.AudioStreamIndex != null) { currentSrc = replaceQueryString(currentSrc, 'AudioStreamIndex', params.AudioStreamIndex); } if (params.SubtitleStreamIndex != null) { currentSrc = replaceQueryString(currentSrc, 'SubtitleStreamIndex', (params.SubtitleStreamIndex == -1 ? '' : params.SubtitleStreamIndex)); } - } - var maxWidth = params.MaxWidth || getParameterByName('MaxWidth', currentSrc); - var audioStreamIndex = params.AudioStreamIndex == null ? getParameterByName('AudioStreamIndex', currentSrc) : params.AudioStreamIndex; - var subtitleStreamIndex = params.SubtitleStreamIndex == null ? getParameterByName('SubtitleStreamIndex', currentSrc) : params.SubtitleStreamIndex; - var videoBitrate = parseInt(getParameterByName('VideoBitrate', currentSrc) || '0'); - var audioBitrate = parseInt(getParameterByName('AudioBitrate', currentSrc) || '0'); - var bitrate = params.Bitrate || (videoBitrate + audioBitrate); - - var transcodingExtension = self.getTranscodingExtension(); - - var isStatic; - if (currentItem.MediaType == "Video") { + var maxWidth = params.MaxWidth || getParameterByName('MaxWidth', currentSrc); + var audioStreamIndex = params.AudioStreamIndex == null ? getParameterByName('AudioStreamIndex', currentSrc) : params.AudioStreamIndex; + var subtitleStreamIndex = params.SubtitleStreamIndex == null ? getParameterByName('SubtitleStreamIndex', currentSrc) : params.SubtitleStreamIndex; + var videoBitrate = parseInt(getParameterByName('VideoBitrate', currentSrc) || '0'); + var audioBitrate = parseInt(getParameterByName('AudioBitrate', currentSrc) || '0'); + var bitrate = params.Bitrate || (videoBitrate + audioBitrate); var finalParams = self.getFinalVideoParams(currentMediaSource, maxWidth, bitrate, audioStreamIndex, subtitleStreamIndex, transcodingExtension); @@ -1176,7 +1174,9 @@ IsPaused: currentMediaElement.paused, IsMuted: currentMediaElement.volume == 0, VolumeLevel: currentMediaElement.volume * 100, - PositionTicks: self.getCurrentTicks() + PositionTicks: self.getCurrentTicks(), + + CanSeek: currentMediaSource.RunTimeTicks && currentMediaSource.RunTimeTicks > 0 }); } @@ -1186,7 +1186,7 @@ clearTimeout(currentProgressInterval); currentProgressInterval = null; } - }; + } function canPlayWebm() { diff --git a/dashboard-ui/scripts/nowplayingbar.js b/dashboard-ui/scripts/nowplayingbar.js index b7d00a9eba..ede46f7518 100644 --- a/dashboard-ui/scripts/nowplayingbar.js +++ b/dashboard-ui/scripts/nowplayingbar.js @@ -163,7 +163,7 @@ function updatePlayerState(state) { - if (state.NowPlayingItem) { + if (state.NowPlayingItem && !$($.mobile.activePage).hasClass('nowPlayingPage')) { showNowPlayingBar(); } else { hideNowPlayingBar(); @@ -231,16 +231,22 @@ var nowPlayingItem = state.NowPlayingItem || {}; if (!isPositionSliderActive) { - if (playState.CanSeek) { + if (nowPlayingItem && nowPlayingItem.RunTimeTicks) { var pct = playState.PositionTicks / nowPlayingItem.RunTimeTicks; pct *= 100; - positionSlider.val(pct).slider("enable"); + positionSlider.val(pct); } else { - positionSlider.val(0).slider("disable"); + positionSlider.val(0); + } + + if (playState.CanSeek) { + positionSlider.slider("enable"); + } else { + positionSlider.slider("disable"); } positionSlider.slider('refresh'); diff --git a/dashboard-ui/scripts/nowplayingpage.js b/dashboard-ui/scripts/nowplayingpage.js index f79f1da4b0..014fd69190 100644 --- a/dashboard-ui/scripts/nowplayingpage.js +++ b/dashboard-ui/scripts/nowplayingpage.js @@ -2,6 +2,7 @@ var currentPlayer; var lastPlayerState; + var isPositionSliderActive; function bindEvents(page) { @@ -44,6 +45,23 @@ currentPlayer.previousTrack(); }); + + $('.positionSlider', page).on('slidestart', function () { + + isPositionSliderActive = true; + + }).on('slidestop', function () { + + isPositionSliderActive = false; + + if (currentPlayer && lastPlayerState) { + + var newPercent = parseFloat(this.value); + var newPositionTicks = (newPercent / 100) * lastPlayerState.NowPlayingItem.RunTimeTicks; + + currentPlayer.seek(Math.floor(newPositionTicks)); + } + }); } function onPlaybackStart(e, state) { @@ -62,6 +80,8 @@ player.endPlayerUpdates(); onStateChanged.call(player, e, state); + + $('.itemName', page).html(''); } function onStateChanged(e, state) { @@ -113,6 +133,96 @@ hideButton(btnPlay); } + if (!isPositionSliderActive) { + + var positionSlider = $('.positionSlider', page); + + if (item && item.RunTimeTicks) { + + var pct = playState.PositionTicks / item.RunTimeTicks; + pct *= 100; + + positionSlider.val(pct); + + } else { + + positionSlider.val(0); + } + + if (playState.CanSeek) { + positionSlider.slider("enable"); + } else { + positionSlider.slider("disable"); + } + + positionSlider.slider('refresh'); + } + + if (playState.PositionTicks == null) { + $('.positionTime', page).html('--:--'); + } else { + $('.positionTime', page).html(Dashboard.getDisplayTime(playState.PositionTicks)); + } + + if (item && item.RunTimeTicks != null) { + $('.runtime', page).html(Dashboard.getDisplayTime(item.RunTimeTicks)); + } else { + $('.runtime', page).html('--:--'); + } + + if (item && item.MediaType == 'Video') { + $('.videoButton', page).css('visibility', 'visible'); + } else { + $('.videoButton', page).css('visibility', 'hidden'); + } + + updateNowPlayingInfo(page, state); + } + + var currentImgUrl; + function updateNowPlayingInfo(page, state) { + + var item = state.NowPlayingItem; + + $('.itemName', page).html(item ? MediaPlayer.getNowPlayingNameHtml(state) : ''); + + var url; + + if (!item) { + } + else if (item.PrimaryImageTag) { + + url = ApiClient.getImageUrl(item.PrimaryImageItemId, { + type: "Primary", + height: 600, + tag: item.PrimaryImageTag + }); + } + else if (item.BackdropImageTag) { + + url = ApiClient.getImageUrl(item.BackdropItemId, { + type: "Backdrop", + height: 600, + tag: item.BackdropImageTag, + index: 0 + }); + + } else if (item.ThumbImageTag) { + + url = ApiClient.getImageUrl(item.ThumbImageItemId, { + type: "Thumb", + height: 600, + tag: item.ThumbImageTag + }); + } + + if (url == currentImgUrl) { + return; + } + + currentImgUrl = url; + + $('.nowPlayingPageImage', page).html(url ? '' : ''); } function updateSupportedCommands(page, commands) {