From 1fc390dc50cff486aa65b9475e8657de92cc2e40 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 26 Mar 2015 12:58:02 -0400 Subject: [PATCH 01/33] use server to build initial stream url's --- dashboard-ui/scripts/mediaplayer-video.js | 254 +++-------- dashboard-ui/scripts/mediaplayer.js | 408 +++++++++++++----- .../thirdparty/apiclient/apiclient.js | 8 +- 3 files changed, 375 insertions(+), 295 deletions(-) diff --git a/dashboard-ui/scripts/mediaplayer-video.js b/dashboard-ui/scripts/mediaplayer-video.js index 0f07dce33..6ccf001f3 100644 --- a/dashboard-ui/scripts/mediaplayer-video.js +++ b/dashboard-ui/scripts/mediaplayer-video.js @@ -428,14 +428,12 @@ if (!$(this).hasClass('selectedMediaPopupOption')) { - var maxWidth = parseInt(this.getAttribute('data-maxwidth')); var bitrate = parseInt(this.getAttribute('data-bitrate')); AppSettings.maxStreamingBitrate(bitrate); self.changeStream(self.getCurrentTicks(), { - MaxWidth: maxWidth, Bitrate: bitrate }); } @@ -796,7 +794,12 @@ var currentSrc = self.getCurrentSrc(self.currentMediaElement).toLowerCase(); var isStatic = currentSrc.indexOf('static=true') != -1; - var options = getVideoQualityOptions(self.currentMediaSource.MediaStreams); + var videoStream = self.currentMediaSource.MediaStreams.filter(function (stream) { + return stream.Type == "Video"; + })[0]; + var videoWidth = videoStream ? videoStream.Width : null; + + var options = self.getVideoQualityOptions(videoWidth); if (isStatic) { options[0].name = "Direct"; @@ -819,7 +822,7 @@ cssClass += ' selectedMediaPopupOption'; } - var optionHtml = '
  • '; + var optionHtml = '
  • '; optionHtml += '

    '; @@ -845,85 +848,6 @@ return html; } - function getVideoQualityOptions(mediaStreams) { - - var videoStream = mediaStreams.filter(function (stream) { - return stream.Type == "Video"; - })[0]; - - var bitrateSetting = AppSettings.maxStreamingBitrate(); - - var maxAllowedWidth = self.getMaxPlayableWidth(); - - var options = []; - - // We have media info - if (videoStream && videoStream.Width) { - - maxAllowedWidth = videoStream.Width; - } - - // Some 1080- videos are reported as 1912? - if (maxAllowedWidth >= 1900) { - options.push({ name: '1080p - 30Mbps', maxWidth: 1920, bitrate: 30000000 }); - options.push({ name: '1080p - 25Mbps', maxWidth: 1920, bitrate: 25000000 }); - options.push({ name: '1080p - 20Mbps', maxWidth: 1920, bitrate: 20000000 }); - options.push({ name: '1080p - 15Mbps', maxWidth: 1920, bitrate: 15000000 }); - options.push({ name: '1080p - 10Mbps', maxWidth: 1920, bitrate: 10000000 }); - options.push({ name: '1080p - 8Mbps', maxWidth: 1920, bitrate: 8000000 }); - options.push({ name: '1080p - 6Mbps', maxWidth: 1920, bitrate: 6000000 }); - options.push({ name: '1080p - 5Mbps', maxWidth: 1920, bitrate: 5000000 }); - } - else if (maxAllowedWidth >= 1260) { - options.push({ name: '720p - 10Mbps', maxWidth: 1280, bitrate: 10000000 }); - options.push({ name: '720p - 8Mbps', maxWidth: 1280, bitrate: 8000000 }); - options.push({ name: '720p - 6Mbps', maxWidth: 1280, bitrate: 6000000 }); - options.push({ name: '720p - 5Mbps', maxWidth: 1280, bitrate: 5000000 }); - } - else if (maxAllowedWidth >= 460) { - options.push({ name: '480p - 4Mbps', maxWidth: 720, bitrate: 4000000 }); - options.push({ name: '480p - 3Mbps', maxWidth: 720, bitrate: 3000000 }); - options.push({ name: '480p - 2.5Mbps', maxWidth: 720, bitrate: 2500000 }); - options.push({ name: '480p - 2Mbps', maxWidth: 720, bitrate: 2000000 }); - options.push({ name: '480p - 1.5Mbps', maxWidth: 720, bitrate: 1500000 }); - } - - if (maxAllowedWidth >= 1260) { - options.push({ name: '720p - 4Mbps', maxWidth: 1280, bitrate: 4000000 }); - options.push({ name: '720p - 3Mbps', maxWidth: 1280, bitrate: 3000000 }); - options.push({ name: '720p - 2Mbps', maxWidth: 1280, bitrate: 2000000 }); - - // The extra 1 is because they're keyed off the bitrate value - options.push({ name: '720p - 1Mbps', maxWidth: 1280, bitrate: 1000001 }); - } - - options.push({ name: '480p - 1.0Mbps', maxWidth: 720, bitrate: 1000000 }); - options.push({ name: '480p - 720kbps', maxWidth: 720, bitrate: 720000 }); - options.push({ name: '480p - 420kbps', maxWidth: 720, bitrate: 420000 }); - options.push({ name: '360p', maxWidth: 640, bitrate: 400000 }); - options.push({ name: '240p', maxWidth: 426, bitrate: 320000 }); - - var i, length, option; - var selectedIndex = -1; - for (i = 0, length = options.length; i < length; i++) { - - option = options[i]; - - if (selectedIndex == -1 && option.bitrate <= bitrateSetting) { - selectedIndex = i; - } - } - - if (selectedIndex == -1) { - - selectedIndex = options.length - 1; - } - - options[selectedIndex].selected = true; - - return options; - } - function bindEventsForPlayback() { var hideElementsOnIdle = !$.browser.mobile; @@ -1007,101 +931,71 @@ } }; - self.playVideo = function (playbackInfo, item, mediaSource, startPosition) { + self.playVideo = function (deviceProfile, playbackInfo, item, mediaSource, startPosition) { + + var videoUrl; + var contentType; var mediaStreams = mediaSource.MediaStreams || []; - var subtitleStreams = mediaStreams.filter(function (s) { return s.Type == 'Subtitle'; }); - var selectedSubtitleStream = subtitleStreams.filter(function (s) { - return s.Index == mediaSource.DefaultSubtitleStreamIndex; - - })[0]; - - var baseParams = { - audioChannels: 2, - StartTimeTicks: startPosition, - AudioStreamIndex: mediaSource.DefaultAudioStreamIndex, - deviceId: ApiClient.deviceId(), - Static: false, - mediaSourceId: mediaSource.Id, - api_key: ApiClient.accessToken(), - StreamId: playbackInfo.StreamId - }; - - if (selectedSubtitleStream && (!self.supportsSubtitleStreamExternally(selectedSubtitleStream) || !self.supportsTextTracks())) { - baseParams.SubtitleStreamIndex = mediaSource.DefaultSubtitleStreamIndex; - } - - var mp4Quality = getVideoQualityOptions(mediaStreams).filter(function (opt) { - return opt.selected; - })[0]; - mp4Quality = $.extend(mp4Quality, self.getFinalVideoParams(mediaSource, mp4Quality.maxWidth, mp4Quality.bitrate, baseParams.AudioStreamIndex, baseParams.SubtitleStreamIndex, '.mp4')); - - var webmQuality = getVideoQualityOptions(mediaStreams).filter(function (opt) { - return opt.selected; - })[0]; - webmQuality = $.extend(webmQuality, self.getFinalVideoParams(mediaSource, webmQuality.maxWidth, webmQuality.bitrate, baseParams.AudioStreamIndex, baseParams.SubtitleStreamIndex, '.webm')); - - var m3U8Quality = getVideoQualityOptions(mediaStreams).filter(function (opt) { - return opt.selected; - })[0]; - m3U8Quality = $.extend(m3U8Quality, self.getFinalVideoParams(mediaSource, mp4Quality.maxWidth, mp4Quality.bitrate, baseParams.AudioStreamIndex, baseParams.SubtitleStreamIndex, '.mp4')); - - var isStatic = mp4Quality.isStatic; - - self.startTimeTicksOffset = isStatic ? 0 : startPosition || 0; - - var startPositionInSeekParam = startPosition ? (startPosition / 10000000) : 0; - var seekParam = startPositionInSeekParam ? '#t=' + startPositionInSeekParam : ''; - - var mp4VideoUrl = ApiClient.getUrl('Videos/' + item.Id + '/stream.mp4', $.extend({}, baseParams, { - Static: isStatic, - maxWidth: mp4Quality.maxWidth, - videoBitrate: mp4Quality.videoBitrate, - audioBitrate: mp4Quality.audioBitrate, - VideoCodec: mp4Quality.videoCodec, - AudioCodec: mp4Quality.audioCodec, - profile: 'high', - //EnableAutoStreamCopy: false, - level: '41' - })); - - if (isStatic && mediaSource.Protocol == 'Http' && !mediaSource.RequiredHttpHeaders.length) { - mp4VideoUrl = mediaSource.Path; - } - - if (isStatic) { - mp4VideoUrl += seekParam; + if (mediaSource.enableDirectPlay) { + videoUrl = mediaSource.Path; + self.startTimeTicksOffset = 0; + contentType = 'video/' + mediaSource.Container; } else { - mp4VideoUrl += "&StreamId=" + new Date().getTime(); + + var selectedSubtitleStream = subtitleStreams.filter(function (s) { + return s.Index == mediaSource.DefaultSubtitleStreamIndex; + + })[0]; + + var transcodingParams = { + audioChannels: 2, + StartTimeTicks: startPosition, + AudioStreamIndex: mediaSource.DefaultAudioStreamIndex, + deviceId: ApiClient.deviceId(), + mediaSourceId: mediaSource.Id, + api_key: ApiClient.accessToken(), + StreamId: playbackInfo.StreamId, + ClientTime: new Date().getTime() + }; + + if (selectedSubtitleStream && (!self.supportsSubtitleStreamExternally(selectedSubtitleStream) || !self.supportsTextTracks())) { + transcodingParams.SubtitleStreamIndex = mediaSource.DefaultSubtitleStreamIndex; + } + + self.startTimeTicksOffset = mediaSource.SupportsDirectStream ? 0 : startPosition || 0; + var startPositionInSeekParam = startPosition ? (startPosition / 10000000) : 0; + var seekParam = startPositionInSeekParam ? '#t=' + startPositionInSeekParam : ''; + + if (mediaSource.SupportsDirectStream) { + + videoUrl = ApiClient.getUrl('Videos/' + item.Id + '/stream.' + mediaSource.Container, { + Static: true, + mediaSourceId: mediaSource.Id, + api_key: ApiClient.accessToken() + }); + videoUrl += seekParam; + contentType = 'video/' + mediaSource.Container; + + } else { + videoUrl = ApiClient.getUrl(mediaSource.TranscodingUrl); + + if (mediaSource.TranscodingSubProtocol == 'hls') { + + videoUrl += seekParam; + contentType = 'application/x-mpegURL'; + } + else { + + contentType = 'video/' + mediaSource.TranscodingContainer; + } + } } - var webmVideoUrl = ApiClient.getUrl('Videos/' + item.Id + '/stream.webm', $.extend({}, baseParams, { - VideoCodec: 'vpx', - AudioCodec: 'Vorbis', - maxWidth: webmQuality.maxWidth, - videoBitrate: webmQuality.videoBitrate, - audioBitrate: webmQuality.audioBitrate, - EnableAutoStreamCopy: false, - StreamId: new Date().getTime() - })); - - var hlsVideoUrl = ApiClient.getUrl('Videos/' + item.Id + '/master.m3u8', $.extend({}, baseParams, { - maxWidth: m3U8Quality.maxWidth, - videoBitrate: m3U8Quality.videoBitrate, - audioBitrate: m3U8Quality.audioBitrate, - VideoCodec: m3U8Quality.videoCodec, - AudioCodec: m3U8Quality.audioCodec, - profile: 'high', - level: '41', - StartTimeTicks: 0, - StreamId: new Date().getTime() - - })) + seekParam; - //======================================================================================> // Create video player @@ -1118,27 +1012,7 @@ html += '

    ${HeaderSupporterBenefits}

    -

    -
    - - -
    -
    -
    +
    +
    +

    ${HeaderSupporterBenefits}

    +

    + + + +
    +
    +
    +
    +
    -
    From 4f967db0b7a3c191a018914243cb44d9d2a1963d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 27 Mar 2015 00:17:04 -0400 Subject: [PATCH 08/33] fix subtitle syncing --- dashboard-ui/css/librarybrowser.css | 1 - dashboard-ui/scripts/mediaplayer.js | 1 - 2 files changed, 2 deletions(-) diff --git a/dashboard-ui/css/librarybrowser.css b/dashboard-ui/css/librarybrowser.css index 7c2ef39c9..62de223e2 100644 --- a/dashboard-ui/css/librarybrowser.css +++ b/dashboard-ui/css/librarybrowser.css @@ -1448,5 +1448,4 @@ span.itemCommunityRating:not(:empty) + .userDataIcons { } .homeTopViews .cardText{ - font-size: 14px; } \ No newline at end of file diff --git a/dashboard-ui/scripts/mediaplayer.js b/dashboard-ui/scripts/mediaplayer.js index 1b8f39d3b..f4ac300c3 100644 --- a/dashboard-ui/scripts/mediaplayer.js +++ b/dashboard-ui/scripts/mediaplayer.js @@ -638,7 +638,6 @@ function getOptimalMediaSource(mediaType, versions) { - alert(JSON.stringify(versions)); var optimalVersion = versions.filter(function (v) { v.enableDirectPlay = supportsDirectPlay(v); From bc94a9ab4bbd60a37e4f87c60b7e2e00c619011b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 27 Mar 2015 00:42:41 -0400 Subject: [PATCH 09/33] sync updates --- dashboard-ui/scripts/mediaplayer-video.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dashboard-ui/scripts/mediaplayer-video.js b/dashboard-ui/scripts/mediaplayer-video.js index 201a3cb35..cf6c13fed 100644 --- a/dashboard-ui/scripts/mediaplayer-video.js +++ b/dashboard-ui/scripts/mediaplayer-video.js @@ -971,7 +971,9 @@ for (var i = 0, length = textStreams.length; i < length; i++) { var textStream = textStreams[i]; - var textStreamUrl = ApiClient.getUrl('Videos/' + item.Id + '/' + mediaSource.Id + '/Subtitles/' + textStream.Index + '/Stream.vtt', { + var textStreamUrl = mediaSource.Protocol == 'Http' ? + textStream.Path : + ApiClient.getUrl('Videos/' + item.Id + '/' + mediaSource.Id + '/Subtitles/' + textStream.Index + '/Stream.vtt', { startPositionTicks: (startPosition || 0), api_key: ApiClient.accessToken() }); From e266c8c4c880193b1727e5f1e85a972d6042519d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 27 Mar 2015 22:19:20 -0400 Subject: [PATCH 10/33] sync updates --- dashboard-ui/scripts/gamegenrepage.js | 2 +- dashboard-ui/scripts/gamestudiospage.js | 2 +- dashboard-ui/scripts/moviegenres.js | 2 +- dashboard-ui/scripts/moviepeople.js | 2 +- dashboard-ui/scripts/moviestudios.js | 2 +- dashboard-ui/scripts/musicalbumartists.js | 2 +- dashboard-ui/scripts/musicartists.js | 2 +- dashboard-ui/scripts/musicgenres.js | 2 +- dashboard-ui/scripts/tvgenres.js | 2 +- dashboard-ui/scripts/tvpeople.js | 2 +- dashboard-ui/scripts/tvstudios.js | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/dashboard-ui/scripts/gamegenrepage.js b/dashboard-ui/scripts/gamegenrepage.js index 909d16735..4167efe54 100644 --- a/dashboard-ui/scripts/gamegenrepage.js +++ b/dashboard-ui/scripts/gamegenrepage.js @@ -6,7 +6,7 @@ SortBy: "SortName", SortOrder: "Ascending", Recursive: true, - Fields: "DateCreated", + Fields: "DateCreated,ItemCounts", StartIndex: 0 }; diff --git a/dashboard-ui/scripts/gamestudiospage.js b/dashboard-ui/scripts/gamestudiospage.js index 31f39a2ba..e7bc72318 100644 --- a/dashboard-ui/scripts/gamestudiospage.js +++ b/dashboard-ui/scripts/gamestudiospage.js @@ -7,7 +7,7 @@ SortOrder: "Ascending", MediaTypes: "Game", Recursive: true, - Fields: "UserData", + Fields: "ItemCounts", StartIndex: 0 }; diff --git a/dashboard-ui/scripts/moviegenres.js b/dashboard-ui/scripts/moviegenres.js index 2129a2366..902f5cd25 100644 --- a/dashboard-ui/scripts/moviegenres.js +++ b/dashboard-ui/scripts/moviegenres.js @@ -9,7 +9,7 @@ SortOrder: "Ascending", IncludeItemTypes: "Movie", Recursive: true, - Fields: "DateCreated,SyncInfo", + Fields: "DateCreated,SyncInfo,ItemCounts", StartIndex: 0 }; diff --git a/dashboard-ui/scripts/moviepeople.js b/dashboard-ui/scripts/moviepeople.js index a9fe5f7e5..5246757bc 100644 --- a/dashboard-ui/scripts/moviepeople.js +++ b/dashboard-ui/scripts/moviepeople.js @@ -9,7 +9,7 @@ SortOrder: "Ascending", IncludeItemTypes: "Movie,Trailer", Recursive: true, - Fields: "DateCreated", + Fields: "DateCreated,ItemCounts", PersonTypes: "", StartIndex: 0, Limit: 100 diff --git a/dashboard-ui/scripts/moviestudios.js b/dashboard-ui/scripts/moviestudios.js index 8f0fb8108..34f3a0b45 100644 --- a/dashboard-ui/scripts/moviestudios.js +++ b/dashboard-ui/scripts/moviestudios.js @@ -7,7 +7,7 @@ SortOrder: "Ascending", IncludeItemTypes: "Movie", Recursive: true, - Fields: "DateCreated", + Fields: "DateCreated,ItemCounts", StartIndex: 0 }; diff --git a/dashboard-ui/scripts/musicalbumartists.js b/dashboard-ui/scripts/musicalbumartists.js index 020dba415..a19246fd4 100644 --- a/dashboard-ui/scripts/musicalbumartists.js +++ b/dashboard-ui/scripts/musicalbumartists.js @@ -10,7 +10,7 @@ SortBy: "SortName", SortOrder: "Ascending", Recursive: true, - Fields: "PrimaryImageAspectRatio,SortName,DateCreated,SyncInfo", + Fields: "PrimaryImageAspectRatio,SortName,DateCreated,SyncInfo,ItemCounts", StartIndex: 0, ImageTypeLimit: 1, EnableImageTypes: "Primary,Backdrop,Banner,Thumb" diff --git a/dashboard-ui/scripts/musicartists.js b/dashboard-ui/scripts/musicartists.js index a1128a36a..8c9171e84 100644 --- a/dashboard-ui/scripts/musicartists.js +++ b/dashboard-ui/scripts/musicartists.js @@ -10,7 +10,7 @@ SortBy: "SortName", SortOrder: "Ascending", Recursive: true, - Fields: "PrimaryImageAspectRatio,SortName,DateCreated,SyncInfo", + Fields: "PrimaryImageAspectRatio,SortName,DateCreated,SyncInfo,ItemCounts", StartIndex: 0, ImageTypeLimit: 1, EnableImageTypes: "Primary,Backdrop,Banner,Thumb" diff --git a/dashboard-ui/scripts/musicgenres.js b/dashboard-ui/scripts/musicgenres.js index 9cecd6e1d..70d0f1837 100644 --- a/dashboard-ui/scripts/musicgenres.js +++ b/dashboard-ui/scripts/musicgenres.js @@ -7,7 +7,7 @@ SortOrder: "Ascending", IncludeItemTypes: "Audio,MusicVideo", Recursive: true, - Fields: "DateCreated,SyncInfo", + Fields: "DateCreated,SyncInfo,ItemCounts", StartIndex: 0 }; diff --git a/dashboard-ui/scripts/tvgenres.js b/dashboard-ui/scripts/tvgenres.js index 9f926d06b..024314393 100644 --- a/dashboard-ui/scripts/tvgenres.js +++ b/dashboard-ui/scripts/tvgenres.js @@ -9,7 +9,7 @@ SortOrder: "Ascending", IncludeItemTypes: "Series", Recursive: true, - Fields: "DateCreated,SyncInfo", + Fields: "DateCreated,SyncInfo,ItemCounts", StartIndex: 0 }; diff --git a/dashboard-ui/scripts/tvpeople.js b/dashboard-ui/scripts/tvpeople.js index f314af0a2..44cfbee2c 100644 --- a/dashboard-ui/scripts/tvpeople.js +++ b/dashboard-ui/scripts/tvpeople.js @@ -9,7 +9,7 @@ SortOrder: "Ascending", IncludeItemTypes: "Series,Episode", Recursive: true, - Fields: "DateCreated", + Fields: "DateCreated,ItemCounts", PersonTypes: "", StartIndex: 0, Limit: 100 diff --git a/dashboard-ui/scripts/tvstudios.js b/dashboard-ui/scripts/tvstudios.js index 8906aa011..2e457a31c 100644 --- a/dashboard-ui/scripts/tvstudios.js +++ b/dashboard-ui/scripts/tvstudios.js @@ -7,7 +7,7 @@ SortOrder: "Ascending", IncludeItemTypes: "Series", Recursive: true, - Fields: "DateCreated", + Fields: "DateCreated,ItemCounts", StartIndex: 0 }; From c2800786fa9969bddaf6e5cec89cb7d663d881ba Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 28 Mar 2015 16:22:27 -0400 Subject: [PATCH 11/33] implement modular media sources --- dashboard-ui/scripts/mediaplayer.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/dashboard-ui/scripts/mediaplayer.js b/dashboard-ui/scripts/mediaplayer.js index f4ac300c3..be73b4b89 100644 --- a/dashboard-ui/scripts/mediaplayer.js +++ b/dashboard-ui/scripts/mediaplayer.js @@ -665,10 +665,6 @@ DeviceProfile: deviceProfile }; - if (mediaSource) { - postData.MediaSource = mediaSource; - } - var query = { UserId: Dashboard.getCurrentUserId(), StartTimeTicks: startPosition || 0 @@ -680,6 +676,9 @@ if (subtitleStreamIndex != null) { query.SubtitleStreamIndex = subtitleStreamIndex; } + if (mediaSource) { + query.MediaSourceId = mediaSource.Id; + } return ApiClient.ajax({ url: ApiClient.getUrl('Items/' + itemId + '/PlaybackInfo', query), From bf21a282da0af1927771695aa80e18b3009e2e50 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 29 Mar 2015 00:56:39 -0400 Subject: [PATCH 12/33] update stream generation --- dashboard-ui/scripts/mediaplayer-video.js | 2 +- dashboard-ui/scripts/mediaplayer.js | 51 ++++++++++++++++------- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/dashboard-ui/scripts/mediaplayer-video.js b/dashboard-ui/scripts/mediaplayer-video.js index cf6c13fed..7eb57641a 100644 --- a/dashboard-ui/scripts/mediaplayer-video.js +++ b/dashboard-ui/scripts/mediaplayer-video.js @@ -931,7 +931,7 @@ } }; - self.playVideo = function (deviceProfile, playbackInfo, item, mediaSource, startPosition) { + self.playVideo = function (item, mediaSource, startPosition) { var streamInfo = self.createStreamInfo('video', item, mediaSource, startPosition); diff --git a/dashboard-ui/scripts/mediaplayer.js b/dashboard-ui/scripts/mediaplayer.js index be73b4b89..0ba7b2726 100644 --- a/dashboard-ui/scripts/mediaplayer.js +++ b/dashboard-ui/scripts/mediaplayer.js @@ -803,26 +803,24 @@ if (mediaSource) { - self.currentMediaSource = mediaSource; - self.currentItem = item; + if (mediaSource.RequiresOpening1) { - if (item.MediaType === "Video") { + ApiClient.ajax({ + url: ApiClient.getUrl('MediaSources/Open', { + OpenToken: mediaSource.OpenToken + }), + type: 'POST', + dataType: "json" - self.currentMediaElement = self.playVideo(deviceProfile, result, item, self.currentMediaSource, startPosition); - self.currentDurationTicks = self.currentMediaSource.RunTimeTicks; + }).done(function (openLiveStreamResult) { - self.updateNowPlayingInfo(item); + mediaSource = openLiveStreamResult; + playInternalPostMediaSourceSelection(item, mediaSource, startPosition, callback); + }); - } else if (item.MediaType === "Audio") { - - self.currentMediaElement = playAudio(item, self.currentMediaSource, startPosition); - self.currentDurationTicks = self.currentMediaSource.RunTimeTicks; + } else { + playInternalPostMediaSourceSelection(item, mediaSource, startPosition, callback); } - - if (callback) { - callback(); - } - } else { showPlaybackInfoErrorMessage('NoCompatibleStream'); } @@ -831,6 +829,29 @@ }); }; + function playInternalPostMediaSourceSelection(item, mediaSource, startPosition, callback) { + + self.currentMediaSource = mediaSource; + self.currentItem = item; + + if (item.MediaType === "Video") { + + self.currentMediaElement = self.playVideo(item, self.currentMediaSource, startPosition); + self.currentDurationTicks = self.currentMediaSource.RunTimeTicks; + + self.updateNowPlayingInfo(item); + + } else if (item.MediaType === "Audio") { + + self.currentMediaElement = playAudio(item, self.currentMediaSource, startPosition); + self.currentDurationTicks = self.currentMediaSource.RunTimeTicks; + } + + if (callback) { + callback(); + } + } + function validatePlaybackInfoResult(result) { if (result.ErrorCode) { From 2afee2ab2bc2174966eb8fd63b6465c4c85e228c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 29 Mar 2015 12:45:16 -0400 Subject: [PATCH 13/33] update live stream generation --- dashboard-ui/scripts/mediaplayer.js | 44 +++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/dashboard-ui/scripts/mediaplayer.js b/dashboard-ui/scripts/mediaplayer.js index 0ba7b2726..24239d55e 100644 --- a/dashboard-ui/scripts/mediaplayer.js +++ b/dashboard-ui/scripts/mediaplayer.js @@ -690,6 +690,36 @@ }); } + function getLiveStream(itemId, deviceProfile, startPosition, mediaSource, audioStreamIndex, subtitleStreamIndex) { + + var postData = { + DeviceProfile: deviceProfile, + OpenToken: mediaSource.OpenToken + }; + + var query = { + UserId: Dashboard.getCurrentUserId(), + StartTimeTicks: startPosition || 0, + ItemId: itemId + }; + + if (audioStreamIndex != null) { + query.AudioStreamIndex = audioStreamIndex; + } + if (subtitleStreamIndex != null) { + query.SubtitleStreamIndex = subtitleStreamIndex; + } + + return ApiClient.ajax({ + url: ApiClient.getUrl('LiveStreams/Open', query), + type: 'POST', + data: JSON.stringify(postData), + contentType: "application/json", + dataType: "json" + + }); + } + self.createStreamInfo = function (type, item, mediaSource, startPosition) { var mediaUrl; @@ -803,19 +833,11 @@ if (mediaSource) { - if (mediaSource.RequiresOpening1) { + if (mediaSource.RequiresOpening) { - ApiClient.ajax({ - url: ApiClient.getUrl('MediaSources/Open', { - OpenToken: mediaSource.OpenToken - }), - type: 'POST', - dataType: "json" + getLiveStream(item.Id, deviceProfile, startPosition, mediaSource, null, null).done(function (openLiveStreamResult) { - }).done(function (openLiveStreamResult) { - - mediaSource = openLiveStreamResult; - playInternalPostMediaSourceSelection(item, mediaSource, startPosition, callback); + playInternalPostMediaSourceSelection(item, openLiveStreamResult.MediaSource, startPosition, callback); }); } else { From b13ff1ba9348f7bc7006e547e70b24ef42357fd3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 29 Mar 2015 14:31:28 -0400 Subject: [PATCH 14/33] update live stream handling --- dashboard-ui/scripts/mediaplayer.js | 14 +++++++------- dashboard-ui/thirdparty/apiclient/apiclient.js | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/dashboard-ui/scripts/mediaplayer.js b/dashboard-ui/scripts/mediaplayer.js index 24239d55e..54f30bb69 100644 --- a/dashboard-ui/scripts/mediaplayer.js +++ b/dashboard-ui/scripts/mediaplayer.js @@ -397,12 +397,12 @@ var currentSrc = element.currentSrc; - var currentStreamId = getParameterByName('StreamId', currentSrc); + var playSessionId = getParameterByName('PlaySessionId', currentSrc); if (params.AudioStreamIndex == null && params.SubtitleStreamIndex == null && params.Bitrate == null) { currentSrc = replaceQueryString(currentSrc, 'starttimeticks', ticks || 0); - changeStreamToUrl(element, currentStreamId, currentSrc, ticks); + changeStreamToUrl(element, playSessionId, currentSrc, ticks); return; } @@ -426,12 +426,12 @@ self.currentSubtitleStreamIndex = subtitleStreamIndex; currentSrc = ApiClient.getUrl(self.currentMediaSource.TranscodingUrl); - changeStreamToUrl(element, currentStreamId, currentSrc, ticks); + changeStreamToUrl(element, playSessionId, currentSrc, ticks); } }); }; - function changeStreamToUrl(element, currentStreamId, url, newPositionTicks) { + function changeStreamToUrl(element, playSessionId, url, newPositionTicks) { clearProgressInterval(); @@ -447,7 +447,7 @@ }); if (self.currentItem.MediaType == "Video") { - ApiClient.stopActiveEncodings(currentStreamId).done(function () { + ApiClient.stopActiveEncodings(playSessionId).done(function () { self.startTimeTicksOffset = newPositionTicks; element.src = url; @@ -1513,7 +1513,7 @@ var playerElement = this; - var currentStreamId = getParameterByName('StreamId', playerElement.currentSrc); + var playSessionId = getParameterByName('PlaySessionId', playerElement.currentSrc); $(playerElement).off('.mediaplayerevent').off('ended.playbackstopped'); @@ -1526,7 +1526,7 @@ if (item.MediaType == "Video") { - ApiClient.stopActiveEncodings(currentStreamId); + ApiClient.stopActiveEncodings(playSessionId); if (self.isFullScreen()) { self.exitFullScreen(); } diff --git a/dashboard-ui/thirdparty/apiclient/apiclient.js b/dashboard-ui/thirdparty/apiclient/apiclient.js index b2c72ed0a..61df8e7f1 100644 --- a/dashboard-ui/thirdparty/apiclient/apiclient.js +++ b/dashboard-ui/thirdparty/apiclient/apiclient.js @@ -1887,14 +1887,14 @@ }); }; - self.stopActiveEncodings = function (streamId) { + self.stopActiveEncodings = function (playSessionId) { var options = { deviceId: deviceId }; - if (streamId) { - options.streamId = streamId; + if (playSessionId) { + options.PlaySessionId = playSessionId; } var url = self.getUrl("Videos/ActiveEncodings", options); From b6fc58c49423e8351a780aeb107f4d97ebc78e08 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 29 Mar 2015 14:35:18 -0400 Subject: [PATCH 15/33] report live stream id during progress --- dashboard-ui/scripts/mediaplayer.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/dashboard-ui/scripts/mediaplayer.js b/dashboard-ui/scripts/mediaplayer.js index 54f30bb69..88c9e058c 100644 --- a/dashboard-ui/scripts/mediaplayer.js +++ b/dashboard-ui/scripts/mediaplayer.js @@ -1556,7 +1556,8 @@ function sendProgressUpdate() { - var state = self.getPlayerStateInternal(self.currentMediaElement, self.currentItem, self.currentMediaSource); + var element = self.currentMediaElement; + var state = self.getPlayerStateInternal(element, self.currentItem, self.currentMediaSource); var info = { QueueableMediaTypes: state.NowPlayingItem.MediaType, @@ -1566,6 +1567,14 @@ info = $.extend(info, state.PlayState); + if (element) { + var currentSrc = element.currentSrc; + var liveStreamId = getParameterByName('LiveStreamId', currentSrc); + if (liveStreamId) { + info.LiveStreamId = liveStreamId; + } + } + ApiClient.reportPlaybackProgress(info); } From 8b505bb84d63645321ca1a61d13dbebf57f9f822 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 29 Mar 2015 14:38:18 -0400 Subject: [PATCH 16/33] report live stream in playback stop --- dashboard-ui/scripts/mediacontroller.js | 10 +++++++--- dashboard-ui/scripts/mediaplayer.js | 10 ++-------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/dashboard-ui/scripts/mediacontroller.js b/dashboard-ui/scripts/mediacontroller.js index ab70725f5..c53fde76c 100644 --- a/dashboard-ui/scripts/mediacontroller.js +++ b/dashboard-ui/scripts/mediacontroller.js @@ -53,13 +53,17 @@ }).on('playbackstop.mediacontroller', function (e, state) { - ApiClient.reportPlaybackStopped({ - + var stopInfo = { itemId: state.NowPlayingItem.Id, mediaSourceId: state.PlayState.MediaSourceId, positionTicks: state.PlayState.PositionTicks + }; - }); + if (state.PlayState.LiveStreamId) { + stopInfo.LiveStreamId = state.PlayState.LiveStreamId; + } + + ApiClient.reportPlaybackStopped(stopInfo); }).on('positionchange.mediacontroller', function (e, state) { diff --git a/dashboard-ui/scripts/mediaplayer.js b/dashboard-ui/scripts/mediaplayer.js index 88c9e058c..bd3979f19 100644 --- a/dashboard-ui/scripts/mediaplayer.js +++ b/dashboard-ui/scripts/mediaplayer.js @@ -1390,6 +1390,8 @@ state.PlayState.PlayMethod = getParameterByName('static', currentSrc) == 'true' ? 'DirectStream' : 'Transcode'; + + state.PlayState.LiveStreamId = getParameterByName('LiveStreamId', currentSrc); } } @@ -1567,14 +1569,6 @@ info = $.extend(info, state.PlayState); - if (element) { - var currentSrc = element.currentSrc; - var liveStreamId = getParameterByName('LiveStreamId', currentSrc); - if (liveStreamId) { - info.LiveStreamId = liveStreamId; - } - } - ApiClient.reportPlaybackProgress(info); } From f2365aec0ea9115511da41722273830c13a9491a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 29 Mar 2015 18:38:32 -0400 Subject: [PATCH 17/33] sync updates --- dashboard-ui/scripts/mediaplayer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/dashboard-ui/scripts/mediaplayer.js b/dashboard-ui/scripts/mediaplayer.js index bd3979f19..846a96eb2 100644 --- a/dashboard-ui/scripts/mediaplayer.js +++ b/dashboard-ui/scripts/mediaplayer.js @@ -837,6 +837,7 @@ getLiveStream(item.Id, deviceProfile, startPosition, mediaSource, null, null).done(function (openLiveStreamResult) { + openLiveStreamResult.MediaSource.enableDirectPlay = supportsDirectPlay(openLiveStreamResult.MediaSource); playInternalPostMediaSourceSelection(item, openLiveStreamResult.MediaSource, startPosition, callback); }); From 74d6e3aaad65e5d0ca4e1bfc4c15410436fb1a8a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 29 Mar 2015 23:04:55 -0400 Subject: [PATCH 18/33] sync updates --- dashboard-ui/autoorganizelog.html | 2 +- dashboard-ui/mypreferenceswebclient.html | 1 + dashboard-ui/scripts/indexpage.js | 1 - dashboard-ui/scripts/librarybrowser.js | 4 ---- dashboard-ui/scripts/librarylist.js | 4 ---- dashboard-ui/scripts/mediaplayer.js | 1 + dashboard-ui/scripts/taskbutton.js | 2 +- 7 files changed, 4 insertions(+), 11 deletions(-) diff --git a/dashboard-ui/autoorganizelog.html b/dashboard-ui/autoorganizelog.html index 98fb24592..7d9ad10a1 100644 --- a/dashboard-ui/autoorganizelog.html +++ b/dashboard-ui/autoorganizelog.html @@ -18,8 +18,8 @@
    - diff --git a/dashboard-ui/mypreferenceswebclient.html b/dashboard-ui/mypreferenceswebclient.html index a66521b18..2373f7d92 100644 --- a/dashboard-ui/mypreferenceswebclient.html +++ b/dashboard-ui/mypreferenceswebclient.html @@ -121,6 +121,7 @@ +
    diff --git a/dashboard-ui/scripts/indexpage.js b/dashboard-ui/scripts/indexpage.js index 0d2bccb64..5baa1e687 100644 --- a/dashboard-ui/scripts/indexpage.js +++ b/dashboard-ui/scripts/indexpage.js @@ -125,7 +125,6 @@ Limit: 24, Fields: "PrimaryImageAspectRatio,SyncInfo", - IsPlayed: false, ImageTypeLimit: 1, EnableImageTypes: "Primary,Backdrop,Banner,Thumb" }; diff --git a/dashboard-ui/scripts/librarybrowser.js b/dashboard-ui/scripts/librarybrowser.js index 417922fc7..3704ff8aa 100644 --- a/dashboard-ui/scripts/librarybrowser.js +++ b/dashboard-ui/scripts/librarybrowser.js @@ -1257,10 +1257,6 @@ if (options.showChildCountIndicator && item.ChildCount) { cssClass += ' groupedCard'; - - if (item.Type == 'Series') { - cssClass += ' unplayedGroupings'; - } } if (options.showTitle && !options.overlayText) { diff --git a/dashboard-ui/scripts/librarylist.js b/dashboard-ui/scripts/librarylist.js index 28fe0ab5e..577ef9df9 100644 --- a/dashboard-ui/scripts/librarylist.js +++ b/dashboard-ui/scripts/librarylist.js @@ -512,10 +512,6 @@ GroupItems: false }; - if ($(card).hasClass('unplayedGroupings')) { - options.IsPlayed = false; - } - var promise2 = ApiClient.getJSON(ApiClient.getUrl('Users/' + userId + '/Items/Latest', options)); $.when(promise1, promise2).done(function (response1, response2) { diff --git a/dashboard-ui/scripts/mediaplayer.js b/dashboard-ui/scripts/mediaplayer.js index 846a96eb2..20ea889fb 100644 --- a/dashboard-ui/scripts/mediaplayer.js +++ b/dashboard-ui/scripts/mediaplayer.js @@ -84,6 +84,7 @@ options.push({ name: '480p - 420kbps', maxWidth: 720, bitrate: 420000 }); options.push({ name: '360p', maxWidth: 640, bitrate: 400000 }); options.push({ name: '240p', maxWidth: 426, bitrate: 320000 }); + options.push({ name: '144p', maxWidth: 256, bitrate: 192000 }); var i, length, option; var selectedIndex = -1; diff --git a/dashboard-ui/scripts/taskbutton.js b/dashboard-ui/scripts/taskbutton.js index 42308a944..5aa6cff11 100644 --- a/dashboard-ui/scripts/taskbutton.js +++ b/dashboard-ui/scripts/taskbutton.js @@ -113,7 +113,7 @@ $.fn.taskButton = function (options) { ApiClient.sendWebSocketMessage("ScheduledTasksInfoStop"); } - } else { + } else if (this.length) { this.on('click.taskbutton', function () { From 4ffd893f3ef74536f76425c9cbc465baf074ae76 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 30 Mar 2015 12:16:34 -0400 Subject: [PATCH 19/33] add setting to control transcodng throttle --- dashboard-ui/addplugin.html | 7 +- dashboard-ui/appservices.html | 52 +++++++++++ dashboard-ui/encodingsettings.html | 5 ++ dashboard-ui/livetvsettings.html | 1 + dashboard-ui/livetvstatus.html | 1 + dashboard-ui/scripts/addpluginpage.js | 17 +++- dashboard-ui/scripts/appservices.js | 110 +++++++++++++++++++++++ dashboard-ui/scripts/encodingsettings.js | 4 +- dashboard-ui/scripts/site.js | 7 +- dashboard-ui/scripts/syncservices.js | 66 -------------- dashboard-ui/syncactivity.html | 2 +- dashboard-ui/syncjob.html | 2 +- dashboard-ui/syncservices.html | 43 --------- dashboard-ui/syncsettings.html | 2 +- 14 files changed, 202 insertions(+), 117 deletions(-) create mode 100644 dashboard-ui/appservices.html create mode 100644 dashboard-ui/scripts/appservices.js delete mode 100644 dashboard-ui/scripts/syncservices.js delete mode 100644 dashboard-ui/syncservices.html diff --git a/dashboard-ui/addplugin.html b/dashboard-ui/addplugin.html index 856152dab..aa443c78e 100644 --- a/dashboard-ui/addplugin.html +++ b/dashboard-ui/addplugin.html @@ -15,9 +15,14 @@ +
    diff --git a/dashboard-ui/appservices.html b/dashboard-ui/appservices.html new file mode 100644 index 000000000..cbbe17611 --- /dev/null +++ b/dashboard-ui/appservices.html @@ -0,0 +1,52 @@ + + + + Emby + + +
    + + +
    + + diff --git a/dashboard-ui/encodingsettings.html b/dashboard-ui/encodingsettings.html index 9da0fc98e..aed1d773a 100644 --- a/dashboard-ui/encodingsettings.html +++ b/dashboard-ui/encodingsettings.html @@ -43,6 +43,11 @@
      +
    • + + +
      ${OptionEnableTranscodingThrottleHelp}
      +
    • diff --git a/dashboard-ui/livetvsettings.html b/dashboard-ui/livetvsettings.html index a3f7d070d..40a79c013 100644 --- a/dashboard-ui/livetvsettings.html +++ b/dashboard-ui/livetvsettings.html @@ -11,6 +11,7 @@ diff --git a/dashboard-ui/livetvstatus.html b/dashboard-ui/livetvstatus.html index 77e81a36a..d02f63f89 100644 --- a/dashboard-ui/livetvstatus.html +++ b/dashboard-ui/livetvstatus.html @@ -11,6 +11,7 @@ diff --git a/dashboard-ui/scripts/addpluginpage.js b/dashboard-ui/scripts/addpluginpage.js index fba9d4c6a..53dea364a 100644 --- a/dashboard-ui/scripts/addpluginpage.js +++ b/dashboard-ui/scripts/addpluginpage.js @@ -265,8 +265,11 @@ }); + }).on('pagebeforeshow pageinit', "#addPluginPage", function () { + // This needs both events for the helpurl to get done at the right time + var page = this; var context = getParameterByName('context'); @@ -274,12 +277,24 @@ if (context == 'sync') { $('.syncTabs', page).show(); $('.pluginTabs', page).hide(); + $('.livetvTabs', page).hide(); page.setAttribute('data-helpurl', 'https://github.com/MediaBrowser/Wiki/wiki/Sync'); Dashboard.setPageTitle(Globalize.translate('TitleSync')); - } else { + } + else if (context == 'livetv') { + + $('.syncTabs', page).hide(); + $('.pluginTabs', page).hide(); + $('.livetvTabs', page).show(); + + Dashboard.setPageTitle(Globalize.translate('TitleLiveTV')); + page.setAttribute('data-helpurl', 'https://github.com/MediaBrowser/Wiki/wiki/Live%20TV'); + } + else { $('.syncTabs', page).hide(); $('.pluginTabs', page).show(); + $('.livetvTabs', page).hide(); page.setAttribute('data-helpurl', 'https://github.com/MediaBrowser/Wiki/wiki/Plugins'); Dashboard.setPageTitle(Globalize.translate('TitlePlugins')); diff --git a/dashboard-ui/scripts/appservices.js b/dashboard-ui/scripts/appservices.js new file mode 100644 index 000000000..64a202971 --- /dev/null +++ b/dashboard-ui/scripts/appservices.js @@ -0,0 +1,110 @@ +(function ($, document) { + + function reloadList(page) { + + Dashboard.showLoadingMsg(); + + var promise1 = ApiClient.getAvailablePlugins({ + TargetSystems: 'Server' + }); + + var promise2 = ApiClient.getInstalledPlugins(); + + $.when(promise1, promise2).done(function (response1, response2) { + renderInstalled(page, response1[0], response2[0]); + renderCatalog(page, response1[0], response2[0]); + }); + } + + function getCategories() { + + var context = getParameterByName('context'); + + var categories = []; + + if (context == 'sync') { + categories.push('Sync'); + } + else if (context == 'livetv') { + categories.push('Live TV'); + } + + return categories; + } + + function renderInstalled(page, availablePlugins, installedPlugins) { + + var category = getCategories()[0]; + + installedPlugins = installedPlugins.filter(function (i) { + + var catalogEntry = availablePlugins.filter(function (a) { + return a.guid == i.Id; + })[0]; + + return catalogEntry && catalogEntry.category == category; + + }); + + PluginsPage.renderPlugins(page, installedPlugins); + } + + function renderCatalog(page, availablePlugins, installedPlugins) { + + var categories = getCategories(); + + PluginCatalog.renderCatalog({ + + catalogElement: $('.catalog', page), + availablePlugins: availablePlugins, + installedPlugins: installedPlugins, + categories: categories, + showCategory: false, + context: getParameterByName('context'), + targetSystem: 'Server' + }); + + } + + $(document).on('pagebeforeshow pageinit', "#appServicesPage", function () { + + // This needs both events for the helpurl to get done at the right time + + var page = this; + + var context = getParameterByName('context'); + + $('.sectionTabs', page).hide(); + $('.' + context + 'SectionTabs', page).show(); + + if (context == 'sync') { + Dashboard.setPageTitle(Globalize.translate('TitleSync')); + page.setAttribute('data-helpurl', 'https://github.com/MediaBrowser/Wiki/wiki/Sync'); + } + else if (context == 'livetv') { + Dashboard.setPageTitle(Globalize.translate('TitleLiveTV')); + page.setAttribute('data-helpurl', 'https://github.com/MediaBrowser/Wiki/wiki/Live%20TV'); + } + + }).on('pageshow', "#appServicesPage", function () { + + // This needs both events for the helpurl to get done at the right time + + var page = this; + + reloadList(page); + + var context = getParameterByName('context'); + + Dashboard.getPluginSecurityInfo().done(function (pluginSecurityInfo) { + + if (pluginSecurityInfo.IsMBSupporter || context != 'sync') { + $('.syncPromotion', page).hide(); + } else { + $('.syncPromotion', page).show(); + } + }); + + }); + +})(jQuery, document); \ No newline at end of file diff --git a/dashboard-ui/scripts/encodingsettings.js b/dashboard-ui/scripts/encodingsettings.js index 80b1063d5..fcd254884 100644 --- a/dashboard-ui/scripts/encodingsettings.js +++ b/dashboard-ui/scripts/encodingsettings.js @@ -3,7 +3,8 @@ function loadPage(page, config) { $('#chkEnableDebugEncodingLogging', page).checked(config.EnableDebugLogging).checkboxradio('refresh'); - + $('#chkEnableThrottle', page).checked(config.EnableThrottling).checkboxradio('refresh'); + $('.radioEncodingQuality', page).each(function() { this.checked = config.EncodingQuality == this.value; @@ -67,6 +68,7 @@ config.EncodingQuality = $('.radioEncodingQuality:checked', form).val(); config.DownMixAudioBoost = $('#txtDownMixAudioBoost', form).val(); config.TranscodingTempPath = $('#txtTranscodingTempPath', form).val(); + config.EnableThrottling = $('#chkEnableThrottle', form).checked(); ApiClient.updateNamedConfiguration("encoding", config).done(Dashboard.processServerConfigurationUpdateResult); }); diff --git a/dashboard-ui/scripts/site.js b/dashboard-ui/scripts/site.js index 739a699bd..705ddc620 100644 --- a/dashboard-ui/scripts/site.js +++ b/dashboard-ui/scripts/site.js @@ -756,6 +756,9 @@ var Dashboard = { var pageElem = page[0]; + var isServicesPage = page.hasClass('appServicesPage'); + var context = getParameterByName('context'); + return [{ name: Globalize.translate('TabServer'), href: "dashboard.html", @@ -793,7 +796,7 @@ var Dashboard = { }, { name: Globalize.translate('TabSync'), href: "syncactivity.html", - selected: page.hasClass('syncConfigurationPage'), + selected: page.hasClass('syncConfigurationPage') || (isServicesPage && context == 'sync'), icon: 'fa-cloud' }, { divider: true, @@ -813,7 +816,7 @@ var Dashboard = { }, { name: Globalize.translate('TabLiveTV'), href: "livetvstatus.html", - selected: page.hasClass("liveTvSettingsPage"), + selected: page.hasClass("liveTvSettingsPage") || (isServicesPage && context == 'livetv'), icon: 'fa-video-camera', color: '#293AAE' }, { diff --git a/dashboard-ui/scripts/syncservices.js b/dashboard-ui/scripts/syncservices.js deleted file mode 100644 index 9d67478c1..000000000 --- a/dashboard-ui/scripts/syncservices.js +++ /dev/null @@ -1,66 +0,0 @@ -(function ($, document) { - - function reloadList(page) { - - Dashboard.showLoadingMsg(); - - var promise1 = ApiClient.getAvailablePlugins({ - TargetSystems: 'Server' - }); - - var promise2 = ApiClient.getInstalledPlugins(); - - $.when(promise1, promise2).done(function (response1, response2) { - renderInstalled(page, response1[0], response2[0]); - renderCatalog(page, response1[0], response2[0]); - }); - } - - function renderInstalled(page, availablePlugins, installedPlugins) { - - installedPlugins = installedPlugins.filter(function (i) { - - var catalogEntry = availablePlugins.filter(function (a) { - return a.guid == i.Id; - })[0]; - - return catalogEntry && catalogEntry.category == 'Sync'; - - }); - - PluginsPage.renderPlugins(page, installedPlugins); - } - - function renderCatalog(page, availablePlugins, installedPlugins) { - - PluginCatalog.renderCatalog({ - - catalogElement: $('.catalog', page), - availablePlugins: availablePlugins, - installedPlugins: installedPlugins, - categories: ['Sync'], - showCategory: false, - context: 'sync', - targetSystem: 'Server' - }); - - } - - $(document).on('pageshow', "#syncServicesPage", function () { - - var page = this; - - reloadList(page); - - Dashboard.getPluginSecurityInfo().done(function (pluginSecurityInfo) { - - if (pluginSecurityInfo.IsMBSupporter) { - $('.syncPromotion', page).hide(); - } else { - $('.syncPromotion', page).show(); - } - }); - - }); - -})(jQuery, document); \ No newline at end of file diff --git a/dashboard-ui/syncactivity.html b/dashboard-ui/syncactivity.html index 16726d34e..179fa9958 100644 --- a/dashboard-ui/syncactivity.html +++ b/dashboard-ui/syncactivity.html @@ -11,7 +11,7 @@ diff --git a/dashboard-ui/syncjob.html b/dashboard-ui/syncjob.html index b7efb9502..014ee76d6 100644 --- a/dashboard-ui/syncjob.html +++ b/dashboard-ui/syncjob.html @@ -11,7 +11,7 @@ diff --git a/dashboard-ui/syncservices.html b/dashboard-ui/syncservices.html deleted file mode 100644 index 4ed3d7268..000000000 --- a/dashboard-ui/syncservices.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - ${TitleSync} - - -
      - -
      - -
      -
      - - diff --git a/dashboard-ui/syncsettings.html b/dashboard-ui/syncsettings.html index fe111383e..3ff152dab 100644 --- a/dashboard-ui/syncsettings.html +++ b/dashboard-ui/syncsettings.html @@ -11,7 +11,7 @@ From e4e3ca4c5c872be6b9bc631f596223348abc422a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 30 Mar 2015 15:57:37 -0400 Subject: [PATCH 20/33] sync updates --- dashboard-ui/scripts/addpluginpage.js | 2 +- dashboard-ui/scripts/appservices.js | 2 +- dashboard-ui/scripts/mediaplayer-video.js | 37 ++++++++--------------- 3 files changed, 15 insertions(+), 26 deletions(-) diff --git a/dashboard-ui/scripts/addpluginpage.js b/dashboard-ui/scripts/addpluginpage.js index 53dea364a..0ef2e7be7 100644 --- a/dashboard-ui/scripts/addpluginpage.js +++ b/dashboard-ui/scripts/addpluginpage.js @@ -266,7 +266,7 @@ }); - }).on('pagebeforeshow pageinit', "#addPluginPage", function () { + }).on('pagebeforeshow pageinit pageshow', "#addPluginPage", function () { // This needs both events for the helpurl to get done at the right time diff --git a/dashboard-ui/scripts/appservices.js b/dashboard-ui/scripts/appservices.js index 64a202971..636f41845 100644 --- a/dashboard-ui/scripts/appservices.js +++ b/dashboard-ui/scripts/appservices.js @@ -66,7 +66,7 @@ } - $(document).on('pagebeforeshow pageinit', "#appServicesPage", function () { + $(document).on('pagebeforeshow pageinit pageshow', "#appServicesPage", function () { // This needs both events for the helpurl to get done at the right time diff --git a/dashboard-ui/scripts/mediaplayer-video.js b/dashboard-ui/scripts/mediaplayer-video.js index 7eb57641a..aaf9bce8f 100644 --- a/dashboard-ui/scripts/mediaplayer-video.js +++ b/dashboard-ui/scripts/mediaplayer-video.js @@ -143,10 +143,6 @@ self.changeStream(self.getCurrentTicks(), { AudioStreamIndex: index }); }; - self.supportsSubtitleStreamExternally = function (stream) { - return stream.Type == 'Subtitle' && stream.IsTextSubtitleStream && stream.SupportsExternalStream; - } - self.setSubtitleStreamIndex = function (index) { if (!self.supportsTextTracks()) { @@ -166,7 +162,7 @@ if (currentStream && !newStream) { - if (!self.supportsSubtitleStreamExternally(currentStream)) { + if (currentStream.DeliveryMethod != 'External') { // Need to change the transcoded stream to remove subs self.changeStream(self.getCurrentTicks(), { SubtitleStreamIndex: -1 }); @@ -174,7 +170,7 @@ } else if (!currentStream && newStream) { - if (self.supportsSubtitleStreamExternally(newStream)) { + if (newStream.DeliveryMethod == 'External') { selectedTrackElementIndex = index; } else { @@ -184,10 +180,10 @@ } else if (currentStream && newStream) { - if (self.supportsSubtitleStreamExternally(newStream)) { + if (newStream.DeliveryMethod == 'External') { selectedTrackElementIndex = index; - if (!self.supportsSubtitleStreamExternally(currentStream)) { + if (currentStream.DeliveryMethod != 'External') { self.changeStream(self.getCurrentTicks(), { SubtitleStreamIndex: -1 }); } } else { @@ -207,7 +203,7 @@ var modes = ['disabled', 'showing', 'hidden']; var textStreams = self.currentMediaSource.MediaStreams.filter(function (s) { - return self.supportsSubtitleStreamExternally(s); + return s.DeliveryMethod == 'External'; }); var newStream = textStreams.filter(function (s) { @@ -963,25 +959,18 @@ html += ''; - if (self.supportsTextTracks()) { - var textStreams = subtitleStreams.filter(function (s) { - return self.supportsSubtitleStreamExternally(s); - }); + var textStreams = subtitleStreams.filter(function (s) { + return s.DeliveryMethod == 'External'; + }); - for (var i = 0, length = textStreams.length; i < length; i++) { + for (var i = 0, length = textStreams.length; i < length; i++) { - var textStream = textStreams[i]; - var textStreamUrl = mediaSource.Protocol == 'Http' ? - textStream.Path : - ApiClient.getUrl('Videos/' + item.Id + '/' + mediaSource.Id + '/Subtitles/' + textStream.Index + '/Stream.vtt', { - startPositionTicks: (startPosition || 0), - api_key: ApiClient.accessToken() - }); + var textStream = textStreams[i]; + var textStreamUrl = textStream.DeliveryUrl; - var defaultAttribute = textStream.Index == mediaSource.DefaultSubtitleStreamIndex ? ' default' : ''; + var defaultAttribute = textStream.Index == mediaSource.DefaultSubtitleStreamIndex ? ' default' : ''; - html += ''; - } + html += ''; } html += ''; From 69083dde3b7ff9c6556c71fee99ab1eb6e87e910 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 31 Mar 2015 12:24:16 -0400 Subject: [PATCH 21/33] sync updates --- dashboard-ui/mypreferencesdisplay.html | 6 ++++++ dashboard-ui/scripts/mediaplayer-video.js | 5 ++--- dashboard-ui/scripts/mediaplayer.js | 14 +++++++++----- dashboard-ui/scripts/mypreferencesdisplay.js | 4 ++++ 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/dashboard-ui/mypreferencesdisplay.html b/dashboard-ui/mypreferencesdisplay.html index 17c7f6eb1..95327ee86 100644 --- a/dashboard-ui/mypreferencesdisplay.html +++ b/dashboard-ui/mypreferencesdisplay.html @@ -76,6 +76,12 @@
      + +
      +
      + + +
    diff --git a/dashboard-ui/scripts/mediaplayer-video.js b/dashboard-ui/scripts/mediaplayer-video.js index aaf9bce8f..0370061fc 100644 --- a/dashboard-ui/scripts/mediaplayer-video.js +++ b/dashboard-ui/scripts/mediaplayer-video.js @@ -950,11 +950,11 @@ // Can't autoplay in these browsers so we need to use the full controls if (requiresNativeControls) { - html += '
  • '; itemHtml += ''; - itemHtml += '

    ' + a.DayOfWeek + '

    '; + itemHtml += '

    ' + Globalize.translate('Option' + a.DayOfWeek) + '

    '; itemHtml += '

    ' + getDisplayTime(a.StartHour) + ' - ' + getDisplayTime(a.EndHour) + '

    '; itemHtml += '
    '; diff --git a/dashboard-ui/syncactivity.html b/dashboard-ui/syncactivity.html index 179fa9958..1b2f90b4b 100644 --- a/dashboard-ui/syncactivity.html +++ b/dashboard-ui/syncactivity.html @@ -20,7 +20,7 @@
    - diff --git a/dashboard-ui/scripts/livetvitems.js b/dashboard-ui/scripts/livetvitems.js index 4dfbec203..6639d3735 100644 --- a/dashboard-ui/scripts/livetvitems.js +++ b/dashboard-ui/scripts/livetvitems.js @@ -8,7 +8,7 @@ // The base query options var query = { UserId: Dashboard.getCurrentUserId(), - SortBy: "PremiereDate,SortName", + SortBy: "StartDate,SortName", SortOrder: "Ascending", StartIndex: 0 }; @@ -19,19 +19,6 @@ function updateFilterControls(page) { - // Reset form values using the last used query - $('.radioSortBy', page).each(function () { - - this.checked = (query.SortBy || '').toLowerCase() == this.getAttribute('data-sortby').toLowerCase(); - - }).checkboxradio('refresh'); - - $('.radioSortOrder', page).each(function () { - - this.checked = (query.SortOrder || '').toLowerCase() == this.getAttribute('data-sortorder').toLowerCase(); - - }).checkboxradio('refresh'); - $('#selectView', page).val(view).selectmenu('refresh'); $('.alphabetPicker', page).alphaValue(query.NameStartsWithOrGreater); $('#selectPageSize', page).val(query.Limit).selectmenu('refresh'); @@ -58,7 +45,6 @@ $('.listTopPaging', page).html(pagingHtml).trigger('create'); updateFilterControls(page); - var trigger = false; if (view == "Poster") { html = LibraryBrowser.getPosterViewHtml({ @@ -112,18 +98,6 @@ var page = this; - $('.radioSortBy', this).on('click', function () { - query.StartIndex = 0; - query.SortBy = this.getAttribute('data-sortby'); - reloadItems(page); - }); - - $('.radioSortOrder', this).on('click', function () { - query.StartIndex = 0; - query.SortOrder = this.getAttribute('data-sortorder'); - reloadItems(page); - }); - $('#selectView', this).on('change', function () { view = this.value; @@ -179,6 +153,7 @@ } query.IsMovie = getParameterByName('type') == 'movies' ? true : null; + query.IsSports = getParameterByName('type') == 'sports' ? true : null; var viewkey = getSavedQueryKey(); diff --git a/dashboard-ui/scripts/livetvsuggested.js b/dashboard-ui/scripts/livetvsuggested.js index 827b2f04a..bacf8dd0a 100644 --- a/dashboard-ui/scripts/livetvsuggested.js +++ b/dashboard-ui/scripts/livetvsuggested.js @@ -33,7 +33,8 @@ IsAiring: false, HasAired: false, limit: 10, - IsMovie: false + IsMovie: false, + IsSports: false }).done(function (result) { @@ -73,6 +74,28 @@ $('.upcomingTvMovieItems', page).html(html).lazyChildren(); }); + + ApiClient.getLiveTvRecommendedPrograms({ + + userId: Dashboard.getCurrentUserId(), + IsAiring: false, + HasAired: false, + limit: 10, + IsSports: true + + }).done(function (result) { + + var html = LibraryBrowser.getPosterViewHtml({ + items: result.Items, + shape: "auto", + showTitle: true, + coverImage: true, + overlayText: false, + lazy: true + }); + + $('.upcomingSportsItems', page).html(html).lazyChildren(); + }); } $(document).on('pagebeforeshow', "#liveTvSuggestedPage", function () { From bb0a406de8ca1554cce3343b54c53f9c94d54d83 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 3 Apr 2015 12:58:12 -0400 Subject: [PATCH 33/33] update images --- dashboard-ui/moviestudios.html | 2 +- dashboard-ui/tvstudios.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dashboard-ui/moviestudios.html b/dashboard-ui/moviestudios.html index 4a768c41c..aa1a62f1b 100644 --- a/dashboard-ui/moviestudios.html +++ b/dashboard-ui/moviestudios.html @@ -21,7 +21,7 @@
    -
    +
    diff --git a/dashboard-ui/tvstudios.html b/dashboard-ui/tvstudios.html index 54bb4b90e..87b2b765f 100644 --- a/dashboard-ui/tvstudios.html +++ b/dashboard-ui/tvstudios.html @@ -20,7 +20,7 @@
    -
    +