mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
extract nowplayingbar into standalone widget to work with any player
This commit is contained in:
parent
ad3f285ded
commit
bd697d36fc
15 changed files with 879 additions and 715 deletions
|
@ -111,7 +111,7 @@
|
||||||
|
|
||||||
#mediaPlayer .ui-slider-handle {
|
#mediaPlayer .ui-slider-handle {
|
||||||
height: 12px !important;
|
height: 12px !important;
|
||||||
margin-top: -7px !important;
|
margin-top: -7px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#videoPlayer.fullscreenVideo #videoControls {
|
#videoPlayer.fullscreenVideo #videoControls {
|
||||||
|
@ -212,10 +212,6 @@
|
||||||
/****************************************/
|
/****************************************/
|
||||||
|
|
||||||
@media all and (max-width: 1200px), all and (max-height: 720px) {
|
@media all and (max-width: 1200px), all and (max-height: 720px) {
|
||||||
#videoControls .nowPlayingMediaInfo {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#videoControls .currentTime {
|
#videoControls .currentTime {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
min-width: 120px;
|
min-width: 120px;
|
||||||
|
@ -370,4 +366,87 @@
|
||||||
|
|
||||||
.cursor-inactive {
|
.cursor-inactive {
|
||||||
cursor: none;
|
cursor: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mediaFlyoutContainer {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mediaPlayerFlyout {
|
||||||
|
width: 200px;
|
||||||
|
color: #000;
|
||||||
|
background-color: #fff;
|
||||||
|
border: 1px solid #999;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 99999;
|
||||||
|
bottom: 78px;
|
||||||
|
margin-left: -125px;
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chaptersFlyout, .audioTracksFlyout {
|
||||||
|
width: 250px;
|
||||||
|
margin-left: -150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mediaFlyoutOption {
|
||||||
|
display: block;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #000;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mediaFlyoutOption:hover, .mediaFlyoutOption:focus {
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectedMediaFlyoutOption {
|
||||||
|
background-color: #d9F4FF;
|
||||||
|
background-image: url(images/media/selected.png);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: right top;
|
||||||
|
background-size: 16px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mediaFlyoutOptionImage {
|
||||||
|
display: inline-block;
|
||||||
|
width: 15%;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mediaFlyoutOptionImage + .mediaFlyoutOptionContent {
|
||||||
|
vertical-align: top;
|
||||||
|
display: inline-block;
|
||||||
|
width: 85%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chaptersFlyout .mediaFlyoutOptionImage {
|
||||||
|
width: 40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chaptersFlyout .mediaFlyoutOptionImage + .mediaFlyoutOptionContent {
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mediaFlyoutOptionName {
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-left: 5px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mediaFlyoutOptionSecondaryText {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: normal;
|
||||||
|
margin-top: 3px;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
|
|
@ -1,21 +1,9 @@
|
||||||
/* Now playing bar */
|
/* Now playing bar */
|
||||||
.nowPlayingBar {
|
.nowPlayingBar {
|
||||||
padding: 6px 0 20px 0;
|
padding: 10px 0 14px 0;
|
||||||
border-top: 2px solid green;
|
border-top: 2px solid green;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nowPlayingBar .barBackground {
|
|
||||||
border-top: 2px solid green;
|
|
||||||
position: absolute;
|
|
||||||
margin: -8px -0.5em -22px !important;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nowPlayingBar > *:not(#mediaElement):not(.mediaFlyoutContainer):not(.barBackground ) {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nowPlayingBarImage {
|
.nowPlayingBarImage {
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
}
|
}
|
||||||
|
@ -29,27 +17,32 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nowPlayingMediaInfo div {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nowPlayingMediaInfo a {
|
|
||||||
margin-right: .25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.nowPlayingMediaInfo {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nowPlayingText {
|
.nowPlayingText {
|
||||||
position: relative;
|
display: inline-block;
|
||||||
top: -3px;
|
|
||||||
margin-left: 3px;
|
|
||||||
margin-right: 2em;
|
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
position: relative;
|
||||||
|
top: -7px;
|
||||||
|
margin-left: 3px;
|
||||||
|
max-width: 200px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-right: 2em;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nowPlayingDoubleText {
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingImage {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingImage img {
|
||||||
|
height: 40px;
|
||||||
|
margin-right: .5em;
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
|
||||||
.mediaButton img {
|
.mediaButton img {
|
||||||
height: 24px;
|
height: 24px;
|
||||||
}
|
}
|
||||||
|
@ -60,7 +53,6 @@
|
||||||
top: -10px;
|
top: -10px;
|
||||||
max-width: 110px;
|
max-width: 110px;
|
||||||
margin-right: 2em;
|
margin-right: 2em;
|
||||||
font-size: 14px;
|
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,125 +119,27 @@ input[type="range"]::-ms-fill-upper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 800px) {
|
@media all and (max-width: 800px) {
|
||||||
#nowPlayingBar .volumeButton, #nowPlayingBar .volumeSliderContainer, #nowPlayingBar .muteButton, #nowPlayingBar .unmuteButton, #nowPlayingBar .nowPlayingMediaInfo {
|
|
||||||
display: none; /*!important;*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (max-width: 650px) {
|
#nowPlayingBar .mediaButton {
|
||||||
#nowPlayingBar .nowPlayingMediaInfo {
|
margin-top: 0;
|
||||||
display: none;
|
margin-bottom: 0;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (max-width: 600px) {
|
|
||||||
#nowPlayingBar .chaptersButton, #nowPlayingBar .audioTracksButton {
|
|
||||||
display: none; /*!important;*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#nowPlayingBar .positionSliderContainer, #nowPlayingBar .currentTime {
|
#nowPlayingBar .mediaButton:not(#playButton):not(#pauseButton) {
|
||||||
top: 0!important;
|
display: none;
|
||||||
position: relative!important;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (max-width: 500px) {
|
#nowPlayingBar #playButton, #nowPlayingBar #pauseButton {
|
||||||
#nowPlayingBar .positionSliderContainer {
|
float: right;
|
||||||
width: 80px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#nowPlayingBar .previousTrackButton, #nowPlayingBar .nextTrackButton {
|
#nowPlayingBar .currentTime, #nowPlayingBar .positionSliderContainer, #nowPlayingBar .volumeSliderContainer, #nowPlayingBar .muteButton, #nowPlayingBar .unmuteButton {
|
||||||
display: none; /*!important;*/
|
display: none !important;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (max-width: 400px) {
|
|
||||||
#nowPlayingBar .playlistButton {
|
|
||||||
display: none; /*!important;*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaFlyoutContainer {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaPlayerFlyout {
|
|
||||||
width: 200px;
|
|
||||||
color: #000;
|
|
||||||
background-color: #fff;
|
|
||||||
border: 1px solid #999;
|
|
||||||
position: absolute;
|
|
||||||
z-index: 99999;
|
|
||||||
bottom: 78px;
|
|
||||||
margin-left: -125px;
|
|
||||||
max-height: 300px;
|
|
||||||
overflow-y: auto;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chaptersFlyout,.audioTracksFlyout {
|
|
||||||
width: 250px;
|
|
||||||
margin-left: -150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaFlyoutOption {
|
|
||||||
display: block;
|
|
||||||
text-decoration: none;
|
|
||||||
color: #000;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaFlyoutOption:hover, .mediaFlyoutOption:focus {
|
|
||||||
background-color: #eee;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.selectedMediaFlyoutOption {
|
.nowPlayingBar {
|
||||||
background-color: #d9F4FF;
|
padding: 10px 5px 10px 0;
|
||||||
background-image: url(images/media/selected.png);
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: right top;
|
|
||||||
background-size: 16px 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaFlyoutOptionImage {
|
|
||||||
display: inline-block;
|
|
||||||
width: 15%;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaFlyoutOptionImage + .mediaFlyoutOptionContent {
|
|
||||||
vertical-align: top;
|
|
||||||
display: inline-block;
|
|
||||||
width: 85%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.chaptersFlyout .mediaFlyoutOptionImage {
|
|
||||||
width: 40%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chaptersFlyout .mediaFlyoutOptionImage + .mediaFlyoutOptionContent {
|
|
||||||
width: 60%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaFlyoutOptionName {
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
padding-left: 5px;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaFlyoutOptionSecondaryText {
|
|
||||||
font-size: 13px;
|
|
||||||
color: #333;
|
|
||||||
font-weight: normal;
|
|
||||||
margin-top: 3px;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
padding-left: 5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1440px) {
|
@media (min-width: 1440px) {
|
||||||
|
@ -253,3 +147,16 @@ input[type="range"]::-ms-fill-upper {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mediaPlayerAudioContainer {
|
||||||
|
position: fixed;
|
||||||
|
top: 40%;
|
||||||
|
text-align: center;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mediaPlayerAudioContainerInner {
|
||||||
|
padding: 1em;
|
||||||
|
background: #222;
|
||||||
|
}
|
||||||
|
|
|
@ -241,6 +241,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
function getCodecLimits() {
|
function getCodecLimits() {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
||||||
maxVideoAudioChannels: 6,
|
maxVideoAudioChannels: 6,
|
||||||
|
@ -608,7 +609,7 @@
|
||||||
url += '&maxheight=' + codecLimits.maxHeight;
|
url += '&maxheight=' + codecLimits.maxHeight;
|
||||||
|
|
||||||
url += '&videoCodec=h264';
|
url += '&videoCodec=h264';
|
||||||
url += '&audioCodec=aac';
|
url += '&audioCodec=aac,mp3';
|
||||||
|
|
||||||
url += '&audiosamplerate=' + codecLimits.maxSampleRate;
|
url += '&audiosamplerate=' + codecLimits.maxSampleRate;
|
||||||
url += '&mediasourceid=' + mediaSourceInfo.mediaSource.Id;
|
url += '&mediasourceid=' + mediaSourceInfo.mediaSource.Id;
|
||||||
|
@ -1004,7 +1005,7 @@
|
||||||
|
|
||||||
var castPlayer = new CastPlayer();
|
var castPlayer = new CastPlayer();
|
||||||
|
|
||||||
function chromecastPlayer(castPlayer) {
|
function chromecastPlayer() {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
@ -1018,11 +1019,11 @@
|
||||||
|
|
||||||
self.playlistIndex = 0;
|
self.playlistIndex = 0;
|
||||||
|
|
||||||
$.subscribe("/playback/complete", function (e) {
|
//$.subscribe("/playback/complete", function (e) {
|
||||||
if (self.playlistIndex < (self.playlist.items || []).length) {
|
// if (self.playlistIndex < (self.playlist.items || []).length) {
|
||||||
self.play(self.playlist);
|
// self.play(self.playlist);
|
||||||
}
|
// }
|
||||||
});
|
//});
|
||||||
|
|
||||||
////$(".positionSlider", "#footer").off("slidestart slidestop")
|
////$(".positionSlider", "#footer").off("slidestart slidestop")
|
||||||
//// .on('slidestart', function (e) {
|
//// .on('slidestart', function (e) {
|
||||||
|
@ -1043,13 +1044,13 @@
|
||||||
query.ExcludeLocationTypes = "Virtual";
|
query.ExcludeLocationTypes = "Virtual";
|
||||||
|
|
||||||
return ApiClient.getItems(userId, query);
|
return ApiClient.getItems(userId, query);
|
||||||
};
|
}
|
||||||
|
|
||||||
function queueItems (items) {
|
function queueItems (items) {
|
||||||
for (var i = 0, length = items.length; i < length; i++) {
|
for (var i = 0, length = items.length; i < length; i++) {
|
||||||
self.playlist.push(items[i]);
|
self.playlist.push(items[i]);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
function queueItemsNext(items) {
|
function queueItemsNext(items) {
|
||||||
var insertIndex = 1;
|
var insertIndex = 1;
|
||||||
|
@ -1057,7 +1058,7 @@
|
||||||
self.playlist.splice(insertIndex, 0, items[i]);
|
self.playlist.splice(insertIndex, 0, items[i]);
|
||||||
insertIndex++;
|
insertIndex++;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
function translateItemsForPlayback(items) {
|
function translateItemsForPlayback(items) {
|
||||||
var deferred = $.Deferred();
|
var deferred = $.Deferred();
|
||||||
|
@ -1100,7 +1101,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
return deferred.promise();
|
return deferred.promise();
|
||||||
};
|
}
|
||||||
|
|
||||||
self.play = function (options) {
|
self.play = function (options) {
|
||||||
console.log("play", options);
|
console.log("play", options);
|
||||||
|
@ -1371,7 +1372,7 @@
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaController.registerPlayer(new chromecastPlayer(castPlayer));
|
MediaController.registerPlayer(new chromecastPlayer());
|
||||||
|
|
||||||
$(MediaController).on('playerchange', function () {
|
$(MediaController).on('playerchange', function () {
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
if (person.PrimaryImageTag) {
|
if (person.PrimaryImageTag) {
|
||||||
|
|
||||||
imgUrl = ApiClient.getPersonImageUrl(person.Name, {
|
imgUrl = ApiClient.getPersonImageUrl(person.Name, {
|
||||||
height: 280,
|
width: 150,
|
||||||
tag: person.PrimaryImageTag,
|
tag: person.PrimaryImageTag,
|
||||||
type: "primary"
|
type: "primary"
|
||||||
});
|
});
|
||||||
|
|
|
@ -1238,7 +1238,7 @@
|
||||||
if (cast.PrimaryImageTag) {
|
if (cast.PrimaryImageTag) {
|
||||||
|
|
||||||
imgUrl = ApiClient.getPersonImageUrl(cast.Name, {
|
imgUrl = ApiClient.getPersonImageUrl(cast.Name, {
|
||||||
width: 130,
|
width: 100,
|
||||||
tag: cast.PrimaryImageTag,
|
tag: cast.PrimaryImageTag,
|
||||||
type: "primary"
|
type: "primary"
|
||||||
});
|
});
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
if (user.PrimaryImageTag) {
|
if (user.PrimaryImageTag) {
|
||||||
|
|
||||||
var url = ApiClient.getUserImageUrl(user.Id, {
|
var url = ApiClient.getUserImageUrl(user.Id, {
|
||||||
height: 40,
|
height: 24,
|
||||||
tag: user.PrimaryImageTag,
|
tag: user.PrimaryImageTag,
|
||||||
type: "Primary"
|
type: "Primary"
|
||||||
});
|
});
|
||||||
|
|
|
@ -175,6 +175,11 @@
|
||||||
})[0];
|
})[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.getCurrentPlayer = function () {
|
||||||
|
|
||||||
|
return currentPlayer;
|
||||||
|
};
|
||||||
|
|
||||||
self.pause = function () {
|
self.pause = function () {
|
||||||
currentPlayer.pause();
|
currentPlayer.pause();
|
||||||
};
|
};
|
||||||
|
@ -188,7 +193,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
self.seek = function (position) {
|
self.seek = function (position) {
|
||||||
currentPlayer.changeStream(position);
|
currentPlayer.seek(position);
|
||||||
};
|
};
|
||||||
|
|
||||||
self.currentPlaylistIndex = function (i) {
|
self.currentPlaylistIndex = function (i) {
|
||||||
|
|
|
@ -23,6 +23,13 @@
|
||||||
var idleState = true;
|
var idleState = true;
|
||||||
var remoteFullscreen = false;
|
var remoteFullscreen = false;
|
||||||
|
|
||||||
|
var muteButton = null;
|
||||||
|
var unmuteButton = null;
|
||||||
|
var volumeSlider = null;
|
||||||
|
var positionSlider;
|
||||||
|
var isPositionSliderActive;
|
||||||
|
var currentTimeElement;
|
||||||
|
|
||||||
self.initVideoPlayer = function () {
|
self.initVideoPlayer = function () {
|
||||||
video = playVideo(item, mediaSource, startPosition, user);
|
video = playVideo(item, mediaSource, startPosition, user);
|
||||||
return video;
|
return video;
|
||||||
|
@ -66,7 +73,7 @@
|
||||||
self.resetEnhancements = function () {
|
self.resetEnhancements = function () {
|
||||||
$("#mediaPlayer").hide();
|
$("#mediaPlayer").hide();
|
||||||
$('#videoPlayer').removeClass('fullscreenVideo');
|
$('#videoPlayer').removeClass('fullscreenVideo');
|
||||||
$("#videoControls").removeClass("inactive")
|
$("#videoControls").removeClass("inactive");
|
||||||
$("video").remove();
|
$("video").remove();
|
||||||
$("html").css("cursor", "default");
|
$("html").css("cursor", "default");
|
||||||
$(".ui-loader").hide();
|
$(".ui-loader").hide();
|
||||||
|
@ -155,7 +162,38 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function onPositionSliderChange() {
|
||||||
|
|
||||||
|
isPositionSliderActive = false;
|
||||||
|
|
||||||
|
var newPercent = parseInt(this.value);
|
||||||
|
|
||||||
|
var newPositionTicks = (newPercent / 100) * currentMediaSource.RunTimeTicks;
|
||||||
|
|
||||||
|
self.changeStream(Math.floor(newPositionTicks));
|
||||||
|
}
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
|
|
||||||
|
var parent = $("#mediaPlayer");
|
||||||
|
muteButton = $('.muteButton', parent);
|
||||||
|
unmuteButton = $('.unmuteButton', parent);
|
||||||
|
currentTimeElement = $('.currentTime', parent);
|
||||||
|
|
||||||
|
positionSlider = $(".positionSlider", parent).on('slidestart', function (e) {
|
||||||
|
|
||||||
|
isPositionSliderActive = true;
|
||||||
|
|
||||||
|
}).on('slidestop', onPositionSliderChange);
|
||||||
|
|
||||||
|
volumeSlider = $('.volumeSlider', parent).on('slidestop', function () {
|
||||||
|
|
||||||
|
var vol = this.value;
|
||||||
|
|
||||||
|
updateVolumeButtons(vol);
|
||||||
|
self.setVolume(vol * 100);
|
||||||
|
});
|
||||||
|
|
||||||
$('#video-chaptersFlyout').on('click', '.mediaFlyoutOption', function () {
|
$('#video-chaptersFlyout').on('click', '.mediaFlyoutOption', function () {
|
||||||
|
|
||||||
var ticks = parseInt(this.getAttribute('data-positionticks'));
|
var ticks = parseInt(this.getAttribute('data-positionticks'));
|
||||||
|
@ -264,6 +302,17 @@
|
||||||
}, 4000);
|
}, 4000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateVolumeButtons(vol) {
|
||||||
|
|
||||||
|
if (vol) {
|
||||||
|
muteButton.show();
|
||||||
|
unmuteButton.hide();
|
||||||
|
} else {
|
||||||
|
muteButton.hide();
|
||||||
|
unmuteButton.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function requestFullScreen(element) {
|
function requestFullScreen(element) {
|
||||||
|
|
||||||
// Supports most browsers and their versions.
|
// Supports most browsers and their versions.
|
||||||
|
@ -729,7 +778,7 @@
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
function playVideo(item, mediaSource, startPosition, user) {
|
function playVideo(item, mediaSource, startPosition, user) {
|
||||||
|
|
||||||
var mediaStreams = mediaSource.MediaStreams || [];
|
var mediaStreams = mediaSource.MediaStreams || [];
|
||||||
|
@ -771,7 +820,10 @@
|
||||||
videoBitrate: mp4Quality.videoBitrate,
|
videoBitrate: mp4Quality.videoBitrate,
|
||||||
audioBitrate: mp4Quality.audioBitrate,
|
audioBitrate: mp4Quality.audioBitrate,
|
||||||
VideoCodec: mp4Quality.videoCodec,
|
VideoCodec: mp4Quality.videoCodec,
|
||||||
AudioCodec: mp4Quality.audioCodec
|
AudioCodec: mp4Quality.audioCodec,
|
||||||
|
|
||||||
|
// None of the browsers seem to like this
|
||||||
|
EnableAutoStreamCopy: false
|
||||||
|
|
||||||
})) + seekParam;
|
})) + seekParam;
|
||||||
|
|
||||||
|
@ -781,7 +833,8 @@
|
||||||
AudioCodec: 'Vorbis',
|
AudioCodec: 'Vorbis',
|
||||||
maxWidth: webmQuality.maxWidth,
|
maxWidth: webmQuality.maxWidth,
|
||||||
videoBitrate: webmQuality.videoBitrate,
|
videoBitrate: webmQuality.videoBitrate,
|
||||||
audioBitrate: webmQuality.audioBitrate
|
audioBitrate: webmQuality.audioBitrate,
|
||||||
|
EnableAutoStreamCopy: false
|
||||||
|
|
||||||
})) + seekParam;
|
})) + seekParam;
|
||||||
|
|
||||||
|
@ -874,42 +927,26 @@
|
||||||
|
|
||||||
var video = $("video", videoElement);
|
var video = $("video", videoElement);
|
||||||
|
|
||||||
initialVolume = localStorage.getItem("volume") || 0.5;
|
initialVolume = self.getSavedVolume();
|
||||||
|
|
||||||
video.each(function () {
|
video.each(function () {
|
||||||
this.volume = initialVolume;
|
this.volume = initialVolume;
|
||||||
});
|
});
|
||||||
|
|
||||||
self.volumeSlider.val(initialVolume).slider('refresh');
|
volumeSlider.val(initialVolume).slider('refresh');
|
||||||
self.updateVolumeButtons(initialVolume);
|
updateVolumeButtons(initialVolume);
|
||||||
|
|
||||||
video.on("volumechange", function (e) {
|
video.on("volumechange", function (e) {
|
||||||
|
|
||||||
var muted = this.muted;
|
|
||||||
|
|
||||||
var vol = this.volume;
|
var vol = this.volume;
|
||||||
|
|
||||||
if (!muted && this.volume > 0) {
|
updateVolumeButtons(vol);
|
||||||
localStorage.setItem("volume", vol);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.muted = this.volume == 0;
|
|
||||||
|
|
||||||
self.updateVolumeButtons(vol);
|
|
||||||
|
|
||||||
}).on("play.once", function () {
|
|
||||||
|
|
||||||
video.off("play.once");
|
|
||||||
|
|
||||||
}).on("playing.once", function () {
|
}).on("playing.once", function () {
|
||||||
|
|
||||||
self.updateCanClientSeek(this);
|
|
||||||
|
|
||||||
video.off("playing.once");
|
video.off("playing.once");
|
||||||
|
|
||||||
ApiClient.reportPlaybackStart(Dashboard.getCurrentUserId(), item.Id, mediaSource.Id, true, item.MediaType);
|
self.onPlaybackStart(this, item, mediaSource);
|
||||||
|
|
||||||
self.startProgressInterval(item.Id, mediaSource.Id);
|
|
||||||
|
|
||||||
}).on("pause", function (e) {
|
}).on("pause", function (e) {
|
||||||
|
|
||||||
|
@ -939,9 +976,9 @@
|
||||||
|
|
||||||
}).on("timeupdate", function () {
|
}).on("timeupdate", function () {
|
||||||
|
|
||||||
if (!self.isPositionSliderActive) {
|
if (!isPositionSliderActive) {
|
||||||
|
|
||||||
self.setCurrentTime(self.getCurrentTicks(this), item, true);
|
self.setCurrentTime(self.getCurrentTicks(this), positionSlider, currentTimeElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
}).on("error", function () {
|
}).on("error", function () {
|
||||||
|
@ -995,8 +1032,13 @@
|
||||||
$(".ui-loader").hide();
|
$(".ui-loader").hide();
|
||||||
$("html").css("cursor", "default");
|
$("html").css("cursor", "default");
|
||||||
|
|
||||||
}).on("ended.playbackstopped", self.onPlaybackStopped)
|
}).on("ended.playbackstopped", function () {
|
||||||
.on('ended.playnext', self.playNextAfterEnded);
|
|
||||||
|
currentTimeElement.empty();
|
||||||
|
|
||||||
|
self.onPlaybackStopped.call(this);
|
||||||
|
|
||||||
|
}).on('ended.playnext', self.playNextAfterEnded);
|
||||||
|
|
||||||
// Stop playback on browser back button nav
|
// Stop playback on browser back button nav
|
||||||
$(window).on("popstate", function () {
|
$(window).on("popstate", function () {
|
||||||
|
|
|
@ -13,12 +13,6 @@
|
||||||
var currentPlaylistIndex = 0;
|
var currentPlaylistIndex = 0;
|
||||||
|
|
||||||
self.currentDurationTicks = null;
|
self.currentDurationTicks = null;
|
||||||
self.currentTimeElement = null;
|
|
||||||
self.unmuteButton = null;
|
|
||||||
self.muteButton = null;
|
|
||||||
self.positionSlider = null;
|
|
||||||
self.isPositionSliderActive = null;
|
|
||||||
self.volumeSlider = null;
|
|
||||||
self.startTimeTicksOffset = null;
|
self.startTimeTicksOffset = null;
|
||||||
|
|
||||||
self.playlist = [];
|
self.playlist = [];
|
||||||
|
@ -45,22 +39,11 @@
|
||||||
canClientSeek = duration && !isNaN(duration) && duration != Number.POSITIVE_INFINITY && duration != Number.NEGATIVE_INFINITY;
|
canClientSeek = duration && !isNaN(duration) && duration != Number.POSITIVE_INFINITY && duration != Number.NEGATIVE_INFINITY;
|
||||||
};
|
};
|
||||||
|
|
||||||
self.updateVolumeButtons = function (vol) {
|
|
||||||
|
|
||||||
if (vol) {
|
|
||||||
self.muteButton.show().prop("disabled", false);
|
|
||||||
self.unmuteButton.hide().prop("disabled", true);
|
|
||||||
} else {
|
|
||||||
self.muteButton.hide().prop("disabled", true);
|
|
||||||
self.unmuteButton.show().prop("disabled", false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.getCurrentTicks = function (mediaElement) {
|
self.getCurrentTicks = function (mediaElement) {
|
||||||
return Math.floor(10000000 * (mediaElement || currentMediaElement).currentTime) + self.startTimeTicksOffset;
|
return Math.floor(10000000 * (mediaElement || currentMediaElement).currentTime) + self.startTimeTicksOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
self.clearPauseStop = function() {
|
self.clearPauseStop = function () {
|
||||||
|
|
||||||
if (self.pauseStop) {
|
if (self.pauseStop) {
|
||||||
console.log('clearing pause stop timer');
|
console.log('clearing pause stop timer');
|
||||||
|
@ -69,31 +52,6 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.onPlaybackStopped = function () {
|
|
||||||
|
|
||||||
self.clearPauseStop();
|
|
||||||
|
|
||||||
$(this).off('ended.playbackstopped');
|
|
||||||
|
|
||||||
self.currentTimeElement.empty();
|
|
||||||
|
|
||||||
var endTime = this.currentTime;
|
|
||||||
|
|
||||||
clearProgressInterval();
|
|
||||||
|
|
||||||
var position = Math.floor(10000000 * endTime) + self.startTimeTicksOffset;
|
|
||||||
|
|
||||||
ApiClient.reportPlaybackStopped(Dashboard.getCurrentUserId(), currentItem.Id, currentMediaSource.Id, position);
|
|
||||||
|
|
||||||
if (currentItem.MediaType == "Video") {
|
|
||||||
ApiClient.stopActiveEncodings();
|
|
||||||
if (self.isFullScreen()) {
|
|
||||||
self.exitFullScreen();
|
|
||||||
}
|
|
||||||
self.resetEnhancements();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.playNextAfterEnded = function () {
|
self.playNextAfterEnded = function () {
|
||||||
|
|
||||||
$(this).off('ended.playnext');
|
$(this).off('ended.playnext');
|
||||||
|
@ -210,7 +168,7 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.setCurrentTime = function (ticks, item, updateSlider) {
|
self.setCurrentTime = function (ticks, positionSlider, currentTimeElement) {
|
||||||
|
|
||||||
// Convert to ticks
|
// Convert to ticks
|
||||||
ticks = Math.floor(ticks);
|
ticks = Math.floor(ticks);
|
||||||
|
@ -221,17 +179,28 @@
|
||||||
|
|
||||||
timeText += " / " + Dashboard.getDisplayTime(self.currentDurationTicks);
|
timeText += " / " + Dashboard.getDisplayTime(self.currentDurationTicks);
|
||||||
|
|
||||||
if (updateSlider) {
|
if (positionSlider) {
|
||||||
|
|
||||||
var percent = ticks / self.currentDurationTicks;
|
var percent = ticks / self.currentDurationTicks;
|
||||||
percent *= 100;
|
percent *= 100;
|
||||||
|
|
||||||
self.positionSlider.val(percent).slider('enable').slider('refresh');
|
positionSlider.val(percent).slider('enable').slider('refresh');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.positionSlider.slider('disable').slider('refresh');
|
|
||||||
|
if (positionSlider) {
|
||||||
|
|
||||||
|
positionSlider.slider('disable').slider('refresh');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.currentTimeElement.html(timeText);
|
if (currentTimeElement) {
|
||||||
|
currentTimeElement.html(timeText);
|
||||||
|
}
|
||||||
|
|
||||||
|
var state = self.getPlayerState(currentMediaElement, currentItem, currentMediaSource);
|
||||||
|
|
||||||
|
$(self).trigger('positionchange', [state]);
|
||||||
};
|
};
|
||||||
|
|
||||||
self.canPlayVideoDirect = function (mediaSource, videoStream, audioStream, subtitleStream, maxWidth, bitrate) {
|
self.canPlayVideoDirect = function (mediaSource, videoStream, audioStream, subtitleStream, maxWidth, bitrate) {
|
||||||
|
@ -459,8 +428,6 @@
|
||||||
|
|
||||||
var mediaElement;
|
var mediaElement;
|
||||||
|
|
||||||
var mediaControls = $('#nowPlayingBar');
|
|
||||||
|
|
||||||
if (item.MediaType === "Video") {
|
if (item.MediaType === "Video") {
|
||||||
|
|
||||||
currentItem = item;
|
currentItem = item;
|
||||||
|
@ -470,15 +437,12 @@
|
||||||
mediaElement = self.initVideoPlayer();
|
mediaElement = self.initVideoPlayer();
|
||||||
self.currentDurationTicks = currentMediaSource.RunTimeTicks;
|
self.currentDurationTicks = currentMediaSource.RunTimeTicks;
|
||||||
|
|
||||||
mediaControls = $("#videoControls");
|
|
||||||
|
|
||||||
} else if (item.MediaType === "Audio") {
|
} else if (item.MediaType === "Audio") {
|
||||||
|
|
||||||
currentItem = item;
|
currentItem = item;
|
||||||
currentMediaSource = getOptimalMediaSource(item.MediaType, item.MediaSources);
|
currentMediaSource = getOptimalMediaSource(item.MediaType, item.MediaSources);
|
||||||
|
|
||||||
mediaElement = playAudio(item, currentMediaSource, startPosition);
|
mediaElement = playAudio(item, currentMediaSource, startPosition);
|
||||||
mediaControls.show();
|
|
||||||
|
|
||||||
self.currentDurationTicks = currentMediaSource.RunTimeTicks;
|
self.currentDurationTicks = currentMediaSource.RunTimeTicks;
|
||||||
|
|
||||||
|
@ -488,36 +452,50 @@
|
||||||
|
|
||||||
currentMediaElement = mediaElement;
|
currentMediaElement = mediaElement;
|
||||||
|
|
||||||
//display image and title
|
if (item.MediaType === "Video") {
|
||||||
var imageTags = item.ImageTags || {};
|
|
||||||
var html = '';
|
self.updateNowPlayingInfo(item);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.updateNowPlayingInfo = function (item) {
|
||||||
|
|
||||||
|
if (!item) {
|
||||||
|
throw new Error('item cannot be null');
|
||||||
|
}
|
||||||
|
|
||||||
|
var mediaControls = $("#videoControls");
|
||||||
|
|
||||||
|
var state = self.getPlayerState(currentMediaElement, item, currentMediaSource);
|
||||||
|
|
||||||
var url = "";
|
var url = "";
|
||||||
|
|
||||||
if (imageTags.Primary) {
|
if (state.primaryImageTag) {
|
||||||
|
|
||||||
url = ApiClient.getImageUrl(item.Id, {
|
url = ApiClient.getImageUrl(state.primaryImageItemId, {
|
||||||
type: "Primary",
|
type: "Primary",
|
||||||
height: 80,
|
height: 80,
|
||||||
tag: item.ImageTags.Primary
|
tag: state.primaryImageTag
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (item.BackdropImageTags && item.BackdropImageTags.length) {
|
else if (state.backdropImageTag) {
|
||||||
|
|
||||||
url = ApiClient.getImageUrl(item.Id, {
|
url = ApiClient.getImageUrl(state.backdropItemId, {
|
||||||
type: "Backdrop",
|
type: "Backdrop",
|
||||||
height: 80,
|
height: 80,
|
||||||
tag: item.BackdropImageTags[0]
|
tag: state.backdropImageTag,
|
||||||
|
index: 0
|
||||||
});
|
});
|
||||||
} else if (imageTags.Thumb) {
|
|
||||||
|
|
||||||
url = ApiClient.getImageUrl(item.Id, {
|
} else if (state.thumbImageTag) {
|
||||||
|
|
||||||
|
url = ApiClient.getImageUrl(state.thumbImageItemId, {
|
||||||
type: "Thumb",
|
type: "Thumb",
|
||||||
height: 80,
|
height: 80,
|
||||||
tag: item.ImageTags.Thumb
|
tag: state.thumbImageTag
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (item.Type == "TvChannel" || item.Type == "Recording") {
|
else if (item.Type == "TvChannel" || item.Type == "Recording") {
|
||||||
url = "css/images/items/detail/tv.png";
|
url = "css/images/items/detail/tv.png";
|
||||||
}
|
}
|
||||||
|
@ -528,40 +506,19 @@
|
||||||
url = "css/images/items/detail/video.png";
|
url = "css/images/items/detail/video.png";
|
||||||
}
|
}
|
||||||
|
|
||||||
var name = item.Name;
|
var name = state.itemName;
|
||||||
var seriesName = '';
|
|
||||||
|
|
||||||
// Channel number
|
var nowPlayingTextElement = $('.nowPlayingText', mediaControls);
|
||||||
if (item.Number) {
|
|
||||||
name = item.Number + ' ' + name;
|
if (state.itemSubName) {
|
||||||
}
|
name += '<br/>' + state.itemSubName;
|
||||||
if (item.IndexNumber != null) {
|
nowPlayingTextElement.addClass('nowPlayingDoubleText');
|
||||||
name = item.IndexNumber + " - " + name;
|
} else {
|
||||||
}
|
nowPlayingTextElement.removeClass('nowPlayingDoubleText');
|
||||||
if (item.ParentIndexNumber != null) {
|
|
||||||
name = item.ParentIndexNumber + "." + name;
|
|
||||||
}
|
|
||||||
if (item.SeriesName || item.Album || item.ProductionYear) {
|
|
||||||
seriesName = item.SeriesName || item.Album || item.ProductionYear;
|
|
||||||
}
|
|
||||||
if (item.CurrentProgram) {
|
|
||||||
seriesName = item.CurrentProgram.Name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var href = LibraryBrowser.getHref(item.CurrentProgram || item);
|
$('.nowPlayingImage', mediaControls).html('<img src="' + url + '" />');
|
||||||
|
nowPlayingTextElement.html(name);
|
||||||
var nowPlayingText = (name ? name + "\n" : "") + (seriesName || "---");
|
|
||||||
if (item.SeriesName || item.Album || item.CurrentProgram) {
|
|
||||||
nowPlayingText = (seriesName ? seriesName : "") + "\n" + (name || "---");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix for apostrophes and quotes
|
|
||||||
var htmlTitle = trimTitle(nowPlayingText).replace(/'/g, ''').replace(/"/g, '"');
|
|
||||||
html += "<div><a href='" + href + "'><img class='nowPlayingBarImage' alt='" + htmlTitle +
|
|
||||||
"' title='" + htmlTitle + "' src='" + url + "' style='height:40px;display:inline-block;' /></a></div>";
|
|
||||||
html += "<div class='nowPlayingText' title='" + htmlTitle + "'>" + titleHtml(nowPlayingText) + "</div>";
|
|
||||||
|
|
||||||
$('.nowPlayingMediaInfo', mediaControls).html(html);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.getItemsForPlayback = function (query) {
|
self.getItemsForPlayback = function (query) {
|
||||||
|
@ -727,51 +684,65 @@
|
||||||
|
|
||||||
self.mute = function () {
|
self.mute = function () {
|
||||||
|
|
||||||
if (currentMediaElement) {
|
self.setVolume(0);
|
||||||
currentMediaElement.volume = 0;
|
|
||||||
currentMediaElement.muted = true;
|
|
||||||
self.volumeSlider.val(0).slider('refresh');
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.unmute = function () {
|
self.unMute = function () {
|
||||||
|
|
||||||
if (currentMediaElement) {
|
self.setVolume(self.getSavedVolume() * 100);
|
||||||
var volume = localStorage.getItem("volume") || self.volumeSlider.val();
|
|
||||||
currentMediaElement.volume = volume;
|
|
||||||
currentMediaElement.muted = false;
|
|
||||||
self.volumeSlider.val(volume).slider('refresh');
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.toggleMute = function () {
|
self.toggleMute = function () {
|
||||||
|
|
||||||
if (currentMediaElement) {
|
if (currentMediaElement) {
|
||||||
var volume = localStorage.getItem("volume") || self.volumeSlider.val();
|
|
||||||
currentMediaElement.volume = currentMediaElement.volume ? 0 : volume;
|
if (currentMediaElement.volume) {
|
||||||
currentMediaElement.muted = currentMediaElement.volume == 0;
|
self.mute();
|
||||||
self.volumeSlider.val(volume).slider('refresh');
|
} else {
|
||||||
|
self.unMute();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.volumeDown = function () {
|
self.volumeDown = function () {
|
||||||
|
|
||||||
if (currentMediaElement) {
|
if (currentMediaElement) {
|
||||||
currentMediaElement.volume = Math.max(currentMediaElement.volume - .02, 0);
|
self.setVolume(Math.max(currentMediaElement.volume - .02, 0) * 100);
|
||||||
localStorage.setItem("volume", currentMediaElement.volume);
|
|
||||||
self.volumeSlider.val(currentMediaElement.volume).slider('refresh');
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.volumeUp = function () {
|
self.volumeUp = function () {
|
||||||
|
|
||||||
if (currentMediaElement) {
|
if (currentMediaElement) {
|
||||||
currentMediaElement.volume = Math.min(currentMediaElement.volume + .02, 1);
|
self.setVolume(Math.min(currentMediaElement.volume + .02, 1) * 100);
|
||||||
localStorage.setItem("volume", currentMediaElement.volume);
|
|
||||||
self.volumeSlider.val(currentMediaElement.volume).slider('refresh');
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Sets volume using a 0-100 scale
|
||||||
|
self.setVolume = function (val) {
|
||||||
|
|
||||||
|
if (currentMediaElement) {
|
||||||
|
|
||||||
|
currentMediaElement.volume = val / 100;
|
||||||
|
|
||||||
|
self.onVolumeChanged(currentMediaElement);
|
||||||
|
|
||||||
|
self.saveVolume();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.saveVolume = function (val) {
|
||||||
|
|
||||||
|
if (val) {
|
||||||
|
localStorage.setItem("volume", val);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
self.getSavedVolume = function () {
|
||||||
|
return localStorage.getItem("volume") || 0.5;
|
||||||
|
};
|
||||||
|
|
||||||
self.shuffle = function (id) {
|
self.shuffle = function (id) {
|
||||||
|
|
||||||
var userId = Dashboard.getCurrentUserId();
|
var userId = Dashboard.getCurrentUserId();
|
||||||
|
@ -882,7 +853,12 @@
|
||||||
|
|
||||||
$(elem).off("ended.playnext").on("ended", function () {
|
$(elem).off("ended.playnext").on("ended", function () {
|
||||||
|
|
||||||
$(this).remove();
|
$(this).off();
|
||||||
|
|
||||||
|
if (this.tagName.toLowerCase() != 'audio') {
|
||||||
|
$(this).remove();
|
||||||
|
}
|
||||||
|
|
||||||
elem.src = "";
|
elem.src = "";
|
||||||
currentMediaElement = null;
|
currentMediaElement = null;
|
||||||
|
|
||||||
|
@ -893,8 +869,6 @@
|
||||||
self.exitFullScreen();
|
self.exitFullScreen();
|
||||||
}
|
}
|
||||||
self.resetEnhancements();
|
self.resetEnhancements();
|
||||||
} else {
|
|
||||||
$('#nowPlayingBar').hide();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -902,55 +876,150 @@
|
||||||
return currentMediaElement;
|
return currentMediaElement;
|
||||||
};
|
};
|
||||||
|
|
||||||
self.bindPositionSlider = function () {
|
self.getPlayerState = function (playerElement, item, mediaSource) {
|
||||||
self.positionSlider.on('slidestart', function (e) {
|
|
||||||
|
|
||||||
self.isPositionSliderActive = true;
|
var itemName = '';
|
||||||
|
var itemSubName = '';
|
||||||
|
|
||||||
}).on('slidestop', onPositionSliderChange);
|
if (item) {
|
||||||
|
|
||||||
|
var name = item.Name;
|
||||||
|
var seriesName = '';
|
||||||
|
|
||||||
|
// Channel number
|
||||||
|
if (item.Number) {
|
||||||
|
name = item.Number + ' ' + name;
|
||||||
|
}
|
||||||
|
if (item.IndexNumber != null) {
|
||||||
|
name = item.IndexNumber + " - " + name;
|
||||||
|
}
|
||||||
|
if (item.ParentIndexNumber != null) {
|
||||||
|
name = item.ParentIndexNumber + "." + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.CurrentProgram) {
|
||||||
|
seriesName = item.CurrentProgram.Name;
|
||||||
|
}
|
||||||
|
else if (item.SeriesName || item.Album || item.ProductionYear) {
|
||||||
|
seriesName = item.SeriesName || item.Album || item.ProductionYear;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seriesName) {
|
||||||
|
itemName = item.SeriesName || item.Album || item.CurrentProgram;
|
||||||
|
itemSubName = name;
|
||||||
|
} else {
|
||||||
|
itemName = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var state = {
|
||||||
|
itemId: item.Id,
|
||||||
|
mediaSourceId: mediaSource.Id,
|
||||||
|
volumeLevel: playerElement.volume * 100,
|
||||||
|
isMuted: playerElement.volume == 0,
|
||||||
|
isPaused: playerElement.paused,
|
||||||
|
runtimeTicks: mediaSource.RunTimeTicks,
|
||||||
|
positionTicks: self.getCurrentTicks(playerElement),
|
||||||
|
canSeek: mediaSource.RunTimeTicks && mediaSource.RunTimeTicks > 0,
|
||||||
|
mediaType: item.MediaType,
|
||||||
|
itemName: itemName,
|
||||||
|
itemSubName: itemSubName,
|
||||||
|
itemType: item.Type
|
||||||
|
};
|
||||||
|
|
||||||
|
var imageTags = item.ImageTags || {};
|
||||||
|
|
||||||
|
if (imageTags.Primary) {
|
||||||
|
|
||||||
|
state.primaryImageItemId = item.Id;
|
||||||
|
state.primaryImageTag = imageTags.Primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.BackdropImageTags && item.BackdropImageTags.length) {
|
||||||
|
|
||||||
|
state.backdropItemId = item.Id;
|
||||||
|
state.backdropImageTag = item.BackdropImageTags[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imageTags.Thumb) {
|
||||||
|
|
||||||
|
state.thumbItemId = item.Id;
|
||||||
|
state.thumbImageTag = imageTags.Thumb;
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
};
|
};
|
||||||
|
|
||||||
self.bindVolumeSlider = function () {
|
self.onPlaybackStart = function (playerElement, item, mediaSource) {
|
||||||
self.volumeSlider.on('slidestop', function () {
|
|
||||||
|
|
||||||
var vol = this.value;
|
self.updateCanClientSeek(playerElement);
|
||||||
|
|
||||||
self.updateVolumeButtons(vol);
|
ApiClient.reportPlaybackStart(Dashboard.getCurrentUserId(), item.Id, mediaSource.Id, true, item.MediaType);
|
||||||
currentMediaElement.volume = vol;
|
|
||||||
});
|
self.startProgressInterval(item.Id, mediaSource.Id);
|
||||||
|
|
||||||
|
var state = self.getPlayerState(playerElement, item, mediaSource);
|
||||||
|
|
||||||
|
$(self).trigger('playbackstart', [state]);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.onVolumeChanged = function (playerElement) {
|
||||||
|
|
||||||
|
self.saveVolume(playerElement.volume);
|
||||||
|
|
||||||
|
var state = self.getPlayerState(playerElement, currentItem, currentMediaSource);
|
||||||
|
|
||||||
|
$(self).trigger('volumechange', [state]);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.onPlaybackStopped = function () {
|
||||||
|
|
||||||
|
self.clearPauseStop();
|
||||||
|
|
||||||
|
var playerElement = this;
|
||||||
|
|
||||||
|
$(playerElement).off('ended.playbackstopped');
|
||||||
|
|
||||||
|
var endTime = playerElement.currentTime;
|
||||||
|
|
||||||
|
clearProgressInterval();
|
||||||
|
|
||||||
|
var position = Math.floor(10000000 * endTime) + self.startTimeTicksOffset;
|
||||||
|
|
||||||
|
var item = currentItem;
|
||||||
|
var mediaSource = currentMediaSource;
|
||||||
|
|
||||||
|
ApiClient.reportPlaybackStopped(Dashboard.getCurrentUserId(), item.Id, mediaSource.Id, position);
|
||||||
|
|
||||||
|
if (item.MediaType == "Video") {
|
||||||
|
ApiClient.stopActiveEncodings();
|
||||||
|
if (self.isFullScreen()) {
|
||||||
|
self.exitFullScreen();
|
||||||
|
}
|
||||||
|
self.resetEnhancements();
|
||||||
|
}
|
||||||
|
|
||||||
|
var state = self.getPlayerState(playerElement, item, mediaSource);
|
||||||
|
|
||||||
|
$(self).trigger('playbackstop', [state]);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.onPlaystateChange = function (playerElement) {
|
||||||
|
|
||||||
|
var state = self.getPlayerState(playerElement, currentItem, currentMediaSource);
|
||||||
|
|
||||||
|
$(self).trigger('playstatechange', [state]);
|
||||||
};
|
};
|
||||||
|
|
||||||
$(window).on("beforeunload popstate", function () {
|
$(window).on("beforeunload popstate", function () {
|
||||||
|
|
||||||
var item = currentItem;
|
|
||||||
var media = currentMediaElement;
|
|
||||||
|
|
||||||
// Try to report playback stopped before the browser closes
|
// Try to report playback stopped before the browser closes
|
||||||
if (item && media && currentProgressInterval) {
|
if (currentItem && currentMediaElement && currentProgressInterval) {
|
||||||
|
|
||||||
var endTime = currentMediaElement.currentTime;
|
self.onPlaybackStopped.call(currentMediaElement);
|
||||||
|
|
||||||
var position = Math.floor(10000000 * endTime) + self.startTimeTicksOffset;
|
|
||||||
|
|
||||||
ApiClient.reportPlaybackStopped(Dashboard.getCurrentUserId(), currentItem.Id, currentMediaSource.Id, position);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$(function () {
|
|
||||||
initPlayer();
|
|
||||||
});
|
|
||||||
|
|
||||||
function initPlayer() {
|
|
||||||
self.muteButton = $('.muteButton');
|
|
||||||
self.unmuteButton = $('.unmuteButton');
|
|
||||||
self.currentTimeElement = $('.currentTime');
|
|
||||||
self.volumeSlider = $('.volumeSlider');
|
|
||||||
self.positionSlider = $(".positionSlider");
|
|
||||||
|
|
||||||
self.bindVolumeSlider();
|
|
||||||
self.bindPositionSlider();
|
|
||||||
}
|
|
||||||
|
|
||||||
function replaceQueryString(url, param, value) {
|
function replaceQueryString(url, param, value) {
|
||||||
var re = new RegExp("([?|&])" + param + "=.*?(&|$)", "i");
|
var re = new RegExp("([?|&])" + param + "=.*?(&|$)", "i");
|
||||||
if (url.match(re))
|
if (url.match(re))
|
||||||
|
@ -977,15 +1046,30 @@
|
||||||
return testableVideoElement.canPlayType('video/webm').replace(/no/, '');
|
return testableVideoElement.canPlayType('video/webm').replace(/no/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
function onPositionSliderChange() {
|
function getAudioElement() {
|
||||||
|
|
||||||
self.isPositionSliderActive = false;
|
var elem = $('.mediaPlayerAudio');
|
||||||
|
|
||||||
var newPercent = parseInt(this.value);
|
if (elem.length) {
|
||||||
|
return elem;
|
||||||
|
}
|
||||||
|
|
||||||
var newPositionTicks = (newPercent / 100) * currentMediaSource.RunTimeTicks;
|
var html = '';
|
||||||
|
|
||||||
self.changeStream(Math.floor(newPositionTicks));
|
var requiresControls = $.browser.android || ($.browser.webkit && !$.browser.chrome);
|
||||||
|
|
||||||
|
if (requiresControls) {
|
||||||
|
html += '<div class="mediaPlayerAudioContainer"><div class="mediaPlayerAudioContainerInner">';;
|
||||||
|
} else {
|
||||||
|
html += '<div class="mediaPlayerAudioContainer" style="display:none;"><div class="mediaPlayerAudioContainerInner">';;
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '<audio class="mediaPlayerAudio" preload="auto" controls>';
|
||||||
|
html += '</audio></div></div>';
|
||||||
|
|
||||||
|
$(document.body).append(html);
|
||||||
|
|
||||||
|
return $('.mediaPlayerAudio');
|
||||||
}
|
}
|
||||||
|
|
||||||
function playAudio(item, mediaSource, startPositionTicks) {
|
function playAudio(item, mediaSource, startPositionTicks) {
|
||||||
|
@ -1003,18 +1087,10 @@
|
||||||
audioCodec: 'mp3'
|
audioCodec: 'mp3'
|
||||||
}));
|
}));
|
||||||
|
|
||||||
var aacUrl = ApiClient.getUrl('Audio/' + item.Id + '/stream.aac', $.extend({}, baseParams, {
|
|
||||||
audioCodec: 'aac'
|
|
||||||
}));
|
|
||||||
|
|
||||||
var webmUrl = ApiClient.getUrl('Audio/' + item.Id + '/stream.webm', $.extend({}, baseParams, {
|
|
||||||
audioCodec: 'Vorbis'
|
|
||||||
}));
|
|
||||||
|
|
||||||
var mediaStreams = mediaSource.MediaStreams;
|
var mediaStreams = mediaSource.MediaStreams;
|
||||||
|
|
||||||
var isStatic = false;
|
var isStatic = false;
|
||||||
var seekParam = isStatic && startPositionTicks ? '#t=' + (startPositionTicks / 10000000) : '';
|
var seekParam = startPositionTicks ? '#t=' + (startPositionTicks / 10000000) : '';
|
||||||
|
|
||||||
for (var i = 0, length = mediaStreams.length; i < length; i++) {
|
for (var i = 0, length = mediaStreams.length; i < length; i++) {
|
||||||
|
|
||||||
|
@ -1024,11 +1100,7 @@
|
||||||
|
|
||||||
var container = (mediaSource.Container || '').toLowerCase();
|
var container = (mediaSource.Container || '').toLowerCase();
|
||||||
// Stream statically when possible
|
// Stream statically when possible
|
||||||
if (container == 'aac' && stream.BitRate <= 256000) {
|
if (container == 'mp3' && stream.BitRate <= 256000) {
|
||||||
aacUrl += "&static=true" + seekParam;
|
|
||||||
isStatic = true;
|
|
||||||
}
|
|
||||||
else if (container == 'mp3' && stream.BitRate <= 256000) {
|
|
||||||
mp3Url += "&static=true" + seekParam;
|
mp3Url += "&static=true" + seekParam;
|
||||||
isStatic = true;
|
isStatic = true;
|
||||||
}
|
}
|
||||||
|
@ -1038,91 +1110,39 @@
|
||||||
|
|
||||||
self.startTimeTicksOffset = isStatic ? 0 : startPositionTicks;
|
self.startTimeTicksOffset = isStatic ? 0 : startPositionTicks;
|
||||||
|
|
||||||
var html = '';
|
var initialVolume = self.getSavedVolume();
|
||||||
|
|
||||||
var requiresControls = $.browser.android || ($.browser.webkit && !$.browser.chrome);
|
return getAudioElement().each(function () {
|
||||||
|
|
||||||
// Can't autoplay in these browsers so we need to use the full controls
|
this.src = mp3Url;
|
||||||
if (requiresControls) {
|
|
||||||
html += '<audio preload="auto" autoplay controls>';
|
|
||||||
} else {
|
|
||||||
html += '<audio preload="auto" style="display:none;" autoplay>';
|
|
||||||
}
|
|
||||||
html += '<source type="audio/mpeg" src="' + mp3Url + '" />';
|
|
||||||
html += '<source type="audio/aac" src="' + aacUrl + '" />';
|
|
||||||
html += '<source type="audio/webm" src="' + webmUrl + '" />';
|
|
||||||
html += '</audio>';
|
|
||||||
|
|
||||||
var nowPlayingBar = $('#nowPlayingBar').show();
|
|
||||||
//show stop button
|
|
||||||
$('#stopButton', nowPlayingBar).show();
|
|
||||||
$('#playButton', nowPlayingBar).hide();
|
|
||||||
$('#pauseButton', nowPlayingBar).show();
|
|
||||||
$('#fullscreenButton', nowPlayingBar).hide();
|
|
||||||
|
|
||||||
$('#previousTrackButton', nowPlayingBar).show();
|
|
||||||
$('#nextTrackButton', nowPlayingBar).show();
|
|
||||||
$('#playlistButton', nowPlayingBar).show();
|
|
||||||
|
|
||||||
$('#qualityButton', nowPlayingBar).hide();
|
|
||||||
$('#audioTracksButton', nowPlayingBar).hide();
|
|
||||||
$('#subtitleButton', nowPlayingBar).hide();
|
|
||||||
$('#chaptersButton', nowPlayingBar).hide();
|
|
||||||
|
|
||||||
var mediaElement = $('#mediaElement', nowPlayingBar).html(html);
|
|
||||||
var audioElement = $("audio", mediaElement);
|
|
||||||
|
|
||||||
var initialVolume = localStorage.getItem("volume") || 0.5;
|
|
||||||
|
|
||||||
audioElement.each(function () {
|
|
||||||
this.volume = initialVolume;
|
this.volume = initialVolume;
|
||||||
});
|
this.play();
|
||||||
|
|
||||||
self.volumeSlider.val(initialVolume).slider('refresh');
|
}).on("volumechange", function () {
|
||||||
self.updateVolumeButtons(initialVolume);
|
|
||||||
|
|
||||||
audioElement.on("volumechange", function () {
|
self.onVolumeChanged(this);
|
||||||
|
|
||||||
var vol = this.volume;
|
}).on("playing.once", function () {
|
||||||
|
|
||||||
localStorage.setItem("volume", vol);
|
$('.mediaPlayerAudioContainer').hide();
|
||||||
|
|
||||||
self.updateVolumeButtons(vol);
|
$(this).off("playing.once");
|
||||||
|
|
||||||
}).on("play.once", function () {
|
self.onPlaybackStart(this, item, mediaSource);
|
||||||
|
|
||||||
if (!requiresControls) {
|
|
||||||
audioElement.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
self.updateCanClientSeek(this);
|
|
||||||
|
|
||||||
audioElement.off("play.once");
|
|
||||||
|
|
||||||
ApiClient.reportPlaybackStart(Dashboard.getCurrentUserId(), item.Id, mediaSource.Id, true, item.MediaType);
|
|
||||||
|
|
||||||
self.startProgressInterval(item.Id, mediaSource.Id);
|
|
||||||
|
|
||||||
}).on("pause", function () {
|
}).on("pause", function () {
|
||||||
|
|
||||||
$('#playButton', nowPlayingBar).show();
|
self.onPlaystateChange(this);
|
||||||
$('#pauseButton', nowPlayingBar).hide();
|
|
||||||
|
|
||||||
}).on("playing", function () {
|
}).on("playing", function () {
|
||||||
|
|
||||||
$('#playButton', nowPlayingBar).hide();
|
self.onPlaystateChange(this);
|
||||||
$('#pauseButton', nowPlayingBar).show();
|
|
||||||
|
|
||||||
}).on("timeupdate", function () {
|
}).on("timeupdate", function () {
|
||||||
|
|
||||||
if (!self.isPositionSliderActive) {
|
self.setCurrentTime(self.getCurrentTicks(this));
|
||||||
|
|
||||||
self.setCurrentTime(self.getCurrentTicks(this), item, true);
|
}).on("ended.playbackstopped", self.onPlaybackStopped).on('ended.playnext', self.playNextAfterEnded)[0];
|
||||||
}
|
|
||||||
|
|
||||||
}).on("ended.playbackstopped", self.onPlaybackStopped).on('ended.playnext', self.playNextAfterEnded);
|
|
||||||
|
|
||||||
return audioElement[0];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function canPlayAudioStreamDirect(audioStream) {
|
function canPlayAudioStreamDirect(audioStream) {
|
||||||
|
@ -1146,27 +1166,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
function trunc(string, len) {
|
|
||||||
if (string.length > 0 && string.length < len) return string;
|
|
||||||
var trimmed = $.trim(string).substring(0, len).split(" ").slice(0, -1).join(" ");
|
|
||||||
if (trimmed) {
|
|
||||||
trimmed += "...";
|
|
||||||
} else {
|
|
||||||
trimmed = "---"
|
|
||||||
}
|
|
||||||
return trimmed;
|
|
||||||
};
|
|
||||||
|
|
||||||
function trimTitle(title) {
|
|
||||||
return title.replace("\n---", "");
|
|
||||||
};
|
|
||||||
|
|
||||||
function titleHtml(title) {
|
|
||||||
var titles = title.split("\n");
|
|
||||||
return (trunc(titles[0], 30) + "<br />" + trunc(titles[1], 30)).replace("---", " ");
|
|
||||||
};
|
|
||||||
|
|
||||||
var getItemFields = "MediaSources,Chapters";
|
var getItemFields = "MediaSources,Chapters";
|
||||||
|
|
||||||
|
|
359
dashboard-ui/scripts/nowplayingbar.js
Normal file
359
dashboard-ui/scripts/nowplayingbar.js
Normal file
|
@ -0,0 +1,359 @@
|
||||||
|
(function (window, document, $, setTimeout, clearTimeout) {
|
||||||
|
|
||||||
|
var currentPlayer;
|
||||||
|
|
||||||
|
var currentTimeElement;
|
||||||
|
var nowPlayingImageElement;
|
||||||
|
var nowPlayingTextElement;
|
||||||
|
var unmuteButton;
|
||||||
|
var muteButton;
|
||||||
|
var volumeSlider;
|
||||||
|
var isVolumeSliderActive;
|
||||||
|
var unpauseButton;
|
||||||
|
var pauseButton;
|
||||||
|
var positionSlider;
|
||||||
|
var isPositionSliderActive;
|
||||||
|
|
||||||
|
var lastPlayerState;
|
||||||
|
|
||||||
|
function getNowPlayingBarHtml() {
|
||||||
|
|
||||||
|
var html = '';
|
||||||
|
|
||||||
|
html += '<div id="nowPlayingBar" class="nowPlayingBar" style="display:none;">';
|
||||||
|
html += '<div style="display:inline-block;width:12px;"></div>';
|
||||||
|
html += '<a id="playlistButton" class="mediaButton playlistButton" href="playlist.html" data-role="button" data-icon="bullets" data-iconpos="notext" data-inline="true" title="Playlist">Playlist</a>';
|
||||||
|
html += '<button id="previousTrackButton" class="mediaButton previousTrackButton" title="Previous Track" type="button" data-icon="previous-track" data-iconpos="notext" data-inline="true">Previous Track</button>';
|
||||||
|
html += '<button id="playButton" class="mediaButton unpauseButton" title="Play" type="button" data-icon="play" data-iconpos="notext" data-inline="true">Play</button>';
|
||||||
|
html += '<button id="pauseButton" class="mediaButton pauseButton" title="Pause" type="button" data-icon="pause" data-iconpos="notext" data-inline="true">Pause</button>';
|
||||||
|
|
||||||
|
html += '<button id="stopButton" class="mediaButton stopButton" title="Stop" type="button" data-icon="stop" data-iconpos="notext" data-inline="true">Stop</button>';
|
||||||
|
html += '<button id="nextTrackButton" class="mediaButton nextTrackButton" title="Next Track" type="button" data-icon="next-track" data-iconpos="notext" data-inline="true">Next Track</button>';
|
||||||
|
|
||||||
|
html += '<div id="mediaElement"></div>';
|
||||||
|
|
||||||
|
html += '<div class="positionSliderContainer sliderContainer">';
|
||||||
|
html += '<input type="range" class="mediaSlider positionSlider slider" step=".001" min="0" max="100" value="0" style="display:none;" data-mini="true" data-theme="a" data-highlight="true" />';
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
html += '<div class="currentTime"></div>';
|
||||||
|
html += '<div class="nowPlayingImage"></div>';
|
||||||
|
html += '<div class="nowPlayingText"></div>';
|
||||||
|
|
||||||
|
html += '<button id="muteButton" class="mediaButton muteButton" title="Mute" type="button" data-icon="audio" data-iconpos="notext" data-inline="true">Mute</button>';
|
||||||
|
html += '<button id="unmuteButton" class="mediaButton unmuteButton" title="Unmute" type="button" data-icon="volume-off" data-iconpos="notext" data-inline="true">Unmute</button>';
|
||||||
|
|
||||||
|
html += '<div class="volumeSliderContainer sliderContainer">';
|
||||||
|
html += '<input type="range" class="mediaSlider volumeSlider slider" step=".05" min="0" max="100" value="0" style="display:none;" data-mini="true" data-theme="a" data-highlight="true" />';
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
function bindEvents(elem) {
|
||||||
|
|
||||||
|
currentTimeElement = $('.currentTime', elem);
|
||||||
|
nowPlayingImageElement = $('.nowPlayingImage', elem);
|
||||||
|
nowPlayingTextElement = $('.nowPlayingText', elem);
|
||||||
|
|
||||||
|
unmuteButton = $('.unmuteButton', elem).on('click', function () {
|
||||||
|
|
||||||
|
if (currentPlayer) {
|
||||||
|
currentPlayer.unMute();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
muteButton = $('.muteButton', elem).on('click', function () {
|
||||||
|
|
||||||
|
if (currentPlayer) {
|
||||||
|
currentPlayer.mute();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.stopButton', elem).on('click', function () {
|
||||||
|
|
||||||
|
if (currentPlayer) {
|
||||||
|
currentPlayer.stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
pauseButton = $('.pauseButton', elem).on('click', function () {
|
||||||
|
|
||||||
|
if (currentPlayer) {
|
||||||
|
currentPlayer.pause();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
unpauseButton = $('.unpauseButton', elem).on('click', function () {
|
||||||
|
|
||||||
|
if (currentPlayer) {
|
||||||
|
currentPlayer.unpause();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.nextTrackButton', elem).on('click', function () {
|
||||||
|
|
||||||
|
if (currentPlayer) {
|
||||||
|
currentPlayer.nextTrack();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.previousTrackButton', elem).on('click', function () {
|
||||||
|
|
||||||
|
if (currentPlayer) {
|
||||||
|
currentPlayer.previousTrack();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
volumeSlider = $('.volumeSlider', elem).on('slidestart', function () {
|
||||||
|
|
||||||
|
isVolumeSliderActive = true;
|
||||||
|
|
||||||
|
}).on('slidestop', function () {
|
||||||
|
|
||||||
|
isVolumeSliderActive = false;
|
||||||
|
|
||||||
|
if (currentPlayer) {
|
||||||
|
currentPlayer.setVolume(this.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
positionSlider = $('.positionSlider', elem).on('slidestart', function () {
|
||||||
|
|
||||||
|
isPositionSliderActive = true;
|
||||||
|
|
||||||
|
}).on('slidestop', function () {
|
||||||
|
|
||||||
|
isPositionSliderActive = false;
|
||||||
|
|
||||||
|
if (currentPlayer && lastPlayerState) {
|
||||||
|
|
||||||
|
var ticks = lastPlayerState.runtimeTicks * this.value / 100;
|
||||||
|
|
||||||
|
currentPlayer.seek(ticks);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNowPlayingBar() {
|
||||||
|
|
||||||
|
var elem = $('.nowPlayingBar');
|
||||||
|
|
||||||
|
if (elem.length) {
|
||||||
|
return elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
elem = $(getNowPlayingBarHtml()).insertBefore('#footerNotifications').trigger('create');
|
||||||
|
|
||||||
|
bindEvents(elem);
|
||||||
|
|
||||||
|
return elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updatePlayerState(state) {
|
||||||
|
|
||||||
|
lastPlayerState = state;
|
||||||
|
|
||||||
|
if (!muteButton) {
|
||||||
|
getNowPlayingBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.isMuted) {
|
||||||
|
|
||||||
|
muteButton.hide();
|
||||||
|
unmuteButton.show();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
muteButton.show();
|
||||||
|
unmuteButton.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.isPaused) {
|
||||||
|
|
||||||
|
pauseButton.hide();
|
||||||
|
unpauseButton.show();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
pauseButton.show();
|
||||||
|
unpauseButton.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isVolumeSliderActive) {
|
||||||
|
volumeSlider.val(state.volumeLevel || 0).slider('refresh');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isPositionSliderActive) {
|
||||||
|
if (state.canSeek) {
|
||||||
|
|
||||||
|
var pct = state.positionTicks / state.runtimeTicks;
|
||||||
|
pct *= 100;
|
||||||
|
|
||||||
|
positionSlider.val(pct).prop('disabled', '');
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
positionSlider.val(0).prop('disabled', 'disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
positionSlider.slider('refresh');
|
||||||
|
}
|
||||||
|
|
||||||
|
var timeText = Dashboard.getDisplayTime(state.positionTicks);
|
||||||
|
|
||||||
|
if (state.runtimeTicks) {
|
||||||
|
|
||||||
|
timeText += " / " + Dashboard.getDisplayTime(state.runtimeTicks);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
currentTimeElement.html(timeText);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateNowPlayingInfo(state) {
|
||||||
|
|
||||||
|
var name = state.itemName;
|
||||||
|
|
||||||
|
if (state.itemSubName) {
|
||||||
|
name += '<br/>' + state.itemSubName;
|
||||||
|
nowPlayingTextElement.addClass('nowPlayingDoubleText');
|
||||||
|
} else {
|
||||||
|
nowPlayingTextElement.removeClass('nowPlayingDoubleText');
|
||||||
|
}
|
||||||
|
|
||||||
|
nowPlayingTextElement.html(name);
|
||||||
|
|
||||||
|
var url;
|
||||||
|
|
||||||
|
if (state.primaryImageTag) {
|
||||||
|
|
||||||
|
url = ApiClient.getImageUrl(state.primaryImageItemId, {
|
||||||
|
type: "Primary",
|
||||||
|
height: 80,
|
||||||
|
tag: state.primaryImageTag
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (state.backdropImageTag) {
|
||||||
|
|
||||||
|
url = ApiClient.getImageUrl(state.backdropItemId, {
|
||||||
|
type: "Backdrop",
|
||||||
|
height: 80,
|
||||||
|
tag: state.backdropImageTag,
|
||||||
|
index: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
} else if (state.thumbImageTag) {
|
||||||
|
|
||||||
|
url = ApiClient.getImageUrl(state.thumbImageItemId, {
|
||||||
|
type: "Thumb",
|
||||||
|
height: 80,
|
||||||
|
tag: state.thumbImageTag
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (item.Type == "TvChannel" || item.Type == "Recording") {
|
||||||
|
url = "css/images/items/detail/tv.png";
|
||||||
|
}
|
||||||
|
else if (item.MediaType == "Audio") {
|
||||||
|
url = "css/images/items/detail/audio.png";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
url = "css/images/items/detail/video.png";
|
||||||
|
}
|
||||||
|
|
||||||
|
nowPlayingImageElement.html('<img src="' + url + '" />');
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPlaybackStart(e, state) {
|
||||||
|
|
||||||
|
var player = this;
|
||||||
|
|
||||||
|
if (player.isDefaultPlayer && state.mediaType == 'Video') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
showNowPlayingBar();
|
||||||
|
|
||||||
|
updatePlayerState(state);
|
||||||
|
updateNowPlayingInfo(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
var nowPlayingBarTimeout;
|
||||||
|
function showNowPlayingBar() {
|
||||||
|
|
||||||
|
if (nowPlayingBarTimeout) {
|
||||||
|
clearTimeout(nowPlayingBarTimeout);
|
||||||
|
nowPlayingBarTimeout = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var nowPlayingBar = getNowPlayingBar();
|
||||||
|
|
||||||
|
nowPlayingBar.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideNowPlayingBar() {
|
||||||
|
|
||||||
|
if (nowPlayingBarTimeout) {
|
||||||
|
clearTimeout(nowPlayingBarTimeout);
|
||||||
|
nowPlayingBarTimeout = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use a timeout to prevent the bar from hiding and showing quickly
|
||||||
|
// in the event of a stop->play command
|
||||||
|
nowPlayingBarTimeout = setTimeout(function () {
|
||||||
|
getNowPlayingBar().hide();
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPlaybackStopped(e, state) {
|
||||||
|
|
||||||
|
hideNowPlayingBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onVolumeChanged(e, state) {
|
||||||
|
|
||||||
|
var player = this;
|
||||||
|
|
||||||
|
if (player.isDefaultPlayer && state.mediaType == 'Video') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePlayerState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
function releaseCurrentPlayer() {
|
||||||
|
|
||||||
|
if (currentPlayer) {
|
||||||
|
|
||||||
|
$(currentPlayer).off('.nowplayingbar');
|
||||||
|
currentPlayer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function bindToPlayer(player) {
|
||||||
|
|
||||||
|
releaseCurrentPlayer();
|
||||||
|
|
||||||
|
currentPlayer = player;
|
||||||
|
|
||||||
|
$(player).on('playbackstart.nowplayingbar', onPlaybackStart)
|
||||||
|
.on('playbackstop.nowplayingbar', onPlaybackStopped)
|
||||||
|
.on('volumechange.nowplayingbar', onVolumeChanged)
|
||||||
|
.on('playstatechange.nowplayingbar', onVolumeChanged)
|
||||||
|
.on('positionchange.nowplayingbar', onVolumeChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
|
||||||
|
$(MediaController).on('playerchange', function () {
|
||||||
|
|
||||||
|
bindToPlayer(MediaController.getCurrentPlayer());
|
||||||
|
});
|
||||||
|
|
||||||
|
bindToPlayer(MediaController.getCurrentPlayer());
|
||||||
|
});
|
||||||
|
|
||||||
|
})(window, document, jQuery, setTimeout, clearTimeout);
|
|
@ -482,7 +482,7 @@ var Dashboard = {
|
||||||
if (user.PrimaryImageTag) {
|
if (user.PrimaryImageTag) {
|
||||||
var imageUrl = ApiClient.getUserImageUrl(user.Id, {
|
var imageUrl = ApiClient.getUserImageUrl(user.Id, {
|
||||||
|
|
||||||
width: 60,
|
width: 28,
|
||||||
tag: user.PrimaryImageTag,
|
tag: user.PrimaryImageTag,
|
||||||
type: "Primary"
|
type: "Primary"
|
||||||
|
|
||||||
|
@ -589,7 +589,7 @@ var Dashboard = {
|
||||||
if (user.PrimaryImageTag) {
|
if (user.PrimaryImageTag) {
|
||||||
|
|
||||||
var url = ApiClient.getUserImageUrl(user.Id, {
|
var url = ApiClient.getUserImageUrl(user.Id, {
|
||||||
width: 225,
|
width: 28,
|
||||||
tag: user.PrimaryImageTag,
|
tag: user.PrimaryImageTag,
|
||||||
type: "Primary"
|
type: "Primary"
|
||||||
});
|
});
|
||||||
|
@ -1286,7 +1286,8 @@ $(function () {
|
||||||
videoPlayerHtml += '<button id="video-nextTrackButton" class="mediaButton nextTrackButton" title="Next Track" type="button" onclick="MediaPlayer.nextTrack();" data-icon="next-track" data-iconpos="notext" data-inline="true">Next Track</button>';
|
videoPlayerHtml += '<button id="video-nextTrackButton" class="mediaButton nextTrackButton" title="Next Track" type="button" onclick="MediaPlayer.nextTrack();" data-icon="next-track" data-iconpos="notext" data-inline="true">Next Track</button>';
|
||||||
|
|
||||||
videoPlayerHtml += '<div class="currentTime"></div>';
|
videoPlayerHtml += '<div class="currentTime"></div>';
|
||||||
videoPlayerHtml += '<div class="nowPlayingMediaInfo"></div>';
|
videoPlayerHtml += '<div class="nowPlayingImage"></div>';
|
||||||
|
videoPlayerHtml += '<div class="nowPlayingText"></div>';
|
||||||
|
|
||||||
videoPlayerHtml += '<button id="video-muteButton" class="mediaButton muteButton" title="Mute" type="button" onclick="MediaPlayer.mute();" data-icon="audio" data-iconpos="notext" data-inline="true">Mute</button>';
|
videoPlayerHtml += '<button id="video-muteButton" class="mediaButton muteButton" title="Mute" type="button" onclick="MediaPlayer.mute();" data-icon="audio" data-iconpos="notext" data-inline="true">Mute</button>';
|
||||||
videoPlayerHtml += '<button id="video-unmuteButton" class="mediaButton unmuteButton" title="Unmute" type="button" onclick="MediaPlayer.unMute();" data-icon="volume-off" data-iconpos="notext" data-inline="true">Unmute</button>';
|
videoPlayerHtml += '<button id="video-unmuteButton" class="mediaButton unmuteButton" title="Unmute" type="button" onclick="MediaPlayer.unMute();" data-icon="volume-off" data-iconpos="notext" data-inline="true">Unmute</button>';
|
||||||
|
@ -1326,49 +1327,7 @@ $(function () {
|
||||||
mediaPlayerElem.trigger('create');
|
mediaPlayerElem.trigger('create');
|
||||||
|
|
||||||
var footerHtml = '<div id="footer" data-theme="b" class="ui-bar-b">';
|
var footerHtml = '<div id="footer" data-theme="b" class="ui-bar-b">';
|
||||||
footerHtml += '<div id="nowPlayingBar" class="nowPlayingBar" style="display:none;">';
|
|
||||||
footerHtml += '<div class="barBackground ui-bar-b"></div>';
|
|
||||||
footerHtml += '<div style="display:inline-block;width:12px;"></div>';
|
|
||||||
footerHtml += '<a id="playlistButton" class="mediaButton playlistButton" href="playlist.html" data-role="button" data-icon="bullets" data-iconpos="notext" data-inline="true" title="Playlist">Playlist</a>';
|
|
||||||
footerHtml += '<button id="previousTrackButton" class="mediaButton previousTrackButton" title="Previous Track" type="button" onclick="MediaPlayer.previousTrack();" data-icon="previous-track" data-iconpos="notext" data-inline="true">Previous Track</button>';
|
|
||||||
footerHtml += '<button id="playButton" class="mediaButton" title="Play" type="button" onclick="MediaPlayer.unpause();" data-icon="play" data-iconpos="notext" data-inline="true">Play</button>';
|
|
||||||
footerHtml += '<button id="pauseButton" class="mediaButton" title="Pause" type="button" onclick="MediaPlayer.pause();" data-icon="pause" data-iconpos="notext" data-inline="true">Pause</button>';
|
|
||||||
|
|
||||||
footerHtml += '<div id="mediaElement"></div>';
|
|
||||||
|
|
||||||
footerHtml += '<button id="stopButton" class="mediaButton" title="Stop" type="button" onclick="MediaPlayer.stop();" data-icon="stop" data-iconpos="notext" data-inline="true">Stop</button>';
|
|
||||||
footerHtml += '<button id="nextTrackButton" class="mediaButton nextTrackButton" title="Next Track" type="button" onclick="MediaPlayer.nextTrack();" data-icon="next-track" data-iconpos="notext" data-inline="true">Next Track</button>';
|
|
||||||
|
|
||||||
footerHtml += '<div class="positionSliderContainer sliderContainer">';
|
|
||||||
footerHtml += '<input type="range" class="mediaSlider positionSlider slider" step=".001" min="0" max="100" value="0" style="display:none;" data-mini="true" data-theme="a" data-highlight="true" />';
|
|
||||||
footerHtml += '</div>';
|
|
||||||
|
|
||||||
footerHtml += '<div class="currentTime"></div>';
|
|
||||||
footerHtml += '<div class="nowPlayingMediaInfo"></div>';
|
|
||||||
|
|
||||||
footerHtml += '<button id="muteButton" class="mediaButton muteButton" title="Mute" type="button" onclick="MediaPlayer.mute();" data-icon="audio" data-iconpos="notext" data-inline="true">Mute</button>';
|
|
||||||
footerHtml += '<button id="unmuteButton" class="mediaButton unmuteButton" title="Unmute" type="button" onclick="MediaPlayer.unMute();" data-icon="volume-off" data-iconpos="notext" data-inline="true">Unmute</button>';
|
|
||||||
|
|
||||||
footerHtml += '<div class="volumeSliderContainer sliderContainer">';
|
|
||||||
footerHtml += '<input type="range" class="mediaSlider volumeSlider slider" step=".05" min="0" max="1" value="0" style="display:none;" data-mini="true" data-theme="a" data-highlight="true" />';
|
|
||||||
footerHtml += '</div>';
|
|
||||||
|
|
||||||
footerHtml += '<button onclick="MediaPlayer.showQualityFlyout();" id="qualityButton" class="mediaButton qualityButton" title="Quality" type="button" data-icon="gear" data-iconpos="notext" data-inline="true">Quality</button>';
|
|
||||||
footerHtml += '<div class="mediaFlyoutContainer"><div id="qualityFlyout" style="display:none;" class="mediaPlayerFlyout"></div></div>';
|
|
||||||
|
|
||||||
footerHtml += '<button onclick="MediaPlayer.showAudioTracksFlyout();" id="audioTracksButton" class="imageButton mediaButton audioTracksButton" title="Audio tracks" type="button" data-icon="audiocd" data-iconpos="notext" data-inline="true">Audio Tracks</button>';
|
|
||||||
footerHtml += '<div class="mediaFlyoutContainer"><div id="audioTracksFlyout" style="display:none;" class="mediaPlayerFlyout audioTracksFlyout"></div></div>';
|
|
||||||
|
|
||||||
footerHtml += '<button onclick="MediaPlayer.showSubtitleMenu();" id="subtitleButton" class="imageButton mediaButton subtitleButton" title="Subtitles" type="button" data-icon="subtitles" data-iconpos="notext" data-inline="true">Subtitles</button>';
|
|
||||||
footerHtml += '<div class="mediaFlyoutContainer"><div id="subtitleFlyout" style="display:none;" class="mediaPlayerFlyout subtitleFlyout"></div></div>';
|
|
||||||
|
|
||||||
footerHtml += '<button onclick="MediaPlayer.showChaptersFlyout();" id="chaptersButton" class="mediaButton chaptersButton" title="Scenes" type="button" data-icon="video" data-iconpos="notext" data-inline="true">Scenes</button>';
|
|
||||||
footerHtml += '<div class="mediaFlyoutContainer"><div id="chaptersFlyout" style="display:none;" class="mediaPlayerFlyout chaptersFlyout"></div></div>';
|
|
||||||
|
|
||||||
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 += '</div>';
|
|
||||||
|
|
||||||
footerHtml += '<div id="footerNotifications"></div>';
|
footerHtml += '<div id="footerNotifications"></div>';
|
||||||
footerHtml += '</div>';
|
footerHtml += '</div>';
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
if (user.PrimaryImageTag) {
|
if (user.PrimaryImageTag) {
|
||||||
|
|
||||||
var imageUrl = ApiClient.getUserImageUrl(user.Id, {
|
var imageUrl = ApiClient.getUserImageUrl(user.Id, {
|
||||||
height: 450,
|
height: 200,
|
||||||
tag: user.PrimaryImageTag,
|
tag: user.PrimaryImageTag,
|
||||||
type: "Primary"
|
type: "Primary"
|
||||||
});
|
});
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
if (user.PrimaryImageTag) {
|
if (user.PrimaryImageTag) {
|
||||||
|
|
||||||
var url = ApiClient.getUserImageUrl(user.Id, {
|
var url = ApiClient.getUserImageUrl(user.Id, {
|
||||||
width: 225,
|
width: 80,
|
||||||
tag: user.PrimaryImageTag,
|
tag: user.PrimaryImageTag,
|
||||||
type: "Primary"
|
type: "Primary"
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
/* jQuery Tiny Pub/Sub - v0.7 - 10/27/2011
|
|
||||||
* http://benalman.com/
|
|
||||||
* Copyright (c) 2011 "Cowboy" Ben Alman; Licensed MIT, GPL */
|
|
||||||
(function (a) { var b = a({}); a.subscribe = function () { b.on.apply(b, arguments) }, a.unsubscribe = function () { b.off.apply(b, arguments) }, a.publish = function () { b.trigger.apply(b, arguments) } })(jQuery)
|
|
|
@ -2197,6 +2197,28 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
|
||||||
dataType: "json"
|
dataType: "json"
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function normalizeImageOptions(options) {
|
||||||
|
|
||||||
|
var ratio = window.devicePixelRatio;
|
||||||
|
|
||||||
|
if (ratio) {
|
||||||
|
|
||||||
|
if (options.width) {
|
||||||
|
options.width = options.width * ratio;
|
||||||
|
}
|
||||||
|
if (options.height) {
|
||||||
|
options.height = options.height * ratio;
|
||||||
|
}
|
||||||
|
if (options.maxWidth) {
|
||||||
|
options.maxWidth = options.maxWidth * ratio;
|
||||||
|
}
|
||||||
|
if (options.maxHeight) {
|
||||||
|
options.maxHeight = options.maxHeight * ratio;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a url for a user image
|
* Constructs a url for a user image
|
||||||
|
@ -2230,6 +2252,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
|
||||||
delete options.type;
|
delete options.type;
|
||||||
delete options.index;
|
delete options.index;
|
||||||
|
|
||||||
|
normalizeImageOptions(options);
|
||||||
|
|
||||||
return self.getUrl(url, options);
|
return self.getUrl(url, options);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2265,215 +2289,7 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
|
||||||
delete options.type;
|
delete options.type;
|
||||||
delete options.index;
|
delete options.index;
|
||||||
|
|
||||||
return self.getUrl(url, options);
|
normalizeImageOptions(options);
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a url for a year image
|
|
||||||
* @param {String} year
|
|
||||||
* @param {Object} options
|
|
||||||
* Options supports the following properties:
|
|
||||||
* width - download the image at a fixed width
|
|
||||||
* height - download the image at a fixed height
|
|
||||||
* maxWidth - download the image at a maxWidth
|
|
||||||
* maxHeight - download the image at a maxHeight
|
|
||||||
* quality - A scale of 0-100. This should almost always be omitted as the default will suffice.
|
|
||||||
* For best results do not specify both width and height together, as aspect ratio might be altered.
|
|
||||||
*/
|
|
||||||
self.getYearImageUrl = function (year, options) {
|
|
||||||
|
|
||||||
if (!year) {
|
|
||||||
throw new Error("null year");
|
|
||||||
}
|
|
||||||
|
|
||||||
options = options || {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var url = "Years/" + year + "/Images/" + options.type;
|
|
||||||
|
|
||||||
if (options.index != null) {
|
|
||||||
url += "/" + options.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't put these on the query string
|
|
||||||
delete options.type;
|
|
||||||
delete options.index;
|
|
||||||
|
|
||||||
return self.getUrl(url, options);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a url for a genre image
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Object} options
|
|
||||||
* Options supports the following properties:
|
|
||||||
* width - download the image at a fixed width
|
|
||||||
* height - download the image at a fixed height
|
|
||||||
* maxWidth - download the image at a maxWidth
|
|
||||||
* maxHeight - download the image at a maxHeight
|
|
||||||
* quality - A scale of 0-100. This should almost always be omitted as the default will suffice.
|
|
||||||
* For best results do not specify both width and height together, as aspect ratio might be altered.
|
|
||||||
*/
|
|
||||||
self.getGenreImageUrl = function (name, options) {
|
|
||||||
|
|
||||||
if (!name) {
|
|
||||||
throw new Error("null name");
|
|
||||||
}
|
|
||||||
|
|
||||||
options = options || {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var url = "Genres/" + self.encodeName(name) + "/Images/" + options.type;
|
|
||||||
|
|
||||||
if (options.index != null) {
|
|
||||||
url += "/" + options.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't put these on the query string
|
|
||||||
delete options.type;
|
|
||||||
delete options.index;
|
|
||||||
|
|
||||||
return self.getUrl(url, options);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a url for a genre image
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Object} options
|
|
||||||
* Options supports the following properties:
|
|
||||||
* width - download the image at a fixed width
|
|
||||||
* height - download the image at a fixed height
|
|
||||||
* maxWidth - download the image at a maxWidth
|
|
||||||
* maxHeight - download the image at a maxHeight
|
|
||||||
* quality - A scale of 0-100. This should almost always be omitted as the default will suffice.
|
|
||||||
* For best results do not specify both width and height together, as aspect ratio might be altered.
|
|
||||||
*/
|
|
||||||
self.getMusicGenreImageUrl = function (name, options) {
|
|
||||||
|
|
||||||
if (!name) {
|
|
||||||
throw new Error("null name");
|
|
||||||
}
|
|
||||||
|
|
||||||
options = options || {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var url = "MusicGenres/" + self.encodeName(name) + "/Images/" + options.type;
|
|
||||||
|
|
||||||
if (options.index != null) {
|
|
||||||
url += "/" + options.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't put these on the query string
|
|
||||||
delete options.type;
|
|
||||||
delete options.index;
|
|
||||||
|
|
||||||
return self.getUrl(url, options);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a url for a genre image
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Object} options
|
|
||||||
* Options supports the following properties:
|
|
||||||
* width - download the image at a fixed width
|
|
||||||
* height - download the image at a fixed height
|
|
||||||
* maxWidth - download the image at a maxWidth
|
|
||||||
* maxHeight - download the image at a maxHeight
|
|
||||||
* quality - A scale of 0-100. This should almost always be omitted as the default will suffice.
|
|
||||||
* For best results do not specify both width and height together, as aspect ratio might be altered.
|
|
||||||
*/
|
|
||||||
self.getGameGenreImageUrl = function (name, options) {
|
|
||||||
|
|
||||||
if (!name) {
|
|
||||||
throw new Error("null name");
|
|
||||||
}
|
|
||||||
|
|
||||||
options = options || {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var url = "GameGenres/" + self.encodeName(name) + "/Images/" + options.type;
|
|
||||||
|
|
||||||
if (options.index != null) {
|
|
||||||
url += "/" + options.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't put these on the query string
|
|
||||||
delete options.type;
|
|
||||||
delete options.index;
|
|
||||||
|
|
||||||
return self.getUrl(url, options);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a url for a artist image
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Object} options
|
|
||||||
* Options supports the following properties:
|
|
||||||
* width - download the image at a fixed width
|
|
||||||
* height - download the image at a fixed height
|
|
||||||
* maxWidth - download the image at a maxWidth
|
|
||||||
* maxHeight - download the image at a maxHeight
|
|
||||||
* quality - A scale of 0-100. This should almost always be omitted as the default will suffice.
|
|
||||||
* For best results do not specify both width and height together, as aspect ratio might be altered.
|
|
||||||
*/
|
|
||||||
self.getArtistImageUrl = function (name, options) {
|
|
||||||
|
|
||||||
if (!name) {
|
|
||||||
throw new Error("null name");
|
|
||||||
}
|
|
||||||
|
|
||||||
options = options || {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var url = "Artists/" + self.encodeName(name) + "/Images/" + options.type;
|
|
||||||
|
|
||||||
if (options.index != null) {
|
|
||||||
url += "/" + options.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't put these on the query string
|
|
||||||
delete options.type;
|
|
||||||
delete options.index;
|
|
||||||
|
|
||||||
return self.getUrl(url, options);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a url for a studio image
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Object} options
|
|
||||||
* Options supports the following properties:
|
|
||||||
* width - download the image at a fixed width
|
|
||||||
* height - download the image at a fixed height
|
|
||||||
* maxWidth - download the image at a maxWidth
|
|
||||||
* maxHeight - download the image at a maxHeight
|
|
||||||
* quality - A scale of 0-100. This should almost always be omitted as the default will suffice.
|
|
||||||
* For best results do not specify both width and height together, as aspect ratio might be altered.
|
|
||||||
*/
|
|
||||||
self.getStudioImageUrl = function (name, options) {
|
|
||||||
|
|
||||||
if (!name) {
|
|
||||||
throw new Error("null name");
|
|
||||||
}
|
|
||||||
|
|
||||||
options = options || {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var url = "Studios/" + self.encodeName(name) + "/Images/" + options.type;
|
|
||||||
|
|
||||||
if (options.index != null) {
|
|
||||||
url += "/" + options.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't put these on the query string
|
|
||||||
delete options.type;
|
|
||||||
delete options.index;
|
|
||||||
|
|
||||||
return self.getUrl(url, options);
|
return self.getUrl(url, options);
|
||||||
};
|
};
|
Loading…
Add table
Add a link
Reference in a new issue