1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Tim Hobbs 2014-03-30 01:29:17 -07:00
commit e9b554b932
24 changed files with 848 additions and 1094 deletions

View file

@ -676,14 +676,14 @@ a.itemTag:hover {
} }
} }
@media all and (min-width: 800px) { @media all and (min-width: 880px) {
.libraryMenuButton { .libraryMenuButton {
display: none; display: none;
} }
} }
@media all and (max-width: 800px) { @media all and (max-width: 880px) {
.desktopHomeLink { .desktopHomeLink {
display: none; display: none;

View file

@ -165,7 +165,7 @@
/****************************************/ /****************************************/
@media all and (max-width: 1200px), all and (max-height: 720px) { @media all and (max-width: 1200px), all and (max-height: 720px) {
#mediaPlayer .chaptersButton, #mediaPlayer .audioTracksButton, #mediaPlayer .sendMediaButton { #mediaPlayer .chaptersButton, #mediaPlayer .audioTracksButton {
display: none!important; display: none!important;
} }
@ -179,7 +179,7 @@
} }
@media all and (max-width: 960px), all and (max-height: 550px) { @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; display: none!important;
} }
@ -193,7 +193,7 @@
} }
@media all and (max-width: 800px), all and (max-height: 460px) { @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; display: none!important;
} }

View file

@ -135,7 +135,7 @@ input[type="range"]::-ms-fill-upper {
} }
@media all and (max-width: 600px) { @media all and (max-width: 600px) {
.chaptersButton, .audioTracksButton, .sendMediaButton { .chaptersButton, .audioTracksButton {
display: none!important; display: none!important;
} }

View file

@ -120,11 +120,13 @@
</div> </div>
<div class="profileTab tabDirectPlayProfiles"> <div class="profileTab tabDirectPlayProfiles">
<p>Add direct play profiles to indicate what formats the device can handle natively.</p> <p>Add direct play profiles to indicate which formats the device can handle natively.</p>
<button class="btnAddDirectPlayProfile" type="button" data-mini="true" data-icon="plus">New</button>
<br />
<div class="directPlayProfiles"></div> <div class="directPlayProfiles"></div>
</div> </div>
<div class="profileTab tabTranscodingProfiles"> <div class="profileTab tabTranscodingProfiles">
<p>Add transcoding profiles to indicate what formats should be used when transcoding is required.</p> <p>Add transcoding profiles to indicate which formats should be used when transcoding is required.</p>
<div class="transcodingProfiles"></div> <div class="transcodingProfiles"></div>
</div> </div>
<div class="profileTab tabContainerProfiles"> <div class="profileTab tabContainerProfiles">
@ -155,8 +157,57 @@
</div> </div>
</div> </div>
<div data-role="popup" data-transition="slidefade" id="popupEditDirectPlayProfile" class="popup">
<div class="ui-bar-a" style="text-align: center; padding: 0 20px;">
<h3>Direct Play Profile</h3>
</div>
<div data-role="content">
<form class="editDirectPlayProfileForm">
<div style="margin: 1em 0;">
<label for="selectDirectPlayProfileType">Type:</label>
<select id="selectDirectPlayProfileType" data-mini="true">
<option value="Audio">Audio</option>
<option value="Photo">Photo</option>
<option value="Video">Video</option>
</select>
</div>
<div style="margin: 1em 0;">
<label for="txtDirectPlayContainer">Containers:</label>
<input type="text" id="txtDirectPlayContainer" data-mini="true" />
<div>Separated by comma. This can be left empty to apply to all containers</div>
</div>
<div id="fldDirectPlayVideoCodec" style="margin: 1em 0;">
<label for="txtDirectPlayVideoCodec">Video codecs:</label>
<input type="text" id="txtDirectPlayVideoCodec" data-mini="true" />
<div>Separated by comma. This can be left empty to apply to all containers</div>
</div>
<div id="fldDirectPlayAudioCodec" style="margin: 1em 0 2em;">
<label for="txtDirectPlayAudioCodec">Audio codecs:</label>
<input type="text" id="txtDirectPlayAudioCodec" data-mini="true" />
<div>Separated by comma. This can be left empty to apply to all containers</div>
</div>
<p>
<button type="submit" data-theme="b" data-icon="check" data-mini="true">
Ok
</button>
<button type="button" data-icon="delete" onclick="$(this).parents('.popup').popup('close');" data-mini="true">
Cancel
</button>
</p>
</form>
</div>
</div>
<script type="text/javascript"> <script type="text/javascript">
$('.dlnaProfileForm').off('submit', DlnaProfilePage.onSubmit).on('submit', DlnaProfilePage.onSubmit); $('.dlnaProfileForm').off('submit', DlnaProfilePage.onSubmit).on('submit', DlnaProfilePage.onSubmit);
$('.editDirectPlayProfileForm').off('submit', DlnaProfilePage.onDirectPlayFormSubmit).on('submit', DlnaProfilePage.onDirectPlayFormSubmit);
</script> </script>
</div> </div>
</body> </body>

View file

@ -145,9 +145,6 @@
<span id="playButtonContainer" style="display: none;"> <span id="playButtonContainer" style="display: none;">
<button id="btnPlay" type="button" data-icon="play" data-inline="true" data-mini="true">Play</button> <button id="btnPlay" type="button" data-icon="play" data-inline="true" data-mini="true">Play</button>
</span> </span>
<span>
<button id="btnRemote" type="button" data-icon="wireless" data-inline="true" data-mini="true">Remote</button>
</span>
<span id="editButtonContainer" style="display: none;"> <span id="editButtonContainer" style="display: none;">
<a id="btnEdit" data-role="button" data-icon="edit" data-inline="true" data-mini="true" href="#">Edit</a> <a id="btnEdit" data-role="button" data-icon="edit" data-inline="true" data-mini="true" href="#">Edit</a>
</span> </span>

View file

@ -131,9 +131,6 @@
<span id="playExternalButtonContainer" style="display: none;"> <span id="playExternalButtonContainer" style="display: none;">
<a id="btnPlayExternal" data-role="button" data-icon="play" data-inline="true" data-mini="true" href="#" target="_blank">Play</a> <a id="btnPlayExternal" data-role="button" data-icon="play" data-inline="true" data-mini="true" href="#" target="_blank">Play</a>
</span> </span>
<span id="remoteButtonContainer" style="display: none;">
<button id="btnRemote" type="button" data-icon="wireless" data-inline="true" data-mini="true">Remote</button>
</span>
<span id="editButtonContainer" style="display: none;"> <span id="editButtonContainer" style="display: none;">
<a id="btnEdit" data-role="button" data-icon="edit" data-inline="true" data-mini="true" href="#">Edit</a> <a id="btnEdit" data-role="button" data-icon="edit" data-inline="true" data-mini="true" href="#">Edit</a>
</span> </span>

View file

@ -30,9 +30,6 @@
<span id="playButtonContainer" style="display: none;"> <span id="playButtonContainer" style="display: none;">
<button id="btnPlay" type="button" data-icon="play" data-inline="true" data-mini="true">Play</button> <button id="btnPlay" type="button" data-icon="play" data-inline="true" data-mini="true">Play</button>
</span> </span>
<span>
<button id="btnRemote" type="button" data-icon="wireless" data-inline="true" data-mini="true">Remote</button>
</span>
<span id="editButtonContainer" style="display: none;"> <span id="editButtonContainer" style="display: none;">
<button id="btnEdit" type="button" data-icon="edit" data-inline="true" data-mini="true">Edit</button> <button id="btnEdit" type="button" data-icon="edit" data-inline="true" data-mini="true">Edit</button>
</span> </span>

View file

@ -47,9 +47,6 @@
<span id="recordButtonContainer" style="display: none;"> <span id="recordButtonContainer" style="display: none;">
<button id="btnRecord" type="button" data-icon="video" data-inline="true" data-mini="true">Record</button> <button id="btnRecord" type="button" data-icon="video" data-inline="true" data-mini="true">Record</button>
</span> </span>
<span>
<button id="btnRemote" type="button" data-icon="wireless" data-inline="true" data-mini="true">Remote</button>
</span>
</div> </div>
<div data-role="content"> <div data-role="content">
<div class="detailPageContent"> <div class="detailPageContent">

View file

@ -41,9 +41,6 @@
<span id="playButtonContainer" style="display: none;"> <span id="playButtonContainer" style="display: none;">
<button id="btnPlay" type="button" data-icon="play" data-inline="true" data-mini="true">Play</button> <button id="btnPlay" type="button" data-icon="play" data-inline="true" data-mini="true">Play</button>
</span> </span>
<span>
<button id="btnRemote" type="button" data-icon="wireless" data-inline="true" data-mini="true">Remote</button>
</span>
<span id="deleteButtonContainer" style="display: none;"> <span id="deleteButtonContainer" style="display: none;">
<button id="btnDelete" type="button" data-icon="delete" data-inline="true" data-mini="true">Delete</button> <button id="btnDelete" type="button" data-icon="delete" data-inline="true" data-mini="true">Delete</button>
</span> </span>

View file

@ -118,8 +118,7 @@
* Generic error callback function * Generic error callback function
*/ */
CastPlayer.prototype.onError = function () { CastPlayer.prototype.onError = function () {
console.log("error"); console.log("chromecast error");
$('.btnCast').hide();
}; };
/** /**
@ -147,13 +146,11 @@
*/ */
CastPlayer.prototype.receiverListener = function (e) { CastPlayer.prototype.receiverListener = function (e) {
if (e === 'available') { if (e === 'available') {
console.log("receiver found"); console.log("chromecast receiver found");
$('.btnCast').show();
this.hasReceivers = true; this.hasReceivers = true;
} }
else { else {
console.log("receiver list empty"); console.log("chromecast receiver list empty");
$('.btnCast').hide();
this.hasReceivers = false; this.hasReceivers = false;
} }
}; };
@ -686,7 +683,7 @@
} else { } else {
} }
$('.btnCast').attr('title', this.castPlayerState + " on " + this.session.receiver.friendlyName); // this.session.receiver.friendlyName
}; };
/** /**
@ -695,19 +692,15 @@
CastPlayer.prototype.updateMediaControlUI = function () { CastPlayer.prototype.updateMediaControlUI = function () {
if (!chrome || !chrome.cast) { if (!chrome || !chrome.cast) {
$('.btnCast').hide();
return; return;
} }
if (this.hasReceivers) { if (this.hasReceivers) {
$('.btnCast').show();
} }
if (this.deviceState == DEVICE_STATE.ACTIVE) { if (this.deviceState == DEVICE_STATE.ACTIVE) {
$('.btnCast').removeClass('btnDefaultCast').addClass('btnActiveCast');
var playerState = this.castPlayerState; var playerState = this.castPlayerState;
} else { } else {
$('.btnCast').removeClass('btnActiveCast').addClass('btnDefaultCast');
var playerState = this.localPlayerState; var playerState = this.localPlayerState;
} }
@ -739,15 +732,6 @@
castPlayer.updateMediaControlUI(); castPlayer.updateMediaControlUI();
$('.btnCast', page).on('click', function () {
if (castPlayer.deviceState == DEVICE_STATE.ACTIVE) {
castPlayer.stopApp();
} else {
castPlayer.launchApp();
}
});
}); });
})(window, window.chrome, console); })(window, window.chrome, console);

View file

@ -2,6 +2,9 @@
var currentProfile; var currentProfile;
var currentSubProfile;
var isSubProfileNew;
function loadProfile(page) { function loadProfile(page) {
Dashboard.showLoadingMsg(); Dashboard.showLoadingMsg();
@ -60,6 +63,11 @@
profile.CodecProfiles = (profile.CodecProfiles || []); profile.CodecProfiles = (profile.CodecProfiles || []);
profile.MediaProfiles = (profile.MediaProfiles || []); profile.MediaProfiles = (profile.MediaProfiles || []);
renderSubProfiles(page, profile);
}
function renderSubProfiles(page, profile) {
renderDirectPlayProfiles(page, profile.DirectPlayProfiles); renderDirectPlayProfiles(page, profile.DirectPlayProfiles);
renderTranscodingProfiles(page, profile.TranscodingProfiles); renderTranscodingProfiles(page, profile.TranscodingProfiles);
renderContainerProfiles(page, profile.ContainerProfiles); renderContainerProfiles(page, profile.ContainerProfiles);
@ -67,6 +75,39 @@
renderMediaProfiles(page, profile.MediaProfiles); 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) { function renderDirectPlayProfiles(page, profiles) {
var html = ''; var html = '';
@ -86,7 +127,7 @@
} }
html += '<li>'; html += '<li>';
html += '<a href="#">'; html += '<a data-profileindex="' + i + '" class="lnkEditSubProfile" href="#">';
html += '<p>Container: ' + (profile.Container || 'All') + '</p>'; html += '<p>Container: ' + (profile.Container || 'All') + '</p>';
@ -101,7 +142,7 @@
html += '</a>'; html += '</a>';
html += '<a href="#" data-icon="delete" class="btnDeleteProfile" data-profileIndex="' + i + '">Delete</a>'; html += '<a href="#" data-icon="delete" class="btnDeleteProfile" data-profileindex="' + i + '">Delete</a>';
html += '</li>'; html += '</li>';
} }
@ -112,9 +153,16 @@
$('.btnDeleteProfile', elem).on('click', function () { $('.btnDeleteProfile', elem).on('click', function () {
var index = this.getAttribute('data-profileIndex'); var index = this.getAttribute('data-profileindex');
deleteDirectPlayProfile(page, index); deleteDirectPlayProfile(page, index);
}); });
$('.lnkEditSubProfile', elem).on('click', function () {
var index = parseInt(this.getAttribute('data-profileindex'));
editDirectPlayProfile(page, currentProfile.DirectPlayProfiles[index]);
});
} }
function deleteDirectPlayProfile(page, index) { function deleteDirectPlayProfile(page, index) {
@ -160,7 +208,7 @@
html += '</a>'; html += '</a>';
html += '<a href="#" data-icon="delete" class="btnDeleteProfile" data-profileIndex="' + i + '">Delete</a>'; html += '<a href="#" data-icon="delete" class="btnDeleteProfile" data-profileindex="' + i + '">Delete</a>';
html += '</li>'; html += '</li>';
} }
@ -171,7 +219,7 @@
$('.btnDeleteProfile', elem).on('click', function () { $('.btnDeleteProfile', elem).on('click', function () {
var index = this.getAttribute('data-profileIndex'); var index = this.getAttribute('data-profileindex');
deleteTranscodingProfile(page, index); deleteTranscodingProfile(page, index);
}); });
} }
@ -218,7 +266,7 @@
html += '</a>'; html += '</a>';
html += '<a href="#" data-icon="delete" class="btnDeleteProfile" data-profileIndex="' + i + '">Delete</a>'; html += '<a href="#" data-icon="delete" class="btnDeleteProfile" data-profileindex="' + i + '">Delete</a>';
html += '</li>'; html += '</li>';
} }
@ -229,7 +277,7 @@
$('.btnDeleteProfile', elem).on('click', function () { $('.btnDeleteProfile', elem).on('click', function () {
var index = this.getAttribute('data-profileIndex'); var index = this.getAttribute('data-profileindex');
deleteContainerProfile(page, index); deleteContainerProfile(page, index);
}); });
} }
@ -278,7 +326,7 @@
html += '</a>'; html += '</a>';
html += '<a href="#" data-icon="delete" class="btnDeleteProfile" data-profileIndex="' + i + '">Delete</a>'; html += '<a href="#" data-icon="delete" class="btnDeleteProfile" data-profileindex="' + i + '">Delete</a>';
html += '</li>'; html += '</li>';
} }
@ -289,7 +337,7 @@
$('.btnDeleteProfile', elem).on('click', function () { $('.btnDeleteProfile', elem).on('click', function () {
var index = this.getAttribute('data-profileIndex'); var index = this.getAttribute('data-profileindex');
deleteCodecProfile(page, index); deleteCodecProfile(page, index);
}); });
} }
@ -345,7 +393,7 @@
html += '</a>'; html += '</a>';
html += '<a href="#" data-icon="delete" class="btnDeleteProfile" data-profileIndex="' + i + '">Delete</a>'; html += '<a href="#" data-icon="delete" class="btnDeleteProfile" data-profileindex="' + i + '">Delete</a>';
html += '</li>'; html += '</li>';
} }
@ -356,7 +404,7 @@
$('.btnDeleteProfile', elem).on('click', function () { $('.btnDeleteProfile', elem).on('click', function () {
var index = this.getAttribute('data-profileIndex'); var index = this.getAttribute('data-profileindex');
deleteMediaProfile(page, index); 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 () { }).on('pageshow', "#dlnaProfilePage", function () {
var page = this; var page = this;
@ -466,6 +536,16 @@
saveProfile(page, currentProfile); saveProfile(page, currentProfile);
return false;
},
onDirectPlayFormSubmit: function () {
var form = this;
var page = $(form).parents('.page');
saveDirectPlayProfile(page);
return false; return false;
} }
}; };

View file

@ -81,7 +81,7 @@
Dashboard.getCurrentUser().done(function (user) { Dashboard.getCurrentUser().done(function (user) {
if (MediaPlayer.canPlay(item, user)) { if (MediaController.canPlay(item)) {
$('#playButtonContainer', page).show(); $('#playButtonContainer', page).show();
} else { } else {
$('#playButtonContainer', page).hide(); $('#playButtonContainer', page).hide();
@ -518,12 +518,7 @@
$('#btnPlay', page).on('click', function () { $('#btnPlay', page).on('click', function () {
var userdata = currentItem.UserData || {}; var userdata = currentItem.UserData || {};
LibraryBrowser.showPlayMenu(this, currentItem.Name, currentItem.Type, "Audio", userdata.PlaybackPositionTicks); LibraryBrowser.showPlayMenu(this, currentItem.Id, currentItem.Type, false, "Audio", userdata.PlaybackPositionTicks);
});
$('#btnRemote', page).on('click', function () {
RemoteControl.showMenuForItem({ item: currentItem, context: getParameterByName('context') || '' });
}); });
}).on('pageshow', "#itemByNameDetailPage", function () { }).on('pageshow', "#itemByNameDetailPage", function () {

View file

@ -29,8 +29,6 @@
renderDetails(page, item, context); renderDetails(page, item, context);
LibraryBrowser.renderDetailPageBackdrop(page, item); LibraryBrowser.renderDetailPageBackdrop(page, item);
$("#remoteButtonContainer", page).show();
if (user.Configuration.IsAdministrator) { if (user.Configuration.IsAdministrator) {
$('#editButtonContainer', page).show(); $('#editButtonContainer', page).show();
@ -38,21 +36,18 @@
$('#editButtonContainer', page).hide(); $('#editButtonContainer', page).hide();
} }
if (MediaPlayer.canPlay(item, user)) { var externalPlayUrl = getExternalPlayUrl(item);
$('#btnPlayExternal', page).attr('href', externalPlayUrl || '#');
var url = MediaPlayer.getPlayUrl(item); if (externalPlayUrl) {
$('#playExternalButtonContainer', page).show();
if (url) { $('#playButtonContainer', page).hide();
$('#playExternalButtonContainer', page).show(); }
$('#playButtonContainer', page).hide(); else if (MediaController.canPlay(item)) {
} else { $('#playButtonContainer', page).show();
$('#playButtonContainer', page).show(); $('#playExternalButtonContainer', page).hide();
$('#playExternalButtonContainer', page).hide(); }
} else {
$('#btnPlayExternal', page).attr('href', url || '#');
} else {
$('#playButtonContainer', page).hide(); $('#playButtonContainer', page).hide();
$('#playExternalButtonContainer', page).hide(); $('#playExternalButtonContainer', page).hide();
} }
@ -124,6 +119,22 @@
$('#btnEdit', page).attr('href', "edititemmetadata.html?id=" + id); $('#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) { function setPeopleHeader(page, item) {
if (item.Type == "Audio" || item.Type == "MusicAlbum" || item.MediaType == "Book" || item.MediaType == "Photo") { if (item.Type == "Audio" || item.Type == "MusicAlbum" || item.MediaType == "Book" || item.MediaType == "Photo") {
@ -1107,7 +1118,7 @@
attributes.push(createAttribute("Layout", stream.ChannelLayout)); attributes.push(createAttribute("Layout", stream.ChannelLayout));
} }
else if (stream.Channels) { else if (stream.Channels) {
attributes.push(createAttribute("Channels", stream.Channels + ' ch')); attributes.push(createAttribute("Channels", stream.Channels + ' ch'));
} }
if (stream.BitRate && stream.Codec != "mjpeg") { if (stream.BitRate && stream.Codec != "mjpeg") {
@ -1138,7 +1149,7 @@
if (version.Path) { if (version.Path) {
html += '<br/><span class="mediaInfoLabel">Path</span><span class="mediaInfoAttribute">' + version.Path + '</span>'; html += '<br/><span class="mediaInfoLabel">Path</span><span class="mediaInfoAttribute">' + version.Path + '</span>';
} }
return html; return html;
} }
@ -1162,7 +1173,7 @@
var href = "itemdetails.html?id=" + item.Id; 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 += '<a class="' + cssClass + '" href="' + href + '"' + onclick + '>'; html += '<a class="' + cssClass + '" href="' + href + '"' + onclick + '>';
@ -1286,7 +1297,10 @@
function play(startPosition) { function play(startPosition) {
MediaPlayer.play([currentItem], startPosition); MediaController.play({
items: [currentItem],
startPositionTicks: startPosition
});
} }
function splitVersions(page) { function splitVersions(page) {
@ -1317,7 +1331,7 @@
ApiClient.getLocalTrailers(Dashboard.getCurrentUserId(), currentItem.Id).done(function (trailers) { ApiClient.getLocalTrailers(Dashboard.getCurrentUserId(), currentItem.Id).done(function (trailers) {
MediaPlayer.play(trailers); MediaController.play({ items: trailers });
}); });
} }
@ -1335,7 +1349,7 @@
mediaType = "Audio"; 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 () { $('#btnPlayTrailer', page).on('click', function () {
@ -1347,19 +1361,6 @@
ApiClient.markPlayed(Dashboard.getCurrentUserId(), currentItem.Id, new Date()); 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 () { $('.btnSplitVersions', page).on('click', function () {
splitVersions(page); splitVersions(page);

View file

@ -211,7 +211,7 @@
html += '<td class="detailTableButtonsCell">'; html += '<td class="detailTableButtonsCell">';
html += '<button class="btnPlay" data-icon="play" type="button" data-iconpos="notext" onclick="LibraryBrowser.showPlayMenu(this, \'' + item.Id + '\', \'Audio\', \'Audio\');" data-inline="true" title="Play">Play</button>'; html += '<button class="btnPlay" data-icon="play" type="button" data-iconpos="notext" onclick="LibraryBrowser.showPlayMenu(this, \'' + item.Id + '\', \'Audio\', \'Audio\');" data-inline="true" title="Play">Play</button>';
html += '<button class="btnQueue" data-icon="plus" type="button" data-iconpos="notext" onclick="MediaPlayer.queue(\'' + item.Id + '\');" data-inline="true" title="Queue">Queue</button>'; html += '<button class="btnQueue" data-icon="plus" type="button" data-iconpos="notext" onclick="MediaController.queue(\'' + item.Id + '\');" data-inline="true" title="Queue">Queue</button>';
html += '</td>'; html += '</td>';
var num = item.IndexNumber; var num = item.IndexNumber;
@ -287,12 +287,10 @@
return html; return html;
}, },
showPlayMenu: function (positionTo, itemId, itemType, mediaType, resumePositionTicks) { showPlayMenu: function (positionTo, itemId, itemType, isFolder, mediaType, resumePositionTicks) {
var isPlaying = MediaPlayer.isPlaying(); if (!resumePositionTicks && mediaType != "Audio" && !isFolder) {
MediaController.play(itemId);
if (!isPlaying && !resumePositionTicks && mediaType != "Audio") {
MediaPlayer.playById(itemId);
return; return;
} }
@ -303,38 +301,22 @@
html += '<ul data-role="listview" style="min-width: 150px;">'; html += '<ul data-role="listview" style="min-width: 150px;">';
html += '<li data-role="list-divider" data-theme="b">Play Menu</li>'; html += '<li data-role="list-divider" data-theme="b">Play Menu</li>';
if (itemType == "MusicArtist") { html += '<li><a href="#" onclick="MediaController.play(\'' + itemId + '\');LibraryBrowser.closePlayMenu();">Play</a></li>';
html += '<li><a href="#" onclick="MediaPlayer.playArtist(\'' + itemId + '\');LibraryBrowser.closePlayMenu();">Play</a></li>';
} else if (itemType != "MusicGenre") { if (itemType == "Audio" || itemType == "MusicAlbum" || itemType == "MusicArtist" || itemType == "MusicGenre") {
html += '<li><a href="#" onclick="MediaPlayer.playById(\'' + itemId + '\');LibraryBrowser.closePlayMenu();">Play</a></li>'; html += '<li><a href="#" onclick="MediaController.instantMix(\'' + itemId + '\');LibraryBrowser.closePlayMenu();">Instant Mix</a></li>';
} }
if (itemType == "Audio") { if (isFolder || itemType == "MusicArtist" || itemType == "MusicGenre") {
html += '<li><a href="#" onclick="MediaPlayer.playInstantMixFromSong(\'' + itemId + '\');LibraryBrowser.closePlayMenu();">Instant Mix</a></li>'; html += '<li><a href="#" onclick="MediaController.shuffle(\'' + itemId + '\');LibraryBrowser.closePlayMenu();">Shuffle</a></li>';
}
else if (itemType == "MusicAlbum") {
html += '<li><a href="#" onclick="MediaPlayer.playInstantMixFromAlbum(\'' + itemId + '\');LibraryBrowser.closePlayMenu();">Instant Mix</a></li>';
html += '<li><a href="#" onclick="MediaPlayer.shuffleFolder(\'' + itemId + '\');LibraryBrowser.closePlayMenu();">Shuffle</a></li>';
}
else if (itemType == "MusicArtist") {
html += '<li><a href="#" onclick="MediaPlayer.playInstantMixFromArtist(\'' + itemId + '\');LibraryBrowser.closePlayMenu();">Instant Mix</a></li>';
html += '<li><a href="#" onclick="MediaPlayer.shuffleArtist(\'' + itemId + '\');LibraryBrowser.closePlayMenu();">Shuffle</a></li>';
}
else if (itemType == "MusicGenre") {
html += '<li><a href="#" onclick="MediaPlayer.playInstantMixFromMusicGenre(\'' + itemId + '\');LibraryBrowser.closePlayMenu();">Instant Mix</a></li>';
html += '<li><a href="#" onclick="MediaPlayer.shuffleMusicGenre(\'' + itemId + '\');LibraryBrowser.closePlayMenu();">Shuffle</a></li>';
} }
if (resumePositionTicks) { if (resumePositionTicks) {
html += '<li><a href="#" onclick="MediaPlayer.playById(\'' + itemId + '\', ' + resumePositionTicks + ');LibraryBrowser.closePlayMenu();">Resume</a></li>'; html += '<li><a href="#" onclick="MediaController.play({ids:[\'' + itemId + '\'],startPositionTicks:' + resumePositionTicks + '});LibraryBrowser.closePlayMenu();">Resume</a></li>';
} }
if (isPlaying) { if (MediaController.canQueueMediaType(mediaType)) {
if (itemType == "MusicArtist") { html += '<li><a href="#" onclick="MediaController.queue(\'' + itemId + '\');LibraryBrowser.closePlayMenu();">Queue</a></li>';
html += '<li><a href="#" onclick="MediaPlayer.queueArtist(\'' + itemId + '\');LibraryBrowser.closePlayMenu();">Queue</a></li>';
} else if (itemType != "MusicGenre") {
html += '<li><a href="#" onclick="MediaPlayer.queue(\'' + itemId + '\');LibraryBrowser.closePlayMenu();">Queue</a></li>';
}
} }
html += '</ul>'; html += '</ul>';

View file

@ -102,16 +102,16 @@
var buttonCount = 0; var buttonCount = 0;
if (MediaPlayer.canPlay(item, currentUser)) { if (MediaController.canPlay(item)) {
var resumePosition = (item.UserData || {}).PlaybackPositionTicks || 0; 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 += '<button type="button" data-mini="true" data-inline="true" data-icon="play" data-iconpos="notext" title="Play" onclick="' + onPlayClick + '" style="' + buttonMargin + '">Play</button>'; html += '<button type="button" data-mini="true" data-inline="true" data-icon="play" data-iconpos="notext" title="Play" onclick="' + onPlayClick + '" style="' + buttonMargin + '">Play</button>';
buttonCount++; buttonCount++;
if (item.MediaType == "Audio" || item.Type == "MusicAlbum") { if (item.MediaType == "Audio" || item.Type == "MusicAlbum") {
html += '<button type="button" data-mini="true" data-inline="true" data-icon="plus" data-iconpos="notext" title="Queue" onclick="MediaPlayer.queue(\'' + item.Id + '\');return false;" style="' + buttonMargin + '">Queue</button>'; html += '<button type="button" data-mini="true" data-inline="true" data-icon="plus" data-iconpos="notext" title="Queue" onclick="MediaController.queue(\'' + item.Id + '\');return false;" style="' + buttonMargin + '">Queue</button>';
buttonCount++; buttonCount++;
} }
} }
@ -126,10 +126,6 @@
buttonCount++; buttonCount++;
} }
if (!isPortrait || buttonCount < 3) {
html += '<button type="button" data-mini="true" data-inline="true" data-icon="wireless" data-iconpos="notext" title="Remote" class="btnRemoteControl" data-itemid="' + item.Id + '" style="' + buttonMargin + '">Remote</button>';
}
html += '</div>'; html += '</div>';
html += '</div>'; html += '</div>';
@ -142,22 +138,7 @@
var id = this.getAttribute('data-itemid'); var id = this.getAttribute('data-itemid');
ApiClient.getLocalTrailers(Dashboard.getCurrentUserId(), id).done(function (trailers) { ApiClient.getLocalTrailers(Dashboard.getCurrentUserId(), id).done(function (trailers) {
MediaPlayer.play(trailers); MediaController.play({ items: trailers });
});
return false;
}
function onRemoteControlButtonClick() {
var id = this.getAttribute('data-itemid');
ApiClient.getItem(Dashboard.getCurrentUserId(), id).done(function (item) {
RemoteControl.showMenuForItem({
item: item
});
}); });
return false; return false;
@ -248,7 +229,6 @@
innerElem.html(getOverlayHtml(item, user, elem)).trigger('create'); innerElem.html(getOverlayHtml(item, user, elem)).trigger('create');
$('.btnPlayTrailer', innerElem).on('click', onTrailerButtonClick); $('.btnPlayTrailer', innerElem).on('click', onTrailerButtonClick);
$('.btnRemoteControl', innerElem).on('click', onRemoteControlButtonClick);
}); });
innerElem.show().each(function () { innerElem.show().each(function () {

View file

@ -24,7 +24,7 @@
html += '<div class="viewMenuSecondary">'; html += '<div class="viewMenuSecondary">';
html += '<button class="btnCast btnDefaultCast" type="button" data-role="none" style="display:none;"></button>'; html += '<button class="btnCast btnDefaultCast" type="button" data-role="none"></button>';
html += '<a class="viewMenuLink btnCurrentUser" href="#" onclick="Dashboard.showUserFlyout(this);">'; html += '<a class="viewMenuLink btnCurrentUser" href="#" onclick="Dashboard.showUserFlyout(this);">';
@ -174,6 +174,20 @@
window.LibraryMenu = { window.LibraryMenu = {
showLibraryMenu: showLibraryMenu 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 () { $(document).on('pageinit', ".libraryPage", function () {
@ -210,6 +224,9 @@
}); });
}); });
} }
updateCastIcon();
}).on('pageshow', ".libraryPage", function () { }).on('pageshow', ".libraryPage", function () {
var page = this; var page = this;
@ -224,4 +241,13 @@
} }
}); });
$(function() {
$(MediaController).on('playerchange', function () {
updateCastIcon();
});
});
})(window, document, jQuery); })(window, document, jQuery);

View file

@ -146,7 +146,7 @@
Dashboard.getCurrentUser().done(function (user) { Dashboard.getCurrentUser().done(function (user) {
if (MediaPlayer.canPlay(item, user)) { if (MediaController.canPlay(item)) {
$('#playButtonContainer', page).show(); $('#playButtonContainer', page).show();
} else { } else {
$('#playButtonContainer', page).hide(); $('#playButtonContainer', page).hide();
@ -296,12 +296,7 @@
$('#btnPlay', page).on('click', function () { $('#btnPlay', page).on('click', function () {
var userdata = currentItem.UserData || {}; var userdata = currentItem.UserData || {};
LibraryBrowser.showPlayMenu(this, currentItem.Id, currentItem.Type, currentItem.MediaType, userdata.PlaybackPositionTicks); LibraryBrowser.showPlayMenu(this, currentItem.Id, currentItem.Type, false, currentItem.MediaType, userdata.PlaybackPositionTicks);
});
$('#btnRemote', page).on('click', function () {
RemoteControl.showMenuForItem({ item: currentItem, context: 'livetv' });
}); });
$('#btnEdit', page).on('click', function () { $('#btnEdit', page).on('click', function () {

View file

@ -114,7 +114,7 @@
ApiClient.getLiveTvChannel(currentItem.ChannelId, Dashboard.getCurrentUserId()).done(function (channel) { ApiClient.getLiveTvChannel(currentItem.ChannelId, Dashboard.getCurrentUserId()).done(function (channel) {
var userdata = channel.UserData || {}; 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); deleteTimer(page, currentItem.TimerId);
}); });
$('#btnRemote', page).on('click', function () {
RemoteControl.showMenuForItem({
item: currentItem,
context: 'livetv'
});
});
}).on('pageshow', "#liveTvProgramPage", function () { }).on('pageshow', "#liveTvProgramPage", function () {
var page = this; var page = this;

View file

@ -27,7 +27,7 @@
var mediaType = currentItem.MediaType; 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) { function renderRecording(page, item) {
@ -68,7 +68,7 @@
Dashboard.getCurrentUser().done(function (user) { Dashboard.getCurrentUser().done(function (user) {
if (MediaPlayer.canPlay(item, user)) { if (MediaController.canPlay(item)) {
$('#playButtonContainer', page).show(); $('#playButtonContainer', page).show();
} else { } else {
$('#playButtonContainer', page).hide(); $('#playButtonContainer', page).hide();
@ -107,15 +107,6 @@
$('#btnDelete', page).on('click', deleteRecording); $('#btnDelete', page).on('click', deleteRecording);
$('#btnPlay', page).on('click', play); $('#btnPlay', page).on('click', play);
$('#btnRemote', page).on('click', function () {
RemoteControl.showMenuForItem({
item: currentItem,
context: 'livetv'
});
});
}).on('pagebeforeshow', "#liveTvRecordingPage", function () { }).on('pagebeforeshow', "#liveTvRecordingPage", function () {
var page = this; var page = this;

View file

@ -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 += '<fieldset data-role="controlgroup" data-mini="true">';
html += '<legend>Select Player:</legend>';
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 += '<input type="radio" class="radioSelectPlayerTarget" name="radioSelectPlayerTarget" data-mediatypes="' + target.playableMediaTypes.join(',') + '" data-playername="' + target.playerName + '" data-targetid="' + target.id + '" data-targetname="' + target.name + '" id="' + id + '" value="' + target.id + '"' + checkedHtml + '>';
html += '<label for="' + id + '" style="font-weight:normal;">' + target.name;
if (target.appName) {
html += '<br/><span style="color:#bbb;">' + target.appName + '</span>';
}
html += '</label>';
}
html += '</fieldset>';
return html;
}
function showPlayerSelection() {
var promise = MediaController.getTargets();
var html = '<div data-role="panel" data-position="right" data-display="overlay" id="playerFlyout" data-theme="b">';
html += '<div class="players"></div>';
html += '</div>';
$(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);

View file

@ -453,8 +453,6 @@
html += "</div>"; html += "</div>";
} }
html += '<div style="padding: 5px;"><a data-role="button" data-icon="gear" href="usersettings.html?userid=' + Dashboard.getCurrentUserId() + '" data-mini="true" data-theme="a">Preferences</a></div>';
return html; return html;
}; };
@ -528,8 +526,6 @@
html += "</div>"; html += "</div>";
} }
html += '<div style="padding: 5px;"><a data-role="button" data-icon="gear" href="usersettings.html?userid=' + Dashboard.getCurrentUserId() + '" data-mini="true" data-theme="a">Preferences</a></div>';
return html; return html;
}; };

View file

@ -13,15 +13,31 @@
var canClientSeek; var canClientSeek;
var currentPlaylistIndex = 0; var currentPlaylistIndex = 0;
self.currentTimeElement; self.currentTimeElement = null;
self.unmuteButton; self.unmuteButton = null;
self.muteButton; self.muteButton = null;
self.positionSlider; self.positionSlider = null;
self.isPositionSliderActive; self.isPositionSliderActive = null;
self.volumeSlider; self.volumeSlider = null;
self.startTimeTicksOffset; self.startTimeTicksOffset = null;
self.playlist = []; 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) { self.updateCanClientSeek = function (elem) {
var duration = elem.duration; var duration = elem.duration;
canClientSeek = duration && !isNaN(duration) && duration != Number.POSITIVE_INFINITY && duration != Number.NEGATIVE_INFINITY; canClientSeek = duration && !isNaN(duration) && duration != Number.POSITIVE_INFINITY && duration != Number.NEGATIVE_INFINITY;
@ -275,7 +291,7 @@
audioBitrate: audioBitrate, audioBitrate: audioBitrate,
videoBitrate: videoBitrate videoBitrate: videoBitrate
}; };
if (params.videoCodec == 'h264') { if (params.videoCodec == 'h264') {
params.profile = 'baseline'; params.profile = 'baseline';
params.level = '3'; params.level = '3';
@ -284,137 +300,100 @@
return params; return params;
}; };
self.canPlay = function (item, user) { self.canQueueMediaType = function (mediaType) {
if (item.PlayAccess != 'Full') { return currentItem && currentItem.MediaType == mediaType;
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);
}; };
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) { self.play = function (options) {
if (mediaType === "Video") {
return true;
}
if (mediaType === "Audio") {
return true;
}
return false;
};
self.play = function (items, startPosition) {
Dashboard.getCurrentUser().done(function (user) { 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); } else {
return;
}
else if (videoType == "bluray") {
self.playWithWarning(items, startPosition, user, "bluraystreamconfirmed", "Blu-ray Folder Streaming", expirementalText); self.getItemsForPlayback({
return;
}
else if (videoType == "iso") {
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); translateItemsForPlayback(result.Items).done(function (items) {
return;
}
else if (isoType == "bluray") {
self.playWithWarning(items, startPosition, user, "blurayisostreamconfirmed", "Blu-ray Iso Streaming", expirementalText); self.playInternal(items[0], options.startPositionTicks, user);
return;
}
}
self.playInternal(items[0], startPosition, user); self.playlist = items;
self.onPlaybackStarted(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.getBitrateSetting = function () {
self.playlist = items;
currentPlaylistIndex = 0;
};
self.getBitrateSetting = function() {
return parseInt(localStorage.getItem('preferredVideoBitrate') || '') || 1500000; return parseInt(localStorage.getItem('preferredVideoBitrate') || '') || 1500000;
}; };
@ -569,163 +548,11 @@
query.Limit = query.Limit || 100; query.Limit = query.Limit || 100;
query.Fields = getItemFields; query.Fields = getItemFields;
query.ExcludeLocationTypes = "Virtual";
return ApiClient.getItems(userId, query); 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.removeFromPlaylist = function (index) {
self.playlist.remove(index); self.playlist.remove(index);
@ -797,51 +624,69 @@
} }
}; };
self.queue = function (id) { self.queue = function (options) {
if (!currentMediaElement) { if (!currentMediaElement) {
self.playById(id); self.play(options);
return; return;
} }
ApiClient.getItem(Dashboard.getCurrentUserId(), id).done(function (item) { Dashboard.getCurrentUser().done(function (user) {
if (item.IsFolder) { if (options.items) {
self.getItemsForPlayback({ translateItemsForPlayback(options.items).done(function (items) {
ParentId: id,
Recursive: true,
SortBy: "SortName"
}).done(function (result) {
self.queueItems(result.Items);
self.queueItems(items);
}); });
} else { } 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, Dashboard.getCurrentUser().done(function (user) {
Recursive: true,
SortBy: "Album,SortName",
IncludeItemTypes: "Audio"
}).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 () { 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 () { self.stop = function () {
var elem = currentMediaElement; var elem = currentMediaElement;
@ -933,14 +880,6 @@
return currentMediaElement; return currentMediaElement;
}; };
self.showSendMediaMenu = function () {
RemoteControl.showMenuForItem({
item: currentItem
});
};
self.bindPositionSlider = function () { self.bindPositionSlider = function () {
self.positionSlider.on('slidestart', function (e) { self.positionSlider.on('slidestart', function (e) {
@ -1220,4 +1159,8 @@
window.MediaPlayer = new mediaPlayer(); 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); })(document, setTimeout, clearTimeout, screen, localStorage, $, setInterval, window);

View file

@ -1,570 +1,5 @@
(function (window, document, $) { (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 = '<div data-role="popup" class="remoteControlFlyout" data-transition="slidedown" data-theme="a">';
html += '<a href="#" data-rel="back" data-role="button" data-icon="delete" data-iconpos="notext" class="ui-btn-right" data-theme="b">Close</a>';
html += '<div class="ui-bar-b" style="text-align:center;">';
html += '<div style="margin:.5em 0;">Remote Control</div>';
html += '</div>';
html += '<div style="padding: 1em;">';
html += '<form id="sendToForm">';
html += '<input type="hidden" value="PlayNow" id="fldPlayCommand" />';
html += '<div class="sessionsPopupContent">';
html += '<div class="circle"></div><div class="circle1"></div>';
html += '</div>';
html += '<p style="text-align:center;margin:.75em 0 0;">';
html += '<span id="playButtonContainer" style="display:none;"><button onclick="$(\'#fldPlayCommand\').val(\'PlayNow\');" type="submit" data-icon="play" data-mini="true" data-inline="true">Play</button></span>';
html += '<span id="resumeButtonContainer" style="display:none;"><button onclick="$(\'#fldPlayCommand\').val(\'Resume\');" type="submit" data-icon="play" data-mini="true" data-inline="true">Resume</button></span>';
html += '<span id="queueButtonContainer" style="display:none;"><button onclick="$(\'#fldPlayCommand\').val(\'PlayLast\');" type="submit" data-icon="plus" data-mini="true" data-inline="true">Queue</button></span>';
html += '<span id="browseButtonContainer" style="display:none;"><button onclick="$(\'#fldPlayCommand\').val(\'Browse\');" type="submit" data-icon="eye" data-mini="true" data-inline="true">View</button></span>';
html += '</p>';
html += '</form></div>';
html += '</div>';
$(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('<p>There are currently no available media browser sessions to control.</p>');
$('.remoteControlFlyout').popup("reposition", {});
return;
}
var item = options.item;
var html = '';
html += '<div style="margin-top:0;">';
html += '<select id="selectCommand" data-mini="true">';
// Default for virtual & IBN types
var playLabel = 'View';
if (item.LocationType != "Virtual") {
if (item.IsFolder) {
playLabel = "Play All";
}
else if (item.MediaType == "Video") {
playLabel = "Play from beginning";
}
else if (item.MediaType) {
playLabel = "Play";
}
}
html += '<option value="Play" selected>' + playLabel + '</label>';
if (item.LocalTrailerCount) {
html += '<option value="Trailer">Play trailer</label>';
}
if (item.SpecialFeatureCount) {
html += '<option value="SpecialFeature">Play special feature</label>';
}
if (options.themeSongs) {
html += '<option value="ThemeSong">Play theme song</label>';
}
if (options.themeVideos) {
html += '<option value="ThemeVideo">Play theme video</label>';
}
html += '</select>';
html += '</div>';
html += '<div class="playFromMenu" style="display:none;"></div>';
html += '<div class="trailers" style="display:none;"></div>';
html += '<div class="specialFeatures" style="display:none;"></div>';
html += '<div class="themeSongs" style="display:none;"></div>';
html += '<div class="themeVideos" style="display:none;"></div>';
html += '<h4 style="margin: 1em 0 .5em;">Select Device</h4>';
html += '<table class="tblRemoteControl">';
html += '<thead><tr>';
html += '<th></th>';
html += '<th>Device</th>';
html += '</tr></thead>';
html += '<tbody>';
for (var i = 0, length = sessions.length; i < length; i++) {
var session = sessions[i];
html += '<tr class="trSession" data-queue="' + session.QueueableMediaTypes.join(',') + '" data-sessionid="' + session.Id + '">';
html += '<td class="tdSelectSession"></td>';
html += '<td>' + session.DeviceName;
if (session.UserName) {
html += ' - ' + session.UserName;
}
html += '</td>';
html += '</tr>';
}
html += '</tbody>';
html += '</table>';
html += '</div>';
elem.html(html).trigger('create');
$('.tdSelectSession', elem).html('<input type="radio" class="chkClient" name="chkClient" />');
$('.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 += '<h4 style="margin: 1em 0 .5em;">' + header + '</h4>';
html += '<div class="playMenuOptions">';
html += '<table class="tblRemoteControl tblRemoteControlNoHeader">';
html += '<tbody>';
for (var i = 0, length = videos.length; i < length; i++) {
var video = videos[i];
html += '<tr class="trItem" data-id="' + video.Id + '">';
html += '<td class="tdSelectItem"></td>';
html += '<td class="tdRemoteControlImage">';
var imgUrl;
if (video.ImageTags && video.ImageTags.Primary) {
imgUrl = ApiClient.getImageUrl(video.Id, {
maxheight: 80,
tag: video.ImageTags.Primary,
type: "Primary"
});
html += '<img src="' + imgUrl + '" />';
}
html += '</td>';
html += '<td>' + video.Name;
if (video.RunTimeTicks) {
html += '<br/>' + Dashboard.getDisplayTime(video.RunTimeTicks);
}
html += '</td>';
html += '</tr>';
}
html += '</tbody>';
html += '</table>';
html += '</div>';
elem.html(html);
$('.tdSelectItem', elem).html('<input type="radio" class="chkSelectItem" name="chkSelectItem" />');
$('.chkSelectItem:first', elem).checked(true);
}
function showMenu(sessions, options) { function showMenu(sessions, options) {
var html = '<div data-role="popup" data-transition="slidedown" class="remoteControlFlyout" data-theme="a">'; var html = '<div data-role="popup" data-transition="slidedown" class="remoteControlFlyout" data-theme="a">';
@ -965,10 +400,6 @@
ControllableByUserId: Dashboard.getCurrentUserId() ControllableByUserId: Dashboard.getCurrentUserId()
}; };
self.showMenuForItem = function (options) {
showMenuForItem(options, ApiClient.getSessions(sessionQuery));
};
self.showMenu = function (options) { self.showMenu = function (options) {
ApiClient.getSessions(sessionQuery).done(function (sessions) { ApiClient.getSessions(sessionQuery).done(function (sessions) {
@ -980,4 +411,99 @@
window.RemoteControl = new remoteControl(); 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); })(window, document, jQuery);

View file

@ -882,51 +882,6 @@ var Dashboard = {
Dashboard.onBrowseCommand(msg.Data); 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") { else if (msg.MessageType === "SystemCommand") {
if (msg.Data === 'GoHome') { if (msg.Data === 'GoHome') {
@ -1365,8 +1320,6 @@ $(function () {
videoPlayerHtml += '<button onclick="MediaPlayer.showChaptersFlyout();" id="video-chaptersButton" class="mediaButton chaptersButton" title="Scenes" type="button" data-icon="video" data-iconpos="notext" data-inline="true">Scenes</button>'; videoPlayerHtml += '<button onclick="MediaPlayer.showChaptersFlyout();" id="video-chaptersButton" class="mediaButton chaptersButton" title="Scenes" type="button" data-icon="video" data-iconpos="notext" data-inline="true">Scenes</button>';
videoPlayerHtml += '<div class="mediaFlyoutContainer"><div id="video-chaptersFlyout" style="display:none;" class="mediaPlayerFlyout chaptersFlyout"></div></div>'; videoPlayerHtml += '<div class="mediaFlyoutContainer"><div id="video-chaptersFlyout" style="display:none;" class="mediaPlayerFlyout chaptersFlyout"></div></div>';
videoPlayerHtml += '<button onclick="MediaPlayer.showSendMediaMenu();" id="video-sendMediaButton" class="mediaButton sendMediaButton" title="Remote" type="button" data-icon="wireless" data-iconpos="notext" data-inline="true">Remote</button>';
videoPlayerHtml += '<button onclick="MediaPlayer.toggleVideoPlayerMenu();" id="video-videoPlayerMenuButton" class="mediaButton videoPlayerMenuButton" title="Menu" type="button" data-icon="bars" data-iconpos="notext" data-inline="true">Menu</button>'; videoPlayerHtml += '<button onclick="MediaPlayer.toggleVideoPlayerMenu();" id="video-videoPlayerMenuButton" class="mediaButton videoPlayerMenuButton" title="Menu" type="button" data-icon="bars" data-iconpos="notext" data-inline="true">Menu</button>';
videoPlayerHtml += '</div>'; // videoControls videoPlayerHtml += '</div>'; // videoControls
@ -1422,8 +1375,6 @@ $(function () {
footerHtml += '<button onclick="MediaPlayer.toggleFullscreen();" id="fullscreenButton" class="mediaButton fullscreenButton" title="Fullscreen" type="button" data-icon="action" data-iconpos="notext" data-inline="true">Fullscreen</button>'; footerHtml += '<button onclick="MediaPlayer.toggleFullscreen();" id="fullscreenButton" class="mediaButton fullscreenButton" title="Fullscreen" type="button" data-icon="action" data-iconpos="notext" data-inline="true">Fullscreen</button>';
footerHtml += '<button onclick="MediaPlayer.showSendMediaMenu();" id="sendMediaButton" class="mediaButton sendMediaButton" title="Remote" type="button" data-icon="wireless" data-iconpos="notext" data-inline="true">Remote</button>';
footerHtml += '</div>'; footerHtml += '</div>';
footerHtml += '<div id="footerNotifications"></div>'; footerHtml += '<div id="footerNotifications"></div>';