diff --git a/dashboard-ui/css/librarybrowser.css b/dashboard-ui/css/librarybrowser.css index 56a8ace8f3..e210b0f657 100644 --- a/dashboard-ui/css/librarybrowser.css +++ b/dashboard-ui/css/librarybrowser.css @@ -859,7 +859,7 @@ a.itemTag:hover { } .mediaInfoStream { - margin: 1em 2em 1em 0; + margin: 1em 3em 1em 0; display: inline-block; color: #bbb; vertical-align: top; @@ -867,6 +867,7 @@ a.itemTag:hover { .mediaInfoStreamType { font-size: 16px; + display: block; color: #fff; } @@ -928,7 +929,7 @@ a.itemTag:hover { background-color: transparent !important; } -.alternateVersionIndicator { +.mediaVersionIndicator { display: block; position: absolute; top: 5px; diff --git a/dashboard-ui/css/posteritem.css b/dashboard-ui/css/posteritem.css index 741096a63c..9861a98a7b 100644 --- a/dashboard-ui/css/posteritem.css +++ b/dashboard-ui/css/posteritem.css @@ -320,61 +320,4 @@ .backdropPosterItem .posterItemImage { height: 167.625px; } -} -/********************/ -.ribbon-wrapper { - width: 50px; - height: 50px; - overflow: hidden; - position: absolute; - top: 0px; - left: 0px; - z-index: 999; -} - -.ribbon { - font: bold 11px Sans-Serif; - color: #333; - text-align: center; - color: #eee; - text-shadow: rgba(51, 51, 51, 0.5) 0px 1px 0px; - -webkit-transform: rotate(-45deg); - -moz-transform: rotate(-45deg); - -ms-transform: rotate(-45deg); - -o-transform: rotate(-45deg); - position: relative; - padding: 2px 0; - right: 15px; - top: 5px; - width: 60px; - -webkit-box-shadow: 0px 0px 3px rgba(0, 0, 0, 0.3); - -moz-box-shadow: 0px 0px 3px rgba(0, 0, 0, 0.3); - box-shadow: 0px 0px 3px rgba(0, 0, 0, 0.3); -} - -.ribbon-3d { - background-color: #3344ff; - background-image: -webkit-gradient(linear, left top, left bottom, from(#BFDC7A), to(#ff0033)); - background-image: -webkit-linear-gradient(top, #3344ff, #ff0033); - background-image: -moz-linear-gradient(top, #3344ff, #ff0033); - background-image: -ms-linear-gradient(top, #3344ff, #ff0033); - background-image: -o-linear-gradient(top, #3344ff, #ff0033); -} - -.ribbon-blue { - background-color: #1199ff; - background-image: -webkit-gradient(linear, left top, left bottom, from(#1199ff), to(#3333ff)); - background-image: -webkit-linear-gradient(top, #1199ff, #3333ff); - background-image: -moz-linear-gradient(top, #1199ff, #3333ff); - background-image: -ms-linear-gradient(top, #1199ff, #3333ff); - background-image: -o-linear-gradient(top, #1199ff, #3333ff); -} - -.ribbon-red { - background-color: #ff3333; - background-image: -webkit-gradient(linear, left top, left bottom, from(#ff3333), to(#992233)); - background-image: -webkit-linear-gradient(top, #ff3333, #992233); - background-image: -moz-linear-gradient(top, #ff3333, #992233); - background-image: -ms-linear-gradient(top, #ff3333, #992233); - background-image: -o-linear-gradient(top, #ff3333, #992233); -} +} \ No newline at end of file diff --git a/dashboard-ui/episodes.html b/dashboard-ui/episodes.html index 78b28e3428..8736aa4bb9 100644 --- a/dashboard-ui/episodes.html +++ b/dashboard-ui/episodes.html @@ -24,7 +24,7 @@
- +
diff --git a/dashboard-ui/itemdetails.html b/dashboard-ui/itemdetails.html index 95d24dcbd3..8ebed78750 100644 --- a/dashboard-ui/itemdetails.html +++ b/dashboard-ui/itemdetails.html @@ -152,7 +152,7 @@
-
+

@@ -163,15 +163,12 @@
+ +
+ +
-
-
- Media Versions - -
-
-

diff --git a/dashboard-ui/movies.html b/dashboard-ui/movies.html index 2f567b0d72..8603e4b8f9 100644 --- a/dashboard-ui/movies.html +++ b/dashboard-ui/movies.html @@ -32,7 +32,7 @@
- +
diff --git a/dashboard-ui/scripts/itemdetailpage.js b/dashboard-ui/scripts/itemdetailpage.js index 1caa917e6a..6bf282d884 100644 --- a/dashboard-ui/scripts/itemdetailpage.js +++ b/dashboard-ui/scripts/itemdetailpage.js @@ -73,10 +73,10 @@ $('#btnPlayExternalTrailer', page).attr('href', '#'); } - if (user.Configuration.IsAdministrator) { - $('.btnSplitVersions', page).show(); + if (user.Configuration.IsAdministrator && item.MediaVersions && item.MediaVersions.length > 1) { + $('.splitVersionContainer', page).show(); } else { - $('.btnSplitVersions', page).hide(); + $('.splitVersionContainer', page).hide(); } }); @@ -210,10 +210,17 @@ $('#childrenCollapsible', page).addClass('hide'); } - if (item.MediaStreams && item.MediaStreams.length) { - renderMediaInfo(page, item); + if (item.MediaVersions && item.MediaVersions.length) { + renderMediaVersions(page, item); } - if (!item.Chapters || !item.Chapters.length) { + + var primaryVersion = (item.MediaVersions || []).filter(function (v) { + return v.IsPrimaryVersion; + + })[0]; + var chapters = primaryVersion ? (primaryVersion.Chapters || []) : []; + + if (!chapters.length) { $('#scenesCollapsible', page).hide(); } else { $('#scenesCollapsible', page).show(); @@ -342,7 +349,7 @@ tabsHtml += ''; tabsHtml += ''; } - + if (item.MediaType == "Audio" || item.MediaType == "Video") { tabsHtml += ''; tabsHtml += ''; @@ -1001,7 +1008,6 @@ useAverageAspectRatio: true, showTitle: true, centerText: true, - formatIndicators: true, linkItem: false, showProgress: false, showUnplayedIndicator: false @@ -1017,7 +1023,11 @@ function renderScenes(page, item, user, limit) { var html = ''; - var chapters = item.Chapters || []; + var primaryVersion = (item.MediaVersions || []).filter(function (v) { + return v.IsPrimaryVersion; + + })[0]; + var chapters = primaryVersion ? (primaryVersion.Chapters || []) : []; for (var i = 0, length = chapters.length; i < length; i++) { @@ -1067,13 +1077,32 @@ $('#scenesContent', page).html(html).trigger('create'); } - function renderMediaInfo(page, item) { + function renderMediaVersions(page, item) { + + var html = item.MediaVersions.map(function (v) { + + return getMediaVersionHtml(item, v); + + }).join('
'); + + if (item.MediaVersions.length > 1) { + html = '
' + html; + } + + $('#mediaInfoContent', page).html(html).trigger('create'); + } + + function getMediaVersionHtml(item, version) { var html = ''; - for (var i = 0, length = item.MediaStreams.length; i < length; i++) { + if (version.Name && item.MediaVersions.length > 1) { + html += '' + version.Name + '
'; + } - var stream = item.MediaStreams[i]; + for (var i = 0, length = version.MediaStreams.length; i < length; i++) { + + var stream = version.MediaStreams[i]; if (stream.Type == "Data") { continue; @@ -1155,7 +1184,11 @@ html += '
'; } - $('#mediaInfoContent', page).html(html).trigger('create'); + if (version.Path) { + html += '
Path' + version.Path + ''; + } + + return html; } function createAttribute(label, value) { diff --git a/dashboard-ui/scripts/librarybrowser.js b/dashboard-ui/scripts/librarybrowser.js index 39f95e7550..722a954baf 100644 --- a/dashboard-ui/scripts/librarybrowser.js +++ b/dashboard-ui/scripts/librarybrowser.js @@ -665,33 +665,11 @@ cssClass += ' ' + options.shape + 'PosterItem'; + var mediaVersionCount = item.MediaVersionCount || 1; + var href = options.linkItem === false ? '#' : LibraryBrowser.getHref(item, options.context); - html += ''; - - // Ribbon - if (item.MediaType == "Video" && options.formatIndicators) { - // This would be much better if specified in the json payload - // Another nice thing to have in the payload would be 720 vs 1080 - // Then, rather than "HD" it could display the specific HD format - // "HD" doesn't do much good if you have the 720p and 1080p version - var format = "SD"; - var ribbonColor = "ribbon-red"; - if (item.IsHD) { - format = "HD"; - ribbonColor = "ribbon-blue"; - } - if (item.Video3DFormat) { - format = "3D"; - ribbonColor = "ribbon-3d"; - } - - html += '
'; - html += '
'; - html += format; - html += '
'; - html += '
'; - } + html += '
'; var style = ""; @@ -722,8 +700,8 @@ html += LibraryBrowser.getPlayedIndicatorHtml(item); } - if (item.AlternateVersionCount) { - html += '
' + (item.AlternateVersionCount + 1) + '
'; + if (mediaVersionCount > 1) { + html += '
' + mediaVersionCount + '
'; } if (item.IsUnidentified) { html += '
'; diff --git a/dashboard-ui/scripts/librarylist.js b/dashboard-ui/scripts/librarylist.js index 4bc3b1ed99..14d49af957 100644 --- a/dashboard-ui/scripts/librarylist.js +++ b/dashboard-ui/scripts/librarylist.js @@ -208,7 +208,9 @@ items.push({ type: 'link', text: 'Images', url: 'edititemimages.html?id=' + id }); - if (elem.getAttribute('data-alternateversioncount') != '0') { + var versionCount = parseInt(elem.getAttribute('data-mediaversioncount') || '0'); + + if (versionCount > 1) { items.push({ type: 'divider' }); items.push({ type: 'header', text: 'Manage' }); diff --git a/dashboard-ui/scripts/libraryreport.js b/dashboard-ui/scripts/libraryreport.js index 64135d5117..bc894428a6 100644 --- a/dashboard-ui/scripts/libraryreport.js +++ b/dashboard-ui/scripts/libraryreport.js @@ -8,12 +8,12 @@ SortBy: defaultSortBy, SortOrder: "Ascending", Recursive: true, - Fields: "MediaStreams,DateCreated,Settings,Studios", + Fields: "MediaVersions,DateCreated,Settings,Studios", StartIndex: 0, IncludeItemTypes: "Movie", IsMissing: false, IsVirtualUnaired: false, - Limit: 300, + Limit: 200, CollapseBoxSetItems: false }; @@ -214,6 +214,12 @@ var stream; + var primaryVersion = (item.MediaVersions || []).filter(function(v) { + return v.IsPrimaryVersion; + })[0] || {}; + + var mediaStreams = primaryVersion.MediaStreams || []; + switch (cell.type || cell.name) { case 'Album Artist': @@ -258,7 +264,7 @@ } case 'Audio': { - stream = (item.MediaStreams || []).filter(function (s) { + stream = mediaStreams.filter(function (s) { return s.Type == 'Audio'; @@ -273,7 +279,7 @@ } case 'Video': { - stream = (item.MediaStreams || []).filter(function (s) { + stream = mediaStreams.filter(function (s) { return s.Type == 'Video'; @@ -286,7 +292,7 @@ } case 'Resolution': { - stream = (item.MediaStreams || []).filter(function (s) { + stream = mediaStreams.filter(function (s) { return s.Type == 'Video'; @@ -299,7 +305,7 @@ } case 'Embedded Image': { - if ((item.MediaStreams || []).filter(function (s) { + if (mediaStreams.filter(function (s) { return s.Type == 'Video'; @@ -310,7 +316,7 @@ } case 'Subtitles': { - var hasSubtitles = (item.MediaStreams || []).filter(function (s) { + var hasSubtitles = mediaStreams.filter(function (s) { return s.Type == 'Subtitle'; diff --git a/dashboard-ui/scripts/mediaplayer-video.js b/dashboard-ui/scripts/mediaplayer-video.js index 3b4be615e4..712df553ce 100644 --- a/dashboard-ui/scripts/mediaplayer-video.js +++ b/dashboard-ui/scripts/mediaplayer-video.js @@ -1,5 +1,5 @@ (function () { - videoPlayer = function(mediaPlayer, item, startPosition, user) { + videoPlayer = function (mediaPlayer, item, mediaVersion, startPosition, user) { if (mediaPlayer == null) { throw new Error("mediaPlayer cannot be null"); } @@ -15,16 +15,16 @@ var self = mediaPlayer; var currentItem; + var currentMediaVersion; var timeout; var video; - var culturesPromise; var initialVolume; var fullscreenExited = false; var idleState = true; var remoteFullscreen = false; self.initVideoPlayer = function () { - video = playVideo(item, startPosition, user); + video = playVideo(item, mediaVersion, startPosition, user); return video; }; @@ -72,7 +72,7 @@ $(".ui-loader").hide(); }; - self.exitFullScreen = function() { + self.exitFullScreen = function () { if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.mozExitFullScreen) { @@ -86,7 +86,7 @@ fullscreenExited = true; }; - self.isFullScreen = function() { + self.isFullScreen = function () { return document.fullscreen || document.mozFullScreen || document.webkitIsFullScreen || document.msFullscreenElement ? true : false; }; @@ -96,15 +96,8 @@ if (!flyout.is(':visible')) { - culturesPromise = culturesPromise || ApiClient.getCultures(); - - $("html").css("cursor", "progress"); - - culturesPromise.done(function (cultures) { - $("html").css("cursor", "default"); - flyout.html(getSubtitleTracksHtml(currentItem, cultures)).trigger('create').scrollTop(0); - toggleFlyout(flyout, '#video-subtitleButton'); - }); + flyout.html(getSubtitleTracksHtml()).trigger('create').scrollTop(0); + toggleFlyout(flyout, '#video-subtitleButton'); } else { toggleFlyout(flyout, '#video-subtitleButton'); @@ -116,7 +109,7 @@ var flyout = $('#video-qualityFlyout'); if (!flyout.is(':visible')) { - flyout.html(getQualityFlyoutHtml(currentItem)).scrollTop(0); + flyout.html(getQualityFlyoutHtml()).scrollTop(0); } toggleFlyout(flyout, '#video-qualityButton'); @@ -127,7 +120,7 @@ var flyout = $('#video-chaptersFlyout'); if (!flyout.is(':visible')) { - flyout.html(getChaptersFlyoutHtml(currentItem)).scrollTop(0); + flyout.html(getChaptersFlyoutHtml()).scrollTop(0); } toggleFlyout(flyout, '#video-chaptersButton'); @@ -139,15 +132,8 @@ if (!flyout.is(':visible')) { - culturesPromise = culturesPromise || ApiClient.getCultures(); - - $("html").css("cursor", "progress"); - - culturesPromise.done(function (cultures) { - $("html").css("cursor", "default"); - flyout.html(getAudioTracksHtml(currentItem, cultures)).trigger('create').scrollTop(0); - toggleFlyout(flyout, '#video-audioTracksButton'); - }); + flyout.html(getAudioTracksHtml()).trigger('create').scrollTop(0); + toggleFlyout(flyout, '#video-audioTracksButton'); } else { toggleFlyout(flyout, '#video-audioTracksButton'); } @@ -327,13 +313,13 @@ $(document.body).off("mousedown.hidesearchhints"); }; - function getChaptersFlyoutHtml(item) { + function getChaptersFlyoutHtml() { var html = ''; var currentTicks = self.getCurrentTicks(); - var chapters = item.Chapters || []; + var chapters = currentMediaVersion.Chapters || []; for (var i = 0, length = chapters.length; i < length; i++) { @@ -358,7 +344,7 @@ if (chapter.ImageTag) { - imgUrl = ApiClient.getImageUrl(item.Id, { + imgUrl = ApiClient.getImageUrl(currentMediaVersion.ItemId, { maxwidth: 200, tag: chapter.ImageTag, type: "Chapter", @@ -386,10 +372,10 @@ return html; }; - function getAudioTracksHtml(item, cultures) { - - var streams = item.MediaStreams.filter(function (i) { - return i.Type == "Audio"; + function getAudioTracksHtml() { + + var streams = currentMediaVersion.MediaStreams.filter(function (currentStream) { + return currentStream.Type == "Audio"; }); var currentIndex = getParameterByName('AudioStreamIndex', video.currentSrc); @@ -410,20 +396,7 @@ html += '
'; - var language = null; - - if (stream.Language && stream.Language != "und") { - - var culture = cultures.filter(function (current) { - return current.ThreeLetterISOLanguageName.toLowerCase() == stream.Language.toLowerCase(); - }); - - if (culture.length) { - language = culture[0].DisplayName; - } - } - - html += '
' + (language || stream.Language || 'Unknown language') + '
'; + html += '
' + (stream.Language || 'Unknown language') + '
'; var options = []; @@ -469,10 +442,10 @@ return html; }; - function getSubtitleTracksHtml(item, cultures) { + function getSubtitleTracksHtml() { - var streams = item.MediaStreams.filter(function (i) { - return i.Type == "Subtitle"; + var streams = currentMediaVersion.MediaStreams.filter(function (currentStream) { + return currentStream.Type == "Subtitle"; }); var currentIndex = getParameterByName('SubtitleStreamIndex', video.currentSrc) || -1; @@ -502,25 +475,13 @@ html += '
'; - var language = null; var options = []; if (stream.Language == "Off") { - language = "Off"; options.push(' '); } - else if (stream.Language && stream.Language != "und") { - var culture = cultures.filter(function (current) { - return current.ThreeLetterISOLanguageName.toLowerCase() == stream.Language.toLowerCase(); - }); - - if (culture.length) { - language = culture[0].DisplayName; - } - } - - html += '
' + (language || 'Unknown language') + '
'; + html += '
' + (stream.Language || 'Unknown language') + '
'; if (stream.Codec) { options.push(stream.Codec); @@ -556,7 +517,7 @@ return html; }; - function getQualityFlyoutHtml(item) { + function getQualityFlyoutHtml() { var html = ''; @@ -567,7 +528,7 @@ var currentAudioStreamIndex = getParameterByName('AudioStreamIndex', video.currentSrc); - var options = getVideoQualityOptions(item, currentAudioStreamIndex, transcodingExtension); + var options = getVideoQualityOptions(currentMediaVersion.MediaStreams, currentAudioStreamIndex, transcodingExtension); if (isStatic) { options[0].name = "Direct"; @@ -659,9 +620,9 @@ return audioStreams.length ? audioStreams[0].Index : null; }; - function getVideoQualityOptions(item) { + function getVideoQualityOptions(mediaStreams) { - var videoStream = (item.MediaStreams || []).filter(function (stream) { + var videoStream = mediaStreams.filter(function (stream) { return stream.Type == "Video"; })[0]; @@ -735,9 +696,9 @@ return options; }; - function playVideo(item, startPosition, user) { + function playVideo(item, mediaVersion, startPosition, user) { - var mediaStreams = item.MediaStreams || []; + var mediaStreams = mediaVersion.MediaStreams || []; var baseParams = { audioChannels: 2, @@ -748,20 +709,20 @@ Static: false }; - var mp4Quality = getVideoQualityOptions(item).filter(function (opt) { + var mp4Quality = getVideoQualityOptions(mediaStreams).filter(function (opt) { return opt.selected; })[0]; - mp4Quality = $.extend(mp4Quality, self.getFinalVideoParams(item, mp4Quality.maxWidth, mp4Quality.bitrate, baseParams.AudioStreamIndex, baseParams.SubtitleStreamIndex, '.mp4')); + mp4Quality = $.extend(mp4Quality, self.getFinalVideoParams(mediaVersion, mp4Quality.maxWidth, mp4Quality.bitrate, baseParams.AudioStreamIndex, baseParams.SubtitleStreamIndex, '.mp4')); - var webmQuality = getVideoQualityOptions(item).filter(function (opt) { + var webmQuality = getVideoQualityOptions(mediaStreams).filter(function (opt) { return opt.selected; })[0]; - webmQuality = $.extend(webmQuality, self.getFinalVideoParams(item, webmQuality.maxWidth, webmQuality.bitrate, baseParams.AudioStreamIndex, baseParams.SubtitleStreamIndex, '.webm')); + webmQuality = $.extend(webmQuality, self.getFinalVideoParams(mediaVersion, webmQuality.maxWidth, webmQuality.bitrate, baseParams.AudioStreamIndex, baseParams.SubtitleStreamIndex, '.webm')); - var m3U8Quality = getVideoQualityOptions(item).filter(function (opt) { + var m3U8Quality = getVideoQualityOptions(mediaStreams).filter(function (opt) { return opt.selected; })[0]; - m3U8Quality = $.extend(m3U8Quality, self.getFinalVideoParams(item, mp4Quality.maxWidth, mp4Quality.bitrate, baseParams.AudioStreamIndex, baseParams.SubtitleStreamIndex, '.mp4')); + m3U8Quality = $.extend(m3U8Quality, self.getFinalVideoParams(mediaVersion, mp4Quality.maxWidth, mp4Quality.bitrate, baseParams.AudioStreamIndex, baseParams.SubtitleStreamIndex, '.mp4')); // Webm must be ahead of mp4 due to the issue of mp4 playing too fast in chrome var prioritizeWebmOverH264 = $.browser.chrome || $.browser.msie; @@ -772,7 +733,7 @@ var seekParam = isStatic && startPosition ? '#t=' + (startPosition / 10000000) : ''; - var mp4VideoUrl = ApiClient.getUrl('Videos/' + item.Id + '/stream.mp4', $.extend({}, baseParams, { + var mp4VideoUrl = ApiClient.getUrl('Videos/' + mediaVersion.ItemId + '/stream.mp4', $.extend({}, baseParams, { profile: 'baseline', level: 3, Static: isStatic, @@ -784,7 +745,7 @@ })) + seekParam; - var webmVideoUrl = ApiClient.getUrl('Videos/' + item.Id + '/stream.webm', $.extend({}, baseParams, { + var webmVideoUrl = ApiClient.getUrl('Videos/' + mediaVersion.ItemId + '/stream.webm', $.extend({}, baseParams, { VideoCodec: 'vpx', AudioCodec: 'Vorbis', @@ -794,7 +755,7 @@ })) + seekParam; - var hlsVideoUrl = ApiClient.getUrl('Videos/' + item.Id + '/stream.m3u8', $.extend({}, baseParams, { + var hlsVideoUrl = ApiClient.getUrl('Videos/' + mediaVersion.ItemId + '/stream.m3u8', $.extend({}, baseParams, { profile: 'baseline', level: 3, timeStampOffsetMs: 0, @@ -874,7 +835,7 @@ $('#video-subtitleButton', videoControls).hide(); } - if (item.Chapters && item.Chapters.length) { + if (mediaVersion.Chapters && mediaVersion.Chapters.length) { $('#video-chaptersButton', videoControls).show(); } else { $('#video-chaptersButton', videoControls).hide(); @@ -921,9 +882,9 @@ videoElement.off("playing.once"); - ApiClient.reportPlaybackStart(Dashboard.getCurrentUserId(), item.Id, true, item.MediaType); + ApiClient.reportPlaybackStart(Dashboard.getCurrentUserId(), mediaVersion.ItemId, true, item.MediaType); - self.startProgressInterval(item.Id); + self.startProgressInterval(mediaVersion.ItemId); }).on("pause", function (e) { @@ -1039,6 +1000,7 @@ fullscreenExited = false; currentItem = item; + currentMediaVersion = mediaVersion; return videoElement[0]; }; diff --git a/dashboard-ui/scripts/mediaplayer.js b/dashboard-ui/scripts/mediaplayer.js index 487e57c141..1df64ae481 100644 --- a/dashboard-ui/scripts/mediaplayer.js +++ b/dashboard-ui/scripts/mediaplayer.js @@ -8,6 +8,7 @@ var currentMediaElement; var currentProgressInterval; var currentItem; + var currentMediaVersion; var curentDurationTicks; var canClientSeek; var currentPlaylistIndex = 0; @@ -53,7 +54,7 @@ var position = Math.floor(10000000 * endTime) + self.startTimeTicksOffset; - ApiClient.reportPlaybackStopped(Dashboard.getCurrentUserId(), currentItem.Id, position); + ApiClient.reportPlaybackStopped(Dashboard.getCurrentUserId(), currentMediaVersion.ItemId, position); if (currentItem.MediaType == "Video") { ApiClient.stopActiveEncodings(); @@ -135,7 +136,7 @@ var transcodingExtension = self.getTranscodingExtension(); - var finalParams = self.getFinalVideoParams(currentItem, maxWidth, bitrate, audioStreamIndex, subtitleStreamIndex, transcodingExtension); + var finalParams = self.getFinalVideoParams(currentMediaVersion, maxWidth, bitrate, audioStreamIndex, subtitleStreamIndex, transcodingExtension); currentSrc = replaceQueryString(currentSrc, 'MaxWidth', finalParams.maxWidth); currentSrc = replaceQueryString(currentSrc, 'VideoBitrate', finalParams.videoBitrate); currentSrc = replaceQueryString(currentSrc, 'AudioBitrate', finalParams.audioBitrate); @@ -155,8 +156,8 @@ $(this).off('play.onceafterseek').on('ended.playbackstopped', self.onPlaybackStopped).on('ended.playnext', self.playNextAfterEnded); - self.startProgressInterval(currentItem.Id); - sendProgressUpdate(currentItem.Id); + self.startProgressInterval(currentMediaVersion.ItemId); + sendProgressUpdate(currentMediaVersion.ItemId); }); @@ -193,9 +194,9 @@ self.currentTimeElement.html(timeText); }; - self.canPlayVideoDirect = function (item, videoStream, audioStream, subtitleStream, maxWidth, bitrate) { + self.canPlayVideoDirect = function (mediaVersion, videoStream, audioStream, subtitleStream, maxWidth, bitrate) { - if (item.VideoType != "VideoFile" || item.LocationType != "FileSystem") { + if (mediaVersion.VideoType != "VideoFile" || mediaVersion.LocationType != "FileSystem") { console.log('Transcoding because the content is not a video file'); return false; } @@ -228,7 +229,7 @@ return false; } - var extension = item.Path.substring(item.Path.lastIndexOf('.') + 1).toLowerCase(); + var extension = mediaVersion.Path.substring(mediaVersion.Path.lastIndexOf('.') + 1).toLowerCase(); if (extension == 'm4v') { return $.browser.chrome; @@ -237,28 +238,29 @@ return extension.toLowerCase() == 'mp4'; }; - self.getFinalVideoParams = function (item, maxWidth, bitrate, audioStreamIndex, subtitleStreamIndex, transcodingExtension) { + self.getFinalVideoParams = function (mediaVersion, maxWidth, bitrate, audioStreamIndex, subtitleStreamIndex, transcodingExtension) { - var videoStream = (item.MediaStreams || []).filter(function (stream) { + var mediaStreams = mediaVersion.MediaStreams; + + var videoStream = mediaStreams.filter(function (stream) { return stream.Type === "Video"; })[0]; - var audioStream = (item.MediaStreams || []).filter(function (stream) { + var audioStream = mediaStreams.filter(function (stream) { return stream.Index === audioStreamIndex; })[0]; - var subtitleStream = (item.MediaStreams || []).filter(function (stream) { + var subtitleStream = mediaStreams.filter(function (stream) { return stream.Index === subtitleStreamIndex; })[0]; - var canPlayDirect = self.canPlayVideoDirect(item, videoStream, audioStream, subtitleStream, maxWidth, bitrate); + var canPlayDirect = self.canPlayVideoDirect(mediaVersion, videoStream, audioStream, subtitleStream, maxWidth, bitrate); var audioBitrate = bitrate >= 700000 ? 128000 : 64000; var videoBitrate = bitrate - audioBitrate; return { - isStatic: canPlayDirect, maxWidth: maxWidth, audioCodec: transcodingExtension == '.webm' ? 'vorbis' : 'aac', @@ -266,7 +268,7 @@ audioBitrate: audioBitrate, videoBitrate: videoBitrate }; - } + }; self.canPlay = function (item, user) { @@ -397,6 +399,13 @@ self.playlist = items; currentPlaylistIndex = 0; }; + + function getOptimalMediaVersion(versions) { + + // TODO: Implement + + return versions[0]; + } self.playInternal = function (item, startPosition, user) { @@ -414,17 +423,25 @@ if (item.MediaType === "Video") { - videoPlayer(self, item, startPosition, user); - mediaElement = self.initVideoPlayer(); currentItem = item; - curentDurationTicks = item.RunTimeTicks; + currentMediaVersion = getOptimalMediaVersion(item.MediaVersions); + + videoPlayer(self, item, currentMediaVersion, startPosition, user); + mediaElement = self.initVideoPlayer(); + curentDurationTicks = currentMediaVersion.RunTimeTicks; + mediaControls = $("#videoControls"); } else if (item.MediaType === "Audio") { - mediaElement = playAudio(item, startPosition); + currentItem = item; + currentMediaVersion = getOptimalMediaVersion(item.MediaVersions); + + mediaElement = playAudio(item, currentMediaVersion, startPosition); mediaControls.show(); + curentDurationTicks = currentMediaVersion.RunTimeTicks; + } else { throw new Error("Unrecognized media type"); } @@ -915,7 +932,7 @@ var position = Math.floor(10000000 * endTime) + self.startTimeTicksOffset; - ApiClient.reportPlaybackStopped(Dashboard.getCurrentUserId(), currentItem.Id, position); + ApiClient.reportPlaybackStopped(Dashboard.getCurrentUserId(), currentMediaVersion.ItemId, position); } }); @@ -966,7 +983,7 @@ var newPercent = parseInt(this.value); - var newPositionTicks = (newPercent / 100) * currentItem.RunTimeTicks; + var newPositionTicks = (newPercent / 100) * currentMediaVersion.RunTimeTicks; self.changeStream(Math.floor(newPositionTicks)); }; @@ -980,7 +997,7 @@ return d >= 0 && text.lastIndexOf(pattern) === d; }; - function playAudio(item, startPositionTicks) { + function playAudio(item, mediaVersion, startPositionTicks) { startPositionTicks = startPositionTicks || 0; @@ -990,19 +1007,19 @@ StartTimeTicks: startPositionTicks }; - var mp3Url = ApiClient.getUrl('Audio/' + item.Id + '/stream.mp3', $.extend({}, baseParams, { + var mp3Url = ApiClient.getUrl('Audio/' + mediaVersion.ItemId + '/stream.mp3', $.extend({}, baseParams, { audioCodec: 'mp3' })); - var aacUrl = ApiClient.getUrl('Audio/' + item.Id + '/stream.aac', $.extend({}, baseParams, { + var aacUrl = ApiClient.getUrl('Audio/' + mediaVersion.ItemId + '/stream.aac', $.extend({}, baseParams, { audioCodec: 'aac' })); - var webmUrl = ApiClient.getUrl('Audio/' + item.Id + '/stream.webm', $.extend({}, baseParams, { + var webmUrl = ApiClient.getUrl('Audio/' + mediaVersion.ItemId + '/stream.webm', $.extend({}, baseParams, { audioCodec: 'Vorbis' })); - var mediaStreams = item.MediaStreams || []; + var mediaStreams = mediaVersion.MediaStreams; var isStatic = false; var seekParam = isStatic && startPositionTicks ? '#t=' + (startPositionTicks / 10000000) : ''; @@ -1089,9 +1106,9 @@ audioElement.off("play.once"); - ApiClient.reportPlaybackStart(Dashboard.getCurrentUserId(), item.Id, true, item.MediaType); + ApiClient.reportPlaybackStart(Dashboard.getCurrentUserId(), mediaVersion.ItemId, true, item.MediaType); - self.startProgressInterval(item.Id); + self.startProgressInterval(mediaVersion.ItemId); }).on("pause", function () { @@ -1112,9 +1129,6 @@ }).on("ended.playbackstopped", self.onPlaybackStopped).on('ended.playnext', self.playNextAfterEnded); - currentItem = item; - curentDurationTicks = item.RunTimeTicks; - return audioElement[0]; }; diff --git a/dashboard-ui/scripts/remotecontrol.js b/dashboard-ui/scripts/remotecontrol.js index 86e721876c..24e33bc0ac 100644 --- a/dashboard-ui/scripts/remotecontrol.js +++ b/dashboard-ui/scripts/remotecontrol.js @@ -299,18 +299,6 @@ resumeButtonContainer.show(); } } - else if (value == "PlayFromChapter" && item.Chapters && item.Chapters.length) { - - playFromMenu.show(); - playButtonContainer.show(); - - if (!playFromRendered) { - playFromRendered = true; - renderPlayFromOptions(playFromMenu, item); - } - - popup.popup("reposition", { tolerance: 0 }); - } else if (value == "Trailer") { trailersElem.show(); @@ -384,65 +372,6 @@ }); } - function renderPlayFromOptions(elem, item) { - - var html = ''; - - html += '

Play from scene

'; - - html += '
'; - html += ''; - - html += ''; - - for (var i = 0, length = item.Chapters.length; i < length; i++) { - - var chapter = item.Chapters[i]; - - html += ''; - - var name = chapter.Name || ("Chapter " + (i + 1)); - - html += ''; - - html += ''; - - html += ''; - - html += ''; - } - - html += ''; - - html += '
'; - - var imgUrl; - - if (chapter.ImageTag) { - - imgUrl = ApiClient.getImageUrl(item.Id, { - maxheight: 80, - tag: chapter.ImageTag, - type: "Chapter", - index: i - }); - - } else { - imgUrl = "css/images/media/chapterflyout.png"; - } - - html += ''; - - html += '' + name + '
' + Dashboard.getDisplayTime(chapter.StartPositionTicks) + '
'; - html += '
'; - - elem.html(html); - - $('.tdSelectPlayTime', elem).html(''); - - $('.chkSelectPlayTime:first', elem).checked(true); - } - function renderSessionsInPlayMenu(sessions, options, elem, popup) { if (!sessions.length) { @@ -476,10 +405,6 @@ html += '