diff --git a/dashboard-ui/css/librarybrowser.css b/dashboard-ui/css/librarybrowser.css index 1ebe93d09..cef8cb388 100644 --- a/dashboard-ui/css/librarybrowser.css +++ b/dashboard-ui/css/librarybrowser.css @@ -676,14 +676,14 @@ a.itemTag:hover { } } -@media all and (min-width: 800px) { +@media all and (min-width: 880px) { .libraryMenuButton { display: none; } } -@media all and (max-width: 800px) { +@media all and (max-width: 880px) { .desktopHomeLink { display: none; diff --git a/dashboard-ui/css/mediaplayer-video.css b/dashboard-ui/css/mediaplayer-video.css index 10fc04fea..951f6213b 100644 --- a/dashboard-ui/css/mediaplayer-video.css +++ b/dashboard-ui/css/mediaplayer-video.css @@ -165,7 +165,7 @@ /****************************************/ @media all and (max-width: 1200px), all and (max-height: 720px) { - #mediaPlayer .chaptersButton, #mediaPlayer .audioTracksButton, #mediaPlayer .sendMediaButton { + #mediaPlayer .chaptersButton, #mediaPlayer .audioTracksButton { display: none!important; } @@ -179,7 +179,7 @@ } @media all and (max-width: 960px), all and (max-height: 550px) { - #mediaPlayer .nowPlayingBarImage, #mediaPlayer .qualityButton, #mediaPlayer .audioTracksButton, #mediaPlayer .chaptersButton, #mediaPlayer .sendMediaButton { + #mediaPlayer .nowPlayingBarImage, #mediaPlayer .qualityButton, #mediaPlayer .audioTracksButton, #mediaPlayer .chaptersButton { display: none!important; } @@ -193,7 +193,7 @@ } @media all and (max-width: 800px), all and (max-height: 460px) { - #mediaPlayer .muteButton, #mediaPlayer .unmuteButton, #mediaPlayer .nowPlayingMediaInfo, #mediaPlayer .sendMediaButton { + #mediaPlayer .muteButton, #mediaPlayer .unmuteButton, #mediaPlayer .nowPlayingMediaInfo { display: none!important; } diff --git a/dashboard-ui/css/mediaplayer.css b/dashboard-ui/css/mediaplayer.css index d37ae0230..4affbc40c 100644 --- a/dashboard-ui/css/mediaplayer.css +++ b/dashboard-ui/css/mediaplayer.css @@ -135,7 +135,7 @@ input[type="range"]::-ms-fill-upper { } @media all and (max-width: 600px) { - .chaptersButton, .audioTracksButton, .sendMediaButton { + .chaptersButton, .audioTracksButton { display: none!important; } diff --git a/dashboard-ui/dlnaprofile.html b/dashboard-ui/dlnaprofile.html index 393692135..274977b65 100644 --- a/dashboard-ui/dlnaprofile.html +++ b/dashboard-ui/dlnaprofile.html @@ -120,11 +120,13 @@
-

Add direct play profiles to indicate what formats the device can handle natively.

+

Add direct play profiles to indicate which formats the device can handle natively.

+ +
-

Add transcoding profiles to indicate what formats should be used when transcoding is required.

+

Add transcoding profiles to indicate which formats should be used when transcoding is required.

@@ -155,8 +157,57 @@
+ diff --git a/dashboard-ui/itembynamedetails.html b/dashboard-ui/itembynamedetails.html index 004e62275..ac2fa1190 100644 --- a/dashboard-ui/itembynamedetails.html +++ b/dashboard-ui/itembynamedetails.html @@ -145,9 +145,6 @@ - - - diff --git a/dashboard-ui/itemdetails.html b/dashboard-ui/itemdetails.html index 8ebed7875..e341ee3ac 100644 --- a/dashboard-ui/itemdetails.html +++ b/dashboard-ui/itemdetails.html @@ -131,9 +131,6 @@ - diff --git a/dashboard-ui/livetvchannel.html b/dashboard-ui/livetvchannel.html index 426a0b3ee..52abc9296 100644 --- a/dashboard-ui/livetvchannel.html +++ b/dashboard-ui/livetvchannel.html @@ -30,9 +30,6 @@ - - - diff --git a/dashboard-ui/livetvprogram.html b/dashboard-ui/livetvprogram.html index 28daefb57..531ac3a5a 100644 --- a/dashboard-ui/livetvprogram.html +++ b/dashboard-ui/livetvprogram.html @@ -47,9 +47,6 @@ - - -
diff --git a/dashboard-ui/livetvrecording.html b/dashboard-ui/livetvrecording.html index a1375e3d2..7e35119e9 100644 --- a/dashboard-ui/livetvrecording.html +++ b/dashboard-ui/livetvrecording.html @@ -41,9 +41,6 @@ - - - diff --git a/dashboard-ui/scripts/chromecast.js b/dashboard-ui/scripts/chromecast.js index f9b201b3e..c72929ae1 100644 --- a/dashboard-ui/scripts/chromecast.js +++ b/dashboard-ui/scripts/chromecast.js @@ -118,8 +118,7 @@ * Generic error callback function */ CastPlayer.prototype.onError = function () { - console.log("error"); - $('.btnCast').hide(); + console.log("chromecast error"); }; /** @@ -147,13 +146,11 @@ */ CastPlayer.prototype.receiverListener = function (e) { if (e === 'available') { - console.log("receiver found"); - $('.btnCast').show(); + console.log("chromecast receiver found"); this.hasReceivers = true; } else { - console.log("receiver list empty"); - $('.btnCast').hide(); + console.log("chromecast receiver list empty"); this.hasReceivers = false; } }; @@ -686,7 +683,7 @@ } else { } - $('.btnCast').attr('title', this.castPlayerState + " on " + this.session.receiver.friendlyName); + // this.session.receiver.friendlyName }; /** @@ -695,19 +692,15 @@ CastPlayer.prototype.updateMediaControlUI = function () { if (!chrome || !chrome.cast) { - $('.btnCast').hide(); return; } if (this.hasReceivers) { - $('.btnCast').show(); } if (this.deviceState == DEVICE_STATE.ACTIVE) { - $('.btnCast').removeClass('btnDefaultCast').addClass('btnActiveCast'); var playerState = this.castPlayerState; } else { - $('.btnCast').removeClass('btnActiveCast').addClass('btnDefaultCast'); var playerState = this.localPlayerState; } @@ -739,15 +732,6 @@ castPlayer.updateMediaControlUI(); - $('.btnCast', page).on('click', function () { - - if (castPlayer.deviceState == DEVICE_STATE.ACTIVE) { - castPlayer.stopApp(); - } else { - castPlayer.launchApp(); - } - }); - }); })(window, window.chrome, console); \ No newline at end of file diff --git a/dashboard-ui/scripts/dlnaprofile.js b/dashboard-ui/scripts/dlnaprofile.js index 8ad019457..2704172ef 100644 --- a/dashboard-ui/scripts/dlnaprofile.js +++ b/dashboard-ui/scripts/dlnaprofile.js @@ -2,6 +2,9 @@ var currentProfile; + var currentSubProfile; + var isSubProfileNew; + function loadProfile(page) { Dashboard.showLoadingMsg(); @@ -60,6 +63,11 @@ profile.CodecProfiles = (profile.CodecProfiles || []); profile.MediaProfiles = (profile.MediaProfiles || []); + renderSubProfiles(page, profile); + } + + function renderSubProfiles(page, profile) { + renderDirectPlayProfiles(page, profile.DirectPlayProfiles); renderTranscodingProfiles(page, profile.TranscodingProfiles); renderContainerProfiles(page, profile.ContainerProfiles); @@ -67,6 +75,39 @@ renderMediaProfiles(page, profile.MediaProfiles); } + function editDirectPlayProfile(page, directPlayProfile) { + + isSubProfileNew = directPlayProfile == null; + directPlayProfile = directPlayProfile || {}; + currentSubProfile = directPlayProfile; + + var popup = $('#popupEditDirectPlayProfile', page).popup('open'); + + $('#selectDirectPlayProfileType', popup).val(directPlayProfile.Type || 'Video').selectmenu('refresh').trigger('change'); + $('#txtDirectPlayContainer', popup).val(directPlayProfile.Container || ''); + $('#txtDirectPlayAudioCodec', popup).val(directPlayProfile.AudioCodec || ''); + $('#txtDirectPlayVideoCodec', popup).val(directPlayProfile.VideoCodec || ''); + } + + function saveDirectPlayProfile(page) { + + currentSubProfile.Type = $('#selectDirectPlayProfileType', page).val(); + currentSubProfile.Container = $('#txtDirectPlayContainer', page).val(); + currentSubProfile.AudioCodec = $('#txtDirectPlayAudioCodec', page).val(); + currentSubProfile.VideoCodec = $('#txtDirectPlayVideoCodec', page).val(); + + if (isSubProfileNew) { + + currentProfile.DirectPlayProfiles.push(currentSubProfile); + } + + renderSubProfiles(page, currentProfile); + + currentSubProfile = null; + + $('#popupEditDirectPlayProfile', page).popup('close'); + } + function renderDirectPlayProfiles(page, profiles) { var html = ''; @@ -86,7 +127,7 @@ } html += '
  • '; - html += ''; + html += ''; html += '

    Container: ' + (profile.Container || 'All') + '

    '; @@ -101,7 +142,7 @@ html += '
    '; - html += 'Delete'; + html += 'Delete'; html += '
  • '; } @@ -112,9 +153,16 @@ $('.btnDeleteProfile', elem).on('click', function () { - var index = this.getAttribute('data-profileIndex'); + var index = this.getAttribute('data-profileindex'); deleteDirectPlayProfile(page, index); }); + + $('.lnkEditSubProfile', elem).on('click', function () { + + var index = parseInt(this.getAttribute('data-profileindex')); + + editDirectPlayProfile(page, currentProfile.DirectPlayProfiles[index]); + }); } function deleteDirectPlayProfile(page, index) { @@ -160,7 +208,7 @@ html += ''; - html += 'Delete'; + html += 'Delete'; html += ''; } @@ -171,7 +219,7 @@ $('.btnDeleteProfile', elem).on('click', function () { - var index = this.getAttribute('data-profileIndex'); + var index = this.getAttribute('data-profileindex'); deleteTranscodingProfile(page, index); }); } @@ -218,7 +266,7 @@ html += ''; - html += 'Delete'; + html += 'Delete'; html += ''; } @@ -229,7 +277,7 @@ $('.btnDeleteProfile', elem).on('click', function () { - var index = this.getAttribute('data-profileIndex'); + var index = this.getAttribute('data-profileindex'); deleteContainerProfile(page, index); }); } @@ -278,7 +326,7 @@ html += ''; - html += 'Delete'; + html += 'Delete'; html += ''; } @@ -289,7 +337,7 @@ $('.btnDeleteProfile', elem).on('click', function () { - var index = this.getAttribute('data-profileIndex'); + var index = this.getAttribute('data-profileindex'); deleteCodecProfile(page, index); }); } @@ -345,7 +393,7 @@ html += ''; - html += 'Delete'; + html += 'Delete'; html += ''; } @@ -356,7 +404,7 @@ $('.btnDeleteProfile', elem).on('click', function () { - var index = this.getAttribute('data-profileIndex'); + var index = this.getAttribute('data-profileindex'); deleteMediaProfile(page, index); }); } @@ -440,6 +488,28 @@ }); + $('#selectDirectPlayProfileType', page).on('change', function () { + + if (this.value == 'Video') { + $('#fldDirectPlayVideoCodec', page).show(); + } else { + $('#fldDirectPlayVideoCodec', page).hide(); + } + + if (this.value == 'Photo') { + $('#fldDirectPlayAudioCodec', page).hide(); + } else { + $('#fldDirectPlayAudioCodec', page).show(); + } + + }); + + $('.btnAddDirectPlayProfile', page).on('click', function () { + + editDirectPlayProfile(page); + + }); + }).on('pageshow', "#dlnaProfilePage", function () { var page = this; @@ -466,6 +536,16 @@ saveProfile(page, currentProfile); + return false; + }, + + onDirectPlayFormSubmit: function () { + + var form = this; + var page = $(form).parents('.page'); + + saveDirectPlayProfile(page); + return false; } }; diff --git a/dashboard-ui/scripts/itembynamedetailpage.js b/dashboard-ui/scripts/itembynamedetailpage.js index b1d7b4901..7852a86d3 100644 --- a/dashboard-ui/scripts/itembynamedetailpage.js +++ b/dashboard-ui/scripts/itembynamedetailpage.js @@ -81,7 +81,7 @@ Dashboard.getCurrentUser().done(function (user) { - if (MediaPlayer.canPlay(item, user)) { + if (MediaController.canPlay(item)) { $('#playButtonContainer', page).show(); } else { $('#playButtonContainer', page).hide(); @@ -518,12 +518,7 @@ $('#btnPlay', page).on('click', function () { var userdata = currentItem.UserData || {}; - LibraryBrowser.showPlayMenu(this, currentItem.Name, currentItem.Type, "Audio", userdata.PlaybackPositionTicks); - }); - - $('#btnRemote', page).on('click', function () { - - RemoteControl.showMenuForItem({ item: currentItem, context: getParameterByName('context') || '' }); + LibraryBrowser.showPlayMenu(this, currentItem.Id, currentItem.Type, false, "Audio", userdata.PlaybackPositionTicks); }); }).on('pageshow', "#itemByNameDetailPage", function () { diff --git a/dashboard-ui/scripts/itemdetailpage.js b/dashboard-ui/scripts/itemdetailpage.js index cc95f465a..50b0ec2a2 100644 --- a/dashboard-ui/scripts/itemdetailpage.js +++ b/dashboard-ui/scripts/itemdetailpage.js @@ -29,8 +29,6 @@ renderDetails(page, item, context); LibraryBrowser.renderDetailPageBackdrop(page, item); - $("#remoteButtonContainer", page).show(); - if (user.Configuration.IsAdministrator) { $('#editButtonContainer', page).show(); @@ -38,21 +36,18 @@ $('#editButtonContainer', page).hide(); } - if (MediaPlayer.canPlay(item, user)) { + var externalPlayUrl = getExternalPlayUrl(item); + $('#btnPlayExternal', page).attr('href', externalPlayUrl || '#'); - var url = MediaPlayer.getPlayUrl(item); - - if (url) { - $('#playExternalButtonContainer', page).show(); - $('#playButtonContainer', page).hide(); - } else { - $('#playButtonContainer', page).show(); - $('#playExternalButtonContainer', page).hide(); - } - - $('#btnPlayExternal', page).attr('href', url || '#'); - - } else { + if (externalPlayUrl) { + $('#playExternalButtonContainer', page).show(); + $('#playButtonContainer', page).hide(); + } + else if (MediaController.canPlay(item)) { + $('#playButtonContainer', page).show(); + $('#playExternalButtonContainer', page).hide(); + } + else { $('#playButtonContainer', page).hide(); $('#playExternalButtonContainer', page).hide(); } @@ -124,6 +119,22 @@ $('#btnEdit', page).attr('href', "edititemmetadata.html?id=" + id); } + function getExternalPlayUrl(item) { + + + if (item.GameSystem == "Nintendo" && item.MediaType == "Game" && item.ProviderIds.NesBox && item.ProviderIds.NesBoxRom) { + + return "http://nesbox.com/game/" + item.ProviderIds.NesBox + '/rom/' + item.ProviderIds.NesBoxRom; + } + + if (item.GameSystem == "Super Nintendo" && item.MediaType == "Game" && item.ProviderIds.NesBox && item.ProviderIds.NesBoxRom) { + + return "http://snesbox.com/game/" + item.ProviderIds.NesBox + '/rom/' + item.ProviderIds.NesBoxRom; + } + + return null; + }; + function setPeopleHeader(page, item) { if (item.Type == "Audio" || item.Type == "MusicAlbum" || item.MediaType == "Book" || item.MediaType == "Photo") { @@ -1107,7 +1118,7 @@ attributes.push(createAttribute("Layout", stream.ChannelLayout)); } else if (stream.Channels) { - attributes.push(createAttribute("Channels", stream.Channels + ' ch')); + attributes.push(createAttribute("Channels", stream.Channels + ' ch')); } if (stream.BitRate && stream.Codec != "mjpeg") { @@ -1138,7 +1149,7 @@ if (version.Path) { html += '
    Path' + version.Path + ''; } - + return html; } @@ -1162,7 +1173,7 @@ var href = "itemdetails.html?id=" + item.Id; - var onclick = item.PlayAccess == 'Full' ? ' onclick="MediaPlayer.playById(\'' + item.Id + '\'); return false;"' : ""; + var onclick = item.PlayAccess == 'Full' ? ' onclick="MediaController.play(\'' + item.Id + '\'); return false;"' : ""; html += ''; @@ -1286,7 +1297,10 @@ function play(startPosition) { - MediaPlayer.play([currentItem], startPosition); + MediaController.play({ + items: [currentItem], + startPositionTicks: startPosition + }); } function splitVersions(page) { @@ -1317,7 +1331,7 @@ ApiClient.getLocalTrailers(Dashboard.getCurrentUserId(), currentItem.Id).done(function (trailers) { - MediaPlayer.play(trailers); + MediaController.play({ items: trailers }); }); } @@ -1335,7 +1349,7 @@ mediaType = "Audio"; } - LibraryBrowser.showPlayMenu(this, currentItem.Id, currentItem.Type, mediaType, userdata.PlaybackPositionTicks); + LibraryBrowser.showPlayMenu(this, currentItem.Id, currentItem.Type, currentItem.IsFolder, mediaType, userdata.PlaybackPositionTicks); }); $('#btnPlayTrailer', page).on('click', function () { @@ -1347,19 +1361,6 @@ ApiClient.markPlayed(Dashboard.getCurrentUserId(), currentItem.Id, new Date()); }); - $('#btnRemote', page).on('click', function () { - - RemoteControl.showMenuForItem({ - - item: currentItem, - context: getContext(currentItem), - - themeSongs: $('#themeSongsCollapsible:visible', page).length > 0, - - themeVideos: $('#themeVideosCollapsible:visible', page).length > 0 - }); - }); - $('.btnSplitVersions', page).on('click', function () { splitVersions(page); diff --git a/dashboard-ui/scripts/librarybrowser.js b/dashboard-ui/scripts/librarybrowser.js index 91b3369f8..9a29a6507 100644 --- a/dashboard-ui/scripts/librarybrowser.js +++ b/dashboard-ui/scripts/librarybrowser.js @@ -211,7 +211,7 @@ html += ''; html += ''; - html += ''; + html += ''; html += ''; var num = item.IndexNumber; @@ -287,12 +287,10 @@ return html; }, - showPlayMenu: function (positionTo, itemId, itemType, mediaType, resumePositionTicks) { + showPlayMenu: function (positionTo, itemId, itemType, isFolder, mediaType, resumePositionTicks) { - var isPlaying = MediaPlayer.isPlaying(); - - if (!isPlaying && !resumePositionTicks && mediaType != "Audio") { - MediaPlayer.playById(itemId); + if (!resumePositionTicks && mediaType != "Audio" && !isFolder) { + MediaController.play(itemId); return; } @@ -303,38 +301,22 @@ html += ''; diff --git a/dashboard-ui/scripts/librarylist.js b/dashboard-ui/scripts/librarylist.js index 23488ac7a..5fab7b43c 100644 --- a/dashboard-ui/scripts/librarylist.js +++ b/dashboard-ui/scripts/librarylist.js @@ -102,16 +102,16 @@ var buttonCount = 0; - if (MediaPlayer.canPlay(item, currentUser)) { + if (MediaController.canPlay(item)) { var resumePosition = (item.UserData || {}).PlaybackPositionTicks || 0; - var onPlayClick = 'LibraryBrowser.showPlayMenu(this, \'' + item.Id + '\', \'' + item.Type + '\', \'' + item.MediaType + '\', ' + resumePosition + ');return false;'; + var onPlayClick = 'LibraryBrowser.showPlayMenu(this, \'' + item.Id + '\', \'' + item.Type + '\', ' + item.IsFolder + ', \'' + item.MediaType + '\', ' + resumePosition + ');return false;'; html += ''; buttonCount++; if (item.MediaType == "Audio" || item.Type == "MusicAlbum") { - html += ''; + html += ''; buttonCount++; } } @@ -126,10 +126,6 @@ buttonCount++; } - if (!isPortrait || buttonCount < 3) { - html += ''; - } - html += '
    '; html += '
    '; @@ -142,22 +138,7 @@ var id = this.getAttribute('data-itemid'); ApiClient.getLocalTrailers(Dashboard.getCurrentUserId(), id).done(function (trailers) { - MediaPlayer.play(trailers); - }); - - return false; - } - - function onRemoteControlButtonClick() { - - var id = this.getAttribute('data-itemid'); - - ApiClient.getItem(Dashboard.getCurrentUserId(), id).done(function (item) { - - RemoteControl.showMenuForItem({ - item: item - }); - + MediaController.play({ items: trailers }); }); return false; @@ -248,7 +229,6 @@ innerElem.html(getOverlayHtml(item, user, elem)).trigger('create'); $('.btnPlayTrailer', innerElem).on('click', onTrailerButtonClick); - $('.btnRemoteControl', innerElem).on('click', onRemoteControlButtonClick); }); innerElem.show().each(function () { diff --git a/dashboard-ui/scripts/librarymenu.js b/dashboard-ui/scripts/librarymenu.js index 98e7c2db1..314107964 100644 --- a/dashboard-ui/scripts/librarymenu.js +++ b/dashboard-ui/scripts/librarymenu.js @@ -24,7 +24,7 @@ html += '
    '; - html += ''; + html += ''; html += ''; @@ -174,6 +174,20 @@ window.LibraryMenu = { showLibraryMenu: showLibraryMenu }; + + function updateCastIcon() { + + var info = MediaController.getPlayerInfo(); + + if (info.isLocalPlayer) { + + $('.btnCast').addClass('btnDefaultCast').removeClass('btnActiveCast'); + + } else { + + $('.btnCast').removeClass('btnDefaultCast').addClass('btnActiveCast'); + } + } $(document).on('pageinit', ".libraryPage", function () { @@ -210,6 +224,9 @@ }); }); } + + updateCastIcon(); + }).on('pageshow', ".libraryPage", function () { var page = this; @@ -224,4 +241,13 @@ } }); + $(function() { + + $(MediaController).on('playerchange', function () { + updateCastIcon(); + }); + + }); + + })(window, document, jQuery); \ No newline at end of file diff --git a/dashboard-ui/scripts/livetvchannel.js b/dashboard-ui/scripts/livetvchannel.js index b76c89698..12b93a7c9 100644 --- a/dashboard-ui/scripts/livetvchannel.js +++ b/dashboard-ui/scripts/livetvchannel.js @@ -146,7 +146,7 @@ Dashboard.getCurrentUser().done(function (user) { - if (MediaPlayer.canPlay(item, user)) { + if (MediaController.canPlay(item)) { $('#playButtonContainer', page).show(); } else { $('#playButtonContainer', page).hide(); @@ -296,12 +296,7 @@ $('#btnPlay', page).on('click', function () { var userdata = currentItem.UserData || {}; - LibraryBrowser.showPlayMenu(this, currentItem.Id, currentItem.Type, currentItem.MediaType, userdata.PlaybackPositionTicks); - }); - - $('#btnRemote', page).on('click', function () { - - RemoteControl.showMenuForItem({ item: currentItem, context: 'livetv' }); + LibraryBrowser.showPlayMenu(this, currentItem.Id, currentItem.Type, false, currentItem.MediaType, userdata.PlaybackPositionTicks); }); $('#btnEdit', page).on('click', function () { diff --git a/dashboard-ui/scripts/livetvprogram.js b/dashboard-ui/scripts/livetvprogram.js index 230b3fb9b..8a43bf988 100644 --- a/dashboard-ui/scripts/livetvprogram.js +++ b/dashboard-ui/scripts/livetvprogram.js @@ -114,7 +114,7 @@ ApiClient.getLiveTvChannel(currentItem.ChannelId, Dashboard.getCurrentUserId()).done(function (channel) { var userdata = channel.UserData || {}; - LibraryBrowser.showPlayMenu(this, channel.Id, channel.Type, channel.MediaType, userdata.PlaybackPositionTicks); + LibraryBrowser.showPlayMenu(this, channel.Id, channel.Type, false, channel.MediaType, userdata.PlaybackPositionTicks); }); }); @@ -123,15 +123,6 @@ deleteTimer(page, currentItem.TimerId); }); - $('#btnRemote', page).on('click', function () { - - RemoteControl.showMenuForItem({ - - item: currentItem, - context: 'livetv' - }); - }); - }).on('pageshow', "#liveTvProgramPage", function () { var page = this; diff --git a/dashboard-ui/scripts/livetvrecording.js b/dashboard-ui/scripts/livetvrecording.js index af5875d4c..6ecf63952 100644 --- a/dashboard-ui/scripts/livetvrecording.js +++ b/dashboard-ui/scripts/livetvrecording.js @@ -27,7 +27,7 @@ var mediaType = currentItem.MediaType; - LibraryBrowser.showPlayMenu(this, currentItem.Id, currentItem.Type, mediaType, userdata.PlaybackPositionTicks); + LibraryBrowser.showPlayMenu(this, currentItem.Id, currentItem.Type, false, mediaType, userdata.PlaybackPositionTicks); } function renderRecording(page, item) { @@ -68,7 +68,7 @@ Dashboard.getCurrentUser().done(function (user) { - if (MediaPlayer.canPlay(item, user)) { + if (MediaController.canPlay(item)) { $('#playButtonContainer', page).show(); } else { $('#playButtonContainer', page).hide(); @@ -107,15 +107,6 @@ $('#btnDelete', page).on('click', deleteRecording); $('#btnPlay', page).on('click', play); - $('#btnRemote', page).on('click', function () { - - RemoteControl.showMenuForItem({ - - item: currentItem, - context: 'livetv' - }); - }); - }).on('pagebeforeshow', "#liveTvRecordingPage", function () { var page = this; diff --git a/dashboard-ui/scripts/mediacontroller.js b/dashboard-ui/scripts/mediacontroller.js new file mode 100644 index 000000000..fc69934b9 --- /dev/null +++ b/dashboard-ui/scripts/mediacontroller.js @@ -0,0 +1,277 @@ +(function ($, window) { + + function mediaController() { + + var self = this; + var currentPlayer; + var currentTargetInfo; + + var players = []; + + self.registerPlayer = function (player) { + + players.push(player); + }; + + self.getPlayerInfo = function () { + + return { + + name: currentPlayer.name, + isLocalPlayer: currentPlayer.isLocalPlayer, + id: currentTargetInfo.id, + deviceName: currentTargetInfo.deviceName, + playableMediaTypes: currentTargetInfo.playableMediaTypes + }; + }; + + self.setActivePlayer = function (player, targetInfo) { + + if (typeof (player) === 'string') { + player = players.filter(function (p) { + return p.name == player; + })[0]; + } + + if (!player) { + throw new Error('null player'); + } + + if (!targetInfo) { + throw new Error('null targetInfo'); + } + + currentPlayer = player; + currentTargetInfo = targetInfo; + + $(self).trigger('playerchange'); + }; + + self.getTargets = function () { + + var deferred = $.Deferred(); + + var promises = players.map(function (p) { + return p.getTargets(); + }); + + $.when.apply($, promises).done(function () { + + var targets = []; + + for (var i = 0; i < arguments.length; i++) { + + var subTargets = arguments[i]; + + for (var j = 0; j < subTargets.length; j++) { + + targets.push(subTargets[j]); + } + + } + + deferred.resolveWith(null, [targets]); + }); + + return deferred.promise(); + }; + + self.play = function (options) { + + if (typeof (options) === 'string') { + options = { ids: [options] }; + } + + currentPlayer.play(options); + }; + + self.shuffle = function (id) { + + currentPlayer.shuffle(id); + }; + + self.instantMix = function (id) { + currentPlayer.instantMix(id); + }; + + self.queue = function (options) { + + if (typeof (options) === 'string') { + options = { ids: [options] }; + } + + currentPlayer.queue(options); + }; + + self.queueNext = function (options) { + + if (typeof (options) === 'string') { + options = { ids: [options] }; + } + + currentPlayer.queueNext(options); + }; + + self.canPlay = function (item) { + + if (item.PlayAccess != 'Full') { + return false; + } + + if (item.LocationType == "Virtual" || item.IsPlaceHolder) { + return false; + } + + if (item.IsFolder || item.Type == "MusicGenre") { + return true; + } + + return self.getPlayerInfo().playableMediaTypes.indexOf(item.MediaType) != -1; + }; + + self.canQueueMediaType = function (mediaType) { + + return currentPlayer.canQueueMediaType(mediaType); + }; + + self.getLocalPlayer = function () { + + return currentPlayer.isLocalPlayer ? + + currentPlayer : + + players.filter(function (p) { + return p.isLocalPlayer; + })[0]; + }; + } + + window.MediaController = new mediaController(); + + function onWebSocketMessageReceived(e, msg) { + + var localPlayer = msg.MessageType === "Play" || msg.MessageType === "Playstate" ? + MediaController.getLocalPlayer() : + null; + + if (msg.MessageType === "Play") { + + if (msg.Data.PlayCommand == "PlayNext") { + localPlayer.queueNext({ ids: msg.Data.ItemIds }); + } + else if (msg.Data.PlayCommand == "PlayLast") { + localPlayer.queue({ ids: msg.Data.ItemIds }); + } + else { + localPlayer.play({ ids: msg.Data.ItemIds, startPositionTicks: msg.Data.StartPositionTicks }); + } + + } + else if (msg.MessageType === "Playstate") { + + if (msg.Data.Command === 'Stop') { + localPlayer.stop(); + } + else if (msg.Data.Command === 'Pause') { + localPlayer.pause(); + } + else if (msg.Data.Command === 'Unpause') { + localPlayer.unpause(); + } + else if (msg.Data.Command === 'Seek') { + localPlayer.seek(msg.Data.SeekPositionTicks); + } + else if (msg.Data.Command === 'NextTrack') { + localPlayer.nextTrack(); + } + else if (msg.Data.Command === 'PreviousTrack') { + localPlayer.previousTrack(); + } + else if (msg.Data.Command === 'Fullscreen') { + localPlayer.remoteFullscreen(); + } + } + } + + $(ApiClient).on("websocketmessage", onWebSocketMessageReceived); + + function getTargetsHtml(targets) { + + var playerInfo = MediaController.getPlayerInfo(); + + var html = ''; + html += '
    '; + html += 'Select Player:'; + + for (var i = 0, length = targets.length; i < length; i++) { + + var target = targets[i]; + + var id = 'radioPlayerTarget' + i; + + var isChecked = target.id == playerInfo.id; + var checkedHtml = isChecked ? ' checked="checked"' : ''; + + html += ''; + html += ''; + } + + html += '
    '; + return html; + } + + function showPlayerSelection() { + + var promise = MediaController.getTargets(); + + var html = '
    '; + + html += '
    '; + + html += '
    '; + + $(document.body).append(html); + + var elem = $('#playerFlyout').panel({}).trigger('create').panel("open").on("panelafterclose", function () { + + $(this).off("panelafterclose").remove(); + }); + + promise.done(function (targets) { + + $('.players', elem).html(getTargetsHtml(targets)).trigger('create'); + + $('.radioSelectPlayerTarget', elem).on('change', function () { + + var playerName = this.getAttribute('data-playername'); + var targetId = this.getAttribute('data-targetid'); + var targetName = this.getAttribute('data-targetname'); + var playableMediaTypes = this.getAttribute('data-mediatypes').split(','); + + MediaController.setActivePlayer(playerName, { + id: targetId, + name: targetName, + playableMediaTypes: playableMediaTypes + + }); + }); + }); + } + + $(document).on('headercreated', ".libraryPage", function () { + + var page = this; + + $('.btnCast', page).on('click', function () { + + showPlayerSelection(); + }); + }); + +})(jQuery, window); \ No newline at end of file diff --git a/dashboard-ui/scripts/mediaplayer-video.js b/dashboard-ui/scripts/mediaplayer-video.js index d5466e682..804f67259 100644 --- a/dashboard-ui/scripts/mediaplayer-video.js +++ b/dashboard-ui/scripts/mediaplayer-video.js @@ -453,8 +453,6 @@ html += "
    "; } - html += '
    Preferences
    '; - return html; }; @@ -528,8 +526,6 @@ html += ""; } - html += '
    Preferences
    '; - return html; }; diff --git a/dashboard-ui/scripts/mediaplayer.js b/dashboard-ui/scripts/mediaplayer.js index bfee22ca1..d5c39289d 100644 --- a/dashboard-ui/scripts/mediaplayer.js +++ b/dashboard-ui/scripts/mediaplayer.js @@ -13,15 +13,31 @@ var canClientSeek; var currentPlaylistIndex = 0; - self.currentTimeElement; - self.unmuteButton; - self.muteButton; - self.positionSlider; - self.isPositionSliderActive; - self.volumeSlider; - self.startTimeTicksOffset; + self.currentTimeElement = null; + self.unmuteButton = null; + self.muteButton = null; + self.positionSlider = null; + self.isPositionSliderActive = null; + self.volumeSlider = null; + self.startTimeTicksOffset = null; + self.playlist = []; + self.isLocalPlayer = true; + self.name = 'Html5 Player'; + + self.getTargets = function () { + + var targets = [{ + name: 'My Browser', + id: ApiClient.deviceId(), + playerName: self.name, + playableMediaTypes: ['Audio', 'Video'] + }]; + + return targets; + }; + self.updateCanClientSeek = function (elem) { var duration = elem.duration; canClientSeek = duration && !isNaN(duration) && duration != Number.POSITIVE_INFINITY && duration != Number.NEGATIVE_INFINITY; @@ -275,7 +291,7 @@ audioBitrate: audioBitrate, videoBitrate: videoBitrate }; - + if (params.videoCodec == 'h264') { params.profile = 'baseline'; params.level = '3'; @@ -284,137 +300,100 @@ return params; }; - self.canPlay = function (item, user) { + self.canQueueMediaType = function (mediaType) { - if (item.PlayAccess != 'Full') { - return false; - } - - if (item.LocationType == "Virtual" || item.IsPlaceHolder) { - return false; - } - if (item.Type == "MusicAlbum" || item.Type == "MusicArtist" || item.Type == "MusicGenre") { - return true; - } - - if (item.GameSystem == "Nintendo" && item.MediaType == "Game" && item.ProviderIds.NesBox && item.ProviderIds.NesBoxRom) { - return true; - } - - if (item.GameSystem == "Super Nintendo" && item.MediaType == "Game" && item.ProviderIds.NesBox && item.ProviderIds.NesBoxRom) { - return true; - } - - return self.canPlayMediaType(item.MediaType); + return currentItem && currentItem.MediaType == mediaType; }; - self.getPlayUrl = function (item) { + function translateItemsForPlayback(items) { + var deferred = $.Deferred(); - if (item.GameSystem == "Nintendo" && item.MediaType == "Game" && item.ProviderIds.NesBox && item.ProviderIds.NesBoxRom) { + var firstItem = items[0]; + var promise; - return "http://nesbox.com/game/" + item.ProviderIds.NesBox + '/rom/' + item.ProviderIds.NesBoxRom; + if (firstItem.IsFolder) { + + promise = self.getItemsForPlayback({ + ParentId: firstItem.Id, + Filters: "IsNotFolder", + Recursive: true, + SortBy: "SortName", + MediaTypes: "Audio,Video" + }); + } + else if (firstItem.Type == "MusicArtist") { + + promise = self.getItemsForPlayback({ + Artists: firstItem.Name, + Filters: "IsNotFolder", + Recursive: true, + SortBy: "SortName", + MediaTypes: "Audio" + }); + + } + else if (firstItem.Type == "MusicGenre") { + + promise = self.getItemsForPlayback({ + Genres: firstItem.Name, + Filters: "IsNotFolder", + Recursive: true, + SortBy: "SortName", + MediaTypes: "Audio" + }); } - if (item.GameSystem == "Super Nintendo" && item.MediaType == "Game" && item.ProviderIds.NesBox && item.ProviderIds.NesBoxRom) { + if (promise) { + promise.done(function (result) { - return "http://snesbox.com/game/" + item.ProviderIds.NesBox + '/rom/' + item.ProviderIds.NesBoxRom; + deferred.resolveWith(null, [result.Items]); + }); + } else { + deferred.resolveWith(null, [items]); } - return null; - }; + return deferred.promise(); + } - self.canPlayMediaType = function (mediaType) { - - if (mediaType === "Video") { - return true; - } - - if (mediaType === "Audio") { - return true; - } - - return false; - }; - - self.play = function (items, startPosition) { + self.play = function (options) { Dashboard.getCurrentUser().done(function (user) { - var item = items[0]; + if (options.items) { - var videoType = (item.VideoType || "").toLowerCase(); + translateItemsForPlayback(options.items).done(function (items) { - var expirementalText = "This feature is experimental. It may not work at all with some titles. Do you wish to continue?"; + self.playInternal(items[0], options.startPositionTicks, user); - if (videoType == "dvd") { + self.playlist = items; + currentPlaylistIndex = 0; + }); - self.playWithWarning(items, startPosition, user, "dvdstreamconfirmed", "Dvd Folder Streaming", expirementalText); - return; - } - else if (videoType == "bluray") { + } else { - self.playWithWarning(items, startPosition, user, "bluraystreamconfirmed", "Blu-ray Folder Streaming", expirementalText); - return; - } - else if (videoType == "iso") { + self.getItemsForPlayback({ - var isoType = (item.IsoType || "").toLowerCase(); + Ids: options.ids.join(',') - if (isoType == "dvd") { + }).done(function (result) { - self.playWithWarning(items, startPosition, user, "dvdisostreamconfirmed", "Dvd Iso Streaming", expirementalText); - return; - } - else if (isoType == "bluray") { + translateItemsForPlayback(result.Items).done(function (items) { - self.playWithWarning(items, startPosition, user, "blurayisostreamconfirmed", "Blu-ray Iso Streaming", expirementalText); - return; - } - } + self.playInternal(items[0], options.startPositionTicks, user); - self.playInternal(items[0], startPosition, user); - self.onPlaybackStarted(items); - }); - }; + self.playlist = items; + currentPlaylistIndex = 0; + }); - self.playWithWarning = function (items, startPosition, user, localStorageKeyName, header, text) { - - // Increment this version when changes are made and we want users to see the prompts again - var warningVersion = "2"; - localStorageKeyName += new Date().getMonth() + warningVersion; - - if (localStorage.getItem(localStorageKeyName) == "1") { - - self.playInternal(items[0], startPosition, user); - - self.onPlaybackStarted(items); - - return; - } - - Dashboard.confirm(text, header, function (result) { - - if (result) { - - localStorage.setItem(localStorageKeyName, "1"); - - self.playInternal(items[0], startPosition, user); - - self.onPlaybackStarted(items); + }); } }); }; - self.onPlaybackStarted = function (items) { - - self.playlist = items; - currentPlaylistIndex = 0; - }; - - self.getBitrateSetting = function() { + self.getBitrateSetting = function () { return parseInt(localStorage.getItem('preferredVideoBitrate') || '') || 1500000; }; @@ -569,163 +548,11 @@ query.Limit = query.Limit || 100; query.Fields = getItemFields; + query.ExcludeLocationTypes = "Virtual"; return ApiClient.getItems(userId, query); }; - self.playById = function (id, startPositionTicks) { - - ApiClient.getItem(Dashboard.getCurrentUserId(), id).done(function (item) { - - if (item.IsFolder) { - - self.getItemsForPlayback({ - - ParentId: id, - Recursive: true, - SortBy: "SortName" - - }).done(function (result) { - - self.play(result.Items, startPositionTicks); - - }); - - } else { - self.play([item], startPositionTicks); - } - - }); - - }; - - self.playInstantMixFromSong = function (id) { - - ApiClient.getInstantMixFromSong(id, { - - UserId: Dashboard.getCurrentUserId(), - Fields: getItemFields, - Limit: 50 - - }).done(function (result) { - - self.play(result.Items); - }); - - }; - - self.playInstantMixFromAlbum = function (id) { - - ApiClient.getInstantMixFromAlbum(id, { - - UserId: Dashboard.getCurrentUserId(), - Fields: getItemFields, - Limit: 50 - - }).done(function (result) { - - self.play(result.Items); - }); - - }; - - self.playInstantMixFromArtist = function (name) { - - ApiClient.getInstantMixFromArtist(name, { - - UserId: Dashboard.getCurrentUserId(), - Fields: getItemFields, - Limit: 50 - - }).done(function (result) { - - self.play(result.Items); - }); - - }; - - self.playInstantMixFromMusicGenre = function (name) { - - ApiClient.getInstantMixFromMusicGenre(name, { - - UserId: Dashboard.getCurrentUserId(), - Fields: getItemFields, - Limit: 50 - - }).done(function (result) { - - self.play(result.Items); - }); - - }; - - self.playArtist = function (artist) { - - self.getItemsForPlayback({ - - Artists: artist, - Recursive: true, - SortBy: "Album,SortName", - IncludeItemTypes: "Audio" - - }).done(function (result) { - - self.play(result.Items); - - }); - - }; - - self.shuffleArtist = function (artist) { - - self.getItemsForPlayback({ - - Artists: artist, - Recursive: true, - SortBy: "Random", - IncludeItemTypes: "Audio" - - }).done(function (result) { - - self.play(result.Items); - - }); - - }; - - self.shuffleMusicGenre = function (genre) { - - self.getItemsForPlayback({ - - Genres: genre, - Recursive: true, - SortBy: "Random", - IncludeItemTypes: "Audio" - - }).done(function (result) { - - self.play(result.Items); - - }); - - }; - - self.shuffleFolder = function (id) { - - self.getItemsForPlayback({ - - ParentId: id, - Recursive: true, - SortBy: "Random" - - }).done(function (result) { - - self.play(result.Items); - - }); - - }; - self.removeFromPlaylist = function (index) { self.playlist.remove(index); @@ -797,51 +624,69 @@ } }; - self.queue = function (id) { + self.queue = function (options) { if (!currentMediaElement) { - self.playById(id); + self.play(options); return; } - ApiClient.getItem(Dashboard.getCurrentUserId(), id).done(function (item) { + Dashboard.getCurrentUser().done(function (user) { - if (item.IsFolder) { + if (options.items) { - self.getItemsForPlayback({ - - ParentId: id, - Recursive: true, - SortBy: "SortName" - - }).done(function (result) { - - self.queueItems(result.Items); + translateItemsForPlayback(options.items).done(function (items) { + self.queueItems(items); }); } else { - self.queueItems([item]); - } + self.getItemsForPlayback({ + + Ids: options.ids.join(',') + + }).done(function (result) { + + translateItemsForPlayback(result.Items).done(function (items) { + + self.queueItems(items); + }); + + }); + } }); }; - self.queueArtist = function (artist) { + self.queueNext = function (options) { - self.getItemsForPlayback({ + if (!currentMediaElement) { + self.play(options); + return; + } - Artists: artist, - Recursive: true, - SortBy: "Album,SortName", - IncludeItemTypes: "Audio" + Dashboard.getCurrentUser().done(function (user) { - }).done(function (result) { + if (options.items) { - self.queueItems(result.Items); + self.queueItemsNext(options.items); + + } else { + + self.getItemsForPlayback({ + + Ids: options.ids.join(',') + + }).done(function (result) { + + options.items = result.Items; + + self.queueItemsNext(options.items); + + }); + } }); - }; self.pause = function () { @@ -905,6 +750,108 @@ } }; + self.shuffle = function (id) { + + var userId = Dashboard.getCurrentUserId(); + + ApiClient.getItem(userId, id).done(function (item) { + + var query = { + UserId: userId, + Fields: getItemFields, + Limit: 50, + Filters: "IsNotFolder", + Recursive: true, + SortBy: "Random" + }; + + if (item.IsFolder) { + query.ParentId = id; + + } + else if (item.Type == "MusicArtist") { + + query.MediaTypes = "Audio"; + query.Artists = item.Name; + + } + else if (item.Type == "MusicGenre") { + + query.MediaTypes = "Audio"; + query.Genres = item.Name; + + } else { + return; + } + + self.getItemsForPlayback(query).done(function (result) { + + self.play({ items: result.Items }); + + }); + + }); + + }; + + self.instantMix = function (id) { + + var userId = Dashboard.getCurrentUserId(); + + ApiClient.getItem(userId, id).done(function (item) { + + var promise; + + if (item.Type == "MusicArtist") { + + promise = ApiClient.getInstantMixFromArtist(name, { + UserId: Dashboard.getCurrentUserId(), + Fields: getItemFields, + Limit: 50 + }); + + } + else if (item.Type == "MusicGenre") { + + promise = ApiClient.getInstantMixFromMusicGenre(name, { + UserId: Dashboard.getCurrentUserId(), + Fields: getItemFields, + Limit: 50 + }); + + } + else if (item.Type == "MusicAlbum") { + + promise = ApiClient.getInstantMixFromAlbum(id, { + UserId: Dashboard.getCurrentUserId(), + Fields: getItemFields, + Limit: 50 + }); + + } + else if (item.Type == "Audio") { + + promise = ApiClient.getInstantMixFromSong(id, { + UserId: Dashboard.getCurrentUserId(), + Fields: getItemFields, + Limit: 50 + }); + + } + else { + return; + } + + promise.done(function (result) { + + self.play({ items: result.Items }); + + }); + + }); + + }; + self.stop = function () { var elem = currentMediaElement; @@ -933,14 +880,6 @@ return currentMediaElement; }; - self.showSendMediaMenu = function () { - - RemoteControl.showMenuForItem({ - item: currentItem - }); - - }; - self.bindPositionSlider = function () { self.positionSlider.on('slidestart', function (e) { @@ -1220,4 +1159,8 @@ window.MediaPlayer = new mediaPlayer(); + window.MediaController.registerPlayer(window.MediaPlayer); + window.MediaController.setActivePlayer(window.MediaPlayer, window.MediaPlayer.getTargets()[0]); + + })(document, setTimeout, clearTimeout, screen, localStorage, $, setInterval, window); \ No newline at end of file diff --git a/dashboard-ui/scripts/remotecontrol.js b/dashboard-ui/scripts/remotecontrol.js index 11fafbeeb..7318926d9 100644 --- a/dashboard-ui/scripts/remotecontrol.js +++ b/dashboard-ui/scripts/remotecontrol.js @@ -1,570 +1,5 @@ (function (window, document, $) { - function sendPlayFolderCommand(item, sessionId, popup) { - - ApiClient.getItems(Dashboard.getCurrentUserId(), { - - ParentId: item.Id, - Filters: "IsNotFolder", - SortBy: "SortName", - Recursive: true, - Limit: 100 - - }).done(function (result) { - - ApiClient.sendPlayCommand(sessionId, { - - ItemIds: result.Items.map(function (i) { - return i.Id; - }).join(','), - - PlayCommand: $('#fldPlayCommand', popup).val() - }); - - popup.popup("close"); - - }); - - } - - function sendPlayArtistCommand(item, sessionId, popup) { - - ApiClient.getItems(Dashboard.getCurrentUserId(), { - - Artists: item.Name, - SortBy: "SortName", - IncludeItemTypes: "Audio", - Recursive: true, - Limit: 100 - - }).done(function (result) { - - ApiClient.sendPlayCommand(sessionId, { - - ItemIds: result.Items.map(function (i) { - return i.Id; - }).join(','), - - PlayCommand: $('#fldPlayCommand', popup).val() - }); - - popup.popup("close"); - - }); - - } - - function showMenuForItem(options, sessionsPromise) { - - var playFromRendered; - var trailersRendered; - var specialFeaturesRendered; - var themeVideosRendered; - var themeSongsRendered; - - var item = options.item; - - var html = '
    '; - - html += 'Close'; - - html += '
    '; - html += '
    Remote Control
    '; - html += '
    '; - - html += '
    '; - - html += '
    '; - html += ''; - html += '
    '; - - html += '
    '; - - html += '
    '; - - html += '

    '; - - html += ''; - - html += ''; - - html += ''; - - html += ''; - - html += '

    '; - - html += '
    '; - - html += '
    '; - - $(document.body).append(html); - - var popup = $('.remoteControlFlyout').popup({ history: false, tolerance: 0, corners: false }).trigger('create').popup("open").on("popupafterclose", function () { - - if (ApiClient.isWebSocketOpen()) { - ApiClient.sendWebSocketMessage("SessionsStop"); - } - - $(ApiClient).off("websocketmessage.remotecontrol"); - - $(this).off("popupafterclose").remove(); - - $('.remoteControlFlyout').popup("destroy").remove(); - }); - - popup.on('click', '.trSession', function () { - - $('input', this).checked(true); - - - }).on('click', '.trSelectPlayTime', function () { - - $('input', this).checked(true); - - }).on('click', '.trItem', function () { - - $('input', this).checked(true); - - }); - - $('#sendToForm', popup).on('submit', function () { - - var checkboxes = $('.chkClient', popup); - - if (!checkboxes.length) { - $('.remoteControlFlyout').popup("close"); - return false; - } - - checkboxes = $('.chkClient:checked', popup); - - if (!checkboxes.length) { - Dashboard.alert('Please select a device to control.'); - return false; - } - - var sessionIds = []; - - checkboxes.parents('.trSession').each(function () { - - sessionIds.push(this.getAttribute('data-sessionid')); - - }); - - var command = $('#selectCommand', popup).val(); - - var promise; - var showRemoteControlMenuAfterCommand = true; - - if (command == "Play") { - - if (item.IsFolder) { - - sendPlayFolderCommand(item, sessionIds[0], popup); - - return false; - } - if (item.Type == "MusicArtist") { - - sendPlayArtistCommand(item, sessionIds[0], popup); - - return false; - } - - var playCommand = $('#fldPlayCommand', popup).val(); - - if (playCommand == "Resume") { - - promise = ApiClient.sendPlayCommand(sessionIds[0], { - - ItemIds: [item.Id].join(','), - PlayCommand: 'PlayNow', - StartPositionTicks: item.UserData.PlaybackPositionTicks - }); - - } - else if (playCommand == "Browse") { - - promise = ApiClient.sendBrowseCommand(sessionIds[0], { - - ItemId: item.Id, - ItemName: item.Name, - ItemType: item.Type, - Context: options.context - - }); - - showRemoteControlMenuAfterCommand = false; - } - else { - promise = ApiClient.sendPlayCommand(sessionIds[0], { - - ItemIds: [item.Id].join(','), - PlayCommand: playCommand - }); - } - } - else if (command == "PlayFromChapter") { - - var checkedChapter = $('.chkSelectPlayTime:checked', popup); - - var ticks = checkedChapter.length ? checkedChapter.parents('.trSelectPlayTime').attr('data-ticks') : 0; - - promise = ApiClient.sendPlayCommand(sessionIds[0], { - - ItemIds: [item.Id].join(','), - PlayCommand: $('#fldPlayCommand', popup).val(), - StartPositionTicks: ticks - - }); - } - else if (command == "Trailer" || command == "SpecialFeature" || command == "ThemeSong" || command == "ThemeVideo") { - - var id = $('.chkSelectItem:checked', popup).parents('.trItem').attr('data-id'); - - if (!id) { - Dashboard.alert('Please select an item.'); - return false; - } - promise = ApiClient.sendPlayCommand(sessionIds[0], { - - ItemIds: [id].join(','), - PlayCommand: $('#fldPlayCommand', popup).val() - - }); - } - - promise.done(function () { - - popup.popup("close"); - - if (showRemoteControlMenuAfterCommand) { - RemoteControl.showMenu(); - } - }); - - return false; - }); - - var elem = $('.sessionsPopupContent'); - - sessionsPromise.done(function (sessions) { - - var deviceId = ApiClient.deviceId(); - - // don't display the current session - sessions = sessions.filter(function (s) { - return s.DeviceId != deviceId; - }); - - renderSessionsInPlayMenu(sessions, options, elem, popup); - - if (ApiClient.isWebSocketOpen()) { - ApiClient.sendWebSocketMessage("SessionsStart", "1000,1000"); - - $(ApiClient).on("websocketmessage.remotecontrol", function (e, msg) { - - if (msg.MessageType === "Sessions") { - updateSessionsInPlayMenu(msg.Data, elem); - } - }); - - } - - $('#selectCommand', popup).on('change', function () { - - var playFromMenu = $('.playFromMenu', popup).hide(); - var trailersElem = $('.trailers', popup).hide(); - var specialFeaturesElem = $('.specialFeatures', popup).hide(); - var themeSongsElem = $('.themeSongs', popup).hide(); - var themeVideosElem = $('.themeVideos', popup).hide(); - var playButtonContainer = $('#playButtonContainer', popup).hide(); - var queueButtonContainer = $('#queueButtonContainer', popup).hide(); - var resumeButtonContainer = $('#resumeButtonContainer', popup).hide(); - var browseButtonContainer = $('#browseButtonContainer', popup).hide(); - - var value = this.value; - - if (value == "Play") { - - browseButtonContainer.show(); - - if (item.Type != 'Person' && item.Type != 'Genre' && item.Type != 'Studio' && item.Type != 'GameGenre' && item.Type != 'MusicGenre' && item.LocationType != 'Virtual') { - playButtonContainer.show(); - queueButtonContainer.show(); - } - - if (!item.IsFolder && item.UserData && item.UserData.PlaybackPositionTicks) { - resumeButtonContainer.show(); - } - } - else if (value == "Trailer") { - - trailersElem.show(); - playButtonContainer.show(); - queueButtonContainer.show(); - - if (!trailersRendered) { - trailersRendered = true; - - ApiClient.getLocalTrailers(Dashboard.getCurrentUserId(), item.Id).done(function (trailers) { - - renderVideos(trailersElem, trailers, 'Trailers'); - - popup.popup("reposition", { tolerance: 0 }); - }); - } - } - else if (value == "SpecialFeature") { - - specialFeaturesElem.show(); - playButtonContainer.show(); - queueButtonContainer.show(); - - if (!specialFeaturesRendered) { - specialFeaturesRendered = true; - - ApiClient.getSpecialFeatures(Dashboard.getCurrentUserId(), item.Id).done(function (videos) { - - renderVideos(specialFeaturesElem, videos, 'Special Features'); - - popup.popup("reposition", { tolerance: 0 }); - }); - } - } - else if (value == "ThemeSong") { - - themeSongsElem.show(); - playButtonContainer.show(); - queueButtonContainer.show(); - - if (!themeSongsRendered) { - themeSongsRendered = true; - - ApiClient.getThemeSongs(Dashboard.getCurrentUserId(), item.Id).done(function (result) { - - renderVideos(themeSongsElem, result.Items, 'Theme Songs'); - - $('.remoteControlFlyout').popup("reposition", { tolerance: 0 }); - }); - } - } - else if (value == "ThemeVideo") { - - themeVideosElem.show(); - playButtonContainer.show(); - queueButtonContainer.show(); - - if (!themeVideosRendered) { - themeVideosRendered = true; - - ApiClient.getThemeVideos(Dashboard.getCurrentUserId(), item.Id).done(function (result) { - - renderVideos(themeVideosElem, result.Items, 'Theme Videos'); - - popup.popup("reposition", { tolerance: 0 }); - }); - } - } - - }).trigger('change'); - }); - } - - function renderSessionsInPlayMenu(sessions, options, elem, popup) { - - if (!sessions.length) { - elem.html('

    There are currently no available media browser sessions to control.

    '); - $('.remoteControlFlyout').popup("reposition", {}); - return; - } - - var item = options.item; - - var html = ''; - - html += '
    '; - html += ''; - html += '
    '; - - html += ''; - html += ''; - html += ''; - html += ''; - html += ''; - - html += '

    Select Device

    '; - - html += ''; - - html += ''; - html += ''; - html += ''; - html += ''; - - html += ''; - - for (var i = 0, length = sessions.length; i < length; i++) { - - var session = sessions[i]; - - html += ''; - - html += ''; - html += ''; - - html += ''; - } - - html += ''; - - html += '
    Device
    ' + session.DeviceName; - - if (session.UserName) { - html += ' - ' + session.UserName; - } - html += '
    '; - - html += ''; - - elem.html(html).trigger('create'); - - $('.tdSelectSession', elem).html(''); - - $('.chkClient:first', elem).checked(true); - } - - function getSessionNowPlayingTime(session) { - - var html = ''; - - if (session.NowPlayingItem) { - - html += Dashboard.getDisplayTime(session.NowPlayingPositionTicks || 0); - - if (session.NowPlayingItem.RunTimeTicks) { - - html += " / "; - html += Dashboard.getDisplayTime(session.NowPlayingItem.RunTimeTicks); - } - } - - return html; - } - - function updateSessionsInPlayMenu(sessions, elem) { - - for (var i = 0, length = sessions.length; i < length; i++) { - - var session = sessions[i]; - - var sessionElem = $('.trSession[data-sessionid=' + session.Id + ']', elem); - - $('.tdUserName', sessionElem).html(session.UserName || ''); - $('.tdNowPlayingTime', sessionElem).html(getSessionNowPlayingTime(session)); - $('.tdNowPlayingName', sessionElem).html(session.NowPlayingItem ? session.NowPlayingItem.Name : ''); - - } - - } - - function renderVideos(elem, videos, header) { - - var html = ''; - - html += '

    ' + header + '

    '; - - html += '
    '; - html += ''; - - html += ''; - - for (var i = 0, length = videos.length; i < length; i++) { - - var video = videos[i]; - - html += ''; - - - html += ''; - - html += ''; - - html += ''; - - html += ''; - } - - html += ''; - - html += '
    '; - - var imgUrl; - - if (video.ImageTags && video.ImageTags.Primary) { - - imgUrl = ApiClient.getImageUrl(video.Id, { - maxheight: 80, - tag: video.ImageTags.Primary, - type: "Primary" - }); - - html += ''; - } - - html += '' + video.Name; - - if (video.RunTimeTicks) { - html += '
    ' + Dashboard.getDisplayTime(video.RunTimeTicks); - } - - html += '
    '; - html += '
    '; - - elem.html(html); - - $('.tdSelectItem', elem).html(''); - - $('.chkSelectItem:first', elem).checked(true); - } - function showMenu(sessions, options) { var html = '
    '; @@ -965,10 +400,6 @@ ControllableByUserId: Dashboard.getCurrentUserId() }; - self.showMenuForItem = function (options) { - showMenuForItem(options, ApiClient.getSessions(sessionQuery)); - }; - self.showMenu = function (options) { ApiClient.getSessions(sessionQuery).done(function (sessions) { @@ -980,4 +411,99 @@ window.RemoteControl = new remoteControl(); + function sendPlayCommand(options, playType) { + + var sessionId = MediaController.getPlayerInfo().id; + + var ids = options.ids || options.items.map(function (i) { + return i.Id; + }); + + var remoteOptions = { + ItemIds: ids.join(','), + + PlayCommand: playType + }; + + if (options.startPositionTicks) { + remoteOptions.startPositionTicks = options.startPositionTicks; + } + + ApiClient.sendPlayCommand(sessionId, remoteOptions); + } + + function remoteControlPlayer() { + + var self = this; + + self.name = 'Remote Control'; + + self.play = function (options) { + + sendPlayCommand(options, 'PlayNow'); + }; + + self.shuffle = function (id) { + + sendPlayCommand({ ids: [id] }, 'PlayShuffle'); + }; + + self.instantMix = function (id) { + + sendPlayCommand({ ids: [id] }, 'PlayInstantMix'); + }; + + self.queue = function (options) { + + sendPlayCommand(options, 'PlayNext'); + }; + + self.queueNext = function (options) { + + sendPlayCommand(options, 'PlayLast'); + }; + + self.canQueueMediaType = function (mediaType) { + + return mediaType == 'Audio' || mediaType == 'Video'; + }; + + self.getTargets = function () { + + var deferred = $.Deferred(); + + var sessionQuery = { + SupportsRemoteControl: true, + ControllableByUserId: Dashboard.getCurrentUserId() + }; + + ApiClient.getSessions(sessionQuery).done(function (sessions) { + + var targets = sessions.filter(function (s) { + + return s.DeviceId != ApiClient.deviceId(); + + }).map(function (s) { + return { + name: s.DeviceName, + id: s.Id, + playerName: self.name, + appName: s.Client, + playableMediaTypes: s.PlayableMediaTypes + }; + }); + + deferred.resolveWith(null, [targets]); + + }).fail(function () { + + deferred.reject(); + }); + + return deferred.promise(); + }; + } + + MediaController.registerPlayer(new remoteControlPlayer()); + })(window, document, jQuery); \ No newline at end of file diff --git a/dashboard-ui/scripts/site.js b/dashboard-ui/scripts/site.js index 09fe48255..00948fb80 100644 --- a/dashboard-ui/scripts/site.js +++ b/dashboard-ui/scripts/site.js @@ -882,51 +882,6 @@ var Dashboard = { Dashboard.onBrowseCommand(msg.Data); } - else if (msg.MessageType === "Play") { - - MediaPlayer.getItemsForPlayback({ - - Ids: msg.Data.ItemIds.join(',') - - }).done(function (result) { - - if (msg.Data.PlayCommand == "PlayNext") { - MediaPlayer.queueItemsNext(result.Items); - } - else if (msg.Data.PlayCommand == "PlayLast") { - MediaPlayer.queueItems(result.Items); - } - else { - MediaPlayer.play(result.Items, msg.Data.StartPositionTicks); - } - - }); - - } - else if (msg.MessageType === "Playstate") { - - if (msg.Data.Command === 'Stop') { - MediaPlayer.stop(); - } - else if (msg.Data.Command === 'Pause') { - MediaPlayer.pause(); - } - else if (msg.Data.Command === 'Unpause') { - MediaPlayer.unpause(); - } - else if (msg.Data.Command === 'Seek') { - MediaPlayer.seek(msg.Data.SeekPositionTicks); - } - else if (msg.Data.Command === 'NextTrack') { - MediaPlayer.nextTrack(); - } - else if (msg.Data.Command === 'PreviousTrack') { - MediaPlayer.previousTrack(); - } - else if (msg.Data.Command === 'Fullscreen') { - MediaPlayer.remoteFullscreen(); - } - } else if (msg.MessageType === "SystemCommand") { if (msg.Data === 'GoHome') { @@ -1365,8 +1320,6 @@ $(function () { videoPlayerHtml += ''; videoPlayerHtml += '
    '; - videoPlayerHtml += ''; - videoPlayerHtml += ''; videoPlayerHtml += '
    '; // videoControls @@ -1422,8 +1375,6 @@ $(function () { footerHtml += ''; - footerHtml += ''; - footerHtml += ''; footerHtml += '
    ';