diff --git a/dashboard-ui/css/site.css b/dashboard-ui/css/site.css index df5df8bf90..49a1486b6d 100644 --- a/dashboard-ui/css/site.css +++ b/dashboard-ui/css/site.css @@ -27,28 +27,31 @@ } @font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 100; - src: local('Roboto Thin'), local('Roboto-Thin'), url(fonts/RobotoThin.woff) format('woff'); + font-family: 'Roboto'; + font-style: normal; + font-weight: 100; + src: local('Roboto Thin'), local('Roboto-Thin'), url(fonts/RobotoThin.woff) format('woff'); } + @font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 300; - src: local('Roboto Light'), local('Roboto-Light'), url(fonts/RobotoLight.woff) format('woff'); + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + src: local('Roboto Light'), local('Roboto-Light'), url(fonts/RobotoLight.woff) format('woff'); } + @font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 400; - src: local('Roboto Regular'), local('Roboto-Regular'), url(fonts/RobotoRegular.woff) format('woff'); + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + src: local('Roboto Regular'), local('Roboto-Regular'), url(fonts/RobotoRegular.woff) format('woff'); } + @font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 500; - src: local('Roboto Medium'), local('Roboto-Medium'), url(fonts/RobotoMedium.woff) format('woff'); + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + src: local('Roboto Medium'), local('Roboto-Medium'), url(fonts/RobotoMedium.woff) format('woff'); } * { @@ -941,7 +944,7 @@ progress { .sessionUserInfo { position: absolute; right: 0; - bottom: 7px; + bottom: 11px; padding: .5em; text-align: right; } @@ -953,7 +956,7 @@ progress { .sessionNowPlayingInfo { position: absolute; left: 0; - bottom: 7px; + bottom: 11px; padding: .5em; max-width: 150px; overflow: hidden; @@ -966,7 +969,7 @@ progress { margin-right: 5px; } -.activeSession progress { +.activeSession .playbackProgress { position: absolute; right: 0; bottom: 0; @@ -1005,7 +1008,14 @@ progress { color: #fff; position: absolute; right: 10px; - bottom: 15px; + bottom: 19px; +} + +.sessionTranscodingFramerate { + position: absolute; + left: 10px; + bottom: 19px; + color: #fff; } .sessionNowPlayingStreamInfo { @@ -1015,6 +1025,42 @@ progress { top: 10px; } +.activeSession .transcodingProgress { + right: 0; + bottom: 0; + left: 0; + height: 5px; + width: 100%; + opacity: .9; + z-index: 1000; + position: absolute; +} + +.transcodingSession .playbackProgress { + bottom: 5px; +} + +/* Firefox */ +.transcodingProgress::-moz-progress-bar { + border-radius: 5px; + background-image: -moz-linear-gradient( center bottom, rgb(221, 73, 25) 37%, rgb(221, 73, 25) 69% )!important; +} + +/* Chrome */ +.transcodingProgress::-webkit-progress-value { + border-radius: 5px; + background-image: -webkit-gradient( linear, left bottom, left top, color-stop(0, rgb(221, 73, 25)), color-stop(1, rgb(221, 73, 25)) )!important; + background-image: -webkit-linear-gradient( center bottom, rgb(221, 73, 25) 37%, rgb(221, 73, 25) 69% )!important; +} + +/* Polyfill */ +.transcodingProgress[aria-valuenow]:before { + border-radius: 5px; + background-image: -moz-linear-gradient( center bottom, rgb(221, 73, 25) 37%, rgb(221, 73, 25) 69% )!important; + background-image: -ms-linear-gradient( center bottom, rgb(221, 73, 25) 37%, rgb(221, 73, 25) 69% )!important; + background-image: -o-linear-gradient( center bottom, rgb(221, 73, 25) 37%, rgb(221, 73, 25) 69% )!important; +} + @media all and (max-width: 1000px) { .activeSession { diff --git a/dashboard-ui/scripts/dashboardpage.js b/dashboard-ui/scripts/dashboardpage.js index 8ebe59a703..5640170bfb 100644 --- a/dashboard-ui/scripts/dashboardpage.js +++ b/dashboard-ui/scripts/dashboardpage.js @@ -132,7 +132,7 @@ $(ApiClient).off("websocketmessage", DashboardPage.onWebSocketMessage).off("websocketopen", DashboardPage.onWebSocketConnectionChange).off("websocketerror", DashboardPage.onWebSocketConnectionChange).off("websocketclose", DashboardPage.onWebSocketConnectionChange); DashboardPage.stopInterval(); - + if (DashboardPage.sessionUpdateTimer) { clearInterval(DashboardPage.sessionUpdateTimer); } @@ -215,21 +215,25 @@ for (var i = 0, length = sessions.length; i < length; i++) { - var connection = sessions[i]; + var session = sessions[i]; - var rowId = 'session' + connection.Id; + var rowId = 'session' + session.Id; var elem = $('#' + rowId, page); if (elem.length) { - DashboardPage.updateSession(elem, connection); + DashboardPage.updateSession(elem, session); continue; } - var nowPlayingItem = connection.NowPlayingItem; + var nowPlayingItem = session.NowPlayingItem; var className = nowPlayingItem ? 'playingSession activeSession' : 'activeSession'; + if (session.TranscodingInfo && session.TranscodingInfo.CompletionPercentage) { + className += ' transcodingSession'; + } + html += '
'; html += '
'; - html += '
' + DashboardPage.getAppSecondaryText(connection) + '
'; + html += '
' + session.DeviceName + '
'; + html += '
' + DashboardPage.getAppSecondaryText(session) + '
'; html += '
'; html += '
'; html += '
'; - var userImage = DashboardPage.getUserImage(connection); + var userImage = DashboardPage.getUserImage(session); if (userImage) { html += '
'; html += ''; @@ -271,12 +275,12 @@ html += '
'; html += '
'; - html += DashboardPage.getUsersHtml(connection); + html += DashboardPage.getUsersHtml(session); html += '
'; html += '
'; - var nowPlayingName = DashboardPage.getNowPlayingName(connection); + var nowPlayingName = DashboardPage.getNowPlayingName(session); html += '
'; html += nowPlayingName.html; @@ -284,20 +288,35 @@ if (nowPlayingItem && nowPlayingItem.RunTimeTicks) { - var position = connection.PlayState.PositionTicks || 0; + var position = session.PlayState.PositionTicks || 0; var value = (100 * position) / nowPlayingItem.RunTimeTicks; - html += ''; + html += ''; } else { - html += ''; + html += ''; + } + + if (session.TranscodingInfo && session.TranscodingInfo.CompletionPercentage) { + + html += ''; + } else { + html += ''; } html += '
'; html += '
'; - html += '
' + DashboardPage.getSessionNowPlayingStreamInfo(connection) + '
'; - html += '
' + DashboardPage.getSessionNowPlayingTime(connection) + '
'; + html += '
' + DashboardPage.getSessionNowPlayingStreamInfo(session) + '
'; + html += '
' + DashboardPage.getSessionNowPlayingTime(session) + '
'; + + if (session.TranscodingInfo && session.TranscodingInfo.Framerate) { + + html += '
' + session.TranscodingInfo.Framerate + ' fps
'; + } else { + html += '
'; + } + html += '
'; html += ''; @@ -327,6 +346,40 @@ html += ''; + if (session.TranscodingInfo) { + + html += '
'; + + var line = []; + + if (session.TranscodingInfo.Container) { + + line.push(session.TranscodingInfo.Container); + } + if (session.TranscodingInfo.Bitrate) { + + if (session.TranscodingInfo.Bitrate > 1000000) { + line.push((session.TranscodingInfo.Bitrate / 1000000).toFixed(1) + ' Mbps'); + } else { + line.push(Math.floor(session.TranscodingInfo.Bitrate / 1000) + ' kbps'); + } + } + if (line.length) { + + html += '
' + line.join(' ') + '
'; + } + + if (session.TranscodingInfo.VideoCodec) { + + html += '
Video: ' + session.TranscodingInfo.VideoCodec + '
'; + } + if (session.TranscodingInfo.AudioCodec && session.TranscodingInfo.AudioCodec != session.TranscodingInfo.Container) { + + html += '
Audio: ' + session.TranscodingInfo.AudioCodec + '
'; + } + + } + return html; }, @@ -475,6 +528,8 @@ $('.sessionAppSecondaryText', row).html(DashboardPage.getAppSecondaryText(session)); + $('.sessionTranscodingFramerate', row).html((session.TranscodingInfo && session.TranscodingInfo.Framerate) ? session.TranscodingInfo.Framerate + ' fps' : ''); + var nowPlayingName = DashboardPage.getNowPlayingName(session); var nowPlayingInfoElem = $('.sessionNowPlayingInfo', row); @@ -488,9 +543,18 @@ var position = session.PlayState.PositionTicks || 0; var value = (100 * position) / nowPlayingItem.RunTimeTicks; - $('progress', row).show().val(value); + $('.playbackProgress', row).show().val(value); } else { - $('progress', row).hide(); + $('.playbackProgress', row).hide(); + } + + if (session.TranscodingInfo && session.TranscodingInfo.CompletionPercentage) { + + row.addClass('transcodingSession'); + $('.transcodingProgress', row).show().val(session.TranscodingInfo.CompletionPercentage); + } else { + $('.transcodingProgress', row).hide(); + row.removeClass('transcodingSession'); } var imgUrl = DashboardPage.getNowPlayingImageUrl(nowPlayingItem) || ''; diff --git a/dashboard-ui/scripts/librarymenu.js b/dashboard-ui/scripts/librarymenu.js index 8b0a216449..55d65c8754 100644 --- a/dashboard-ui/scripts/librarymenu.js +++ b/dashboard-ui/scripts/librarymenu.js @@ -364,7 +364,7 @@ $.fn.createHoverTouch = function () { timerId = setTimeout(function () { $(elem).trigger('hovertouch'); - }, 200); + }, 250); } function stopTimer(elem) { diff --git a/dashboard-ui/scripts/mediaplayer.js b/dashboard-ui/scripts/mediaplayer.js index 32cf50d754..c8d0621876 100644 --- a/dashboard-ui/scripts/mediaplayer.js +++ b/dashboard-ui/scripts/mediaplayer.js @@ -1190,7 +1190,8 @@ audioChannels: 2, audioBitrate: 128000, StartTimeTicks: startPositionTicks, - mediaSourceId: mediaSource.Id + mediaSourceId: mediaSource.Id, + deviceId: ApiClient.deviceId() }; var sourceContainer = (mediaSource.Container || '').toLowerCase(); diff --git a/dashboard-ui/scripts/movies.js b/dashboard-ui/scripts/movies.js index 4f4ae3fec4..cca276f614 100644 --- a/dashboard-ui/scripts/movies.js +++ b/dashboard-ui/scripts/movies.js @@ -7,7 +7,7 @@ SortBy: "SortName", SortOrder: "Ascending", - IncludeItemTypes: "Movie,BoxSet", + IncludeItemTypes: "Movie", Recursive: true, Fields: "PrimaryImageAspectRatio", StartIndex: 0 diff --git a/dashboard-ui/scripts/nowplayingpage.js b/dashboard-ui/scripts/nowplayingpage.js index d93f7274e3..cc459d515a 100644 --- a/dashboard-ui/scripts/nowplayingpage.js +++ b/dashboard-ui/scripts/nowplayingpage.js @@ -419,7 +419,7 @@ $('.btnAudioTracks', page).buttonEnabled(hasStreams(item, 'Audio') && supportedCommands.indexOf('SetAudioStreamIndex') != -1); $('.btnSubtitles', page).buttonEnabled(hasStreams(item, 'Subtitle') && supportedCommands.indexOf('SetSubtitleStreamIndex') != -1); - if (item && item.Chapters && item.Chapters.length) { + if (item && item.Chapters && item.Chapters.length && playState.CanSeek) { $('.btnChapters', page).buttonEnabled(true); } else {