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

Merge pull request #777 from timhobbs/master

Cast updates and lazy loading
This commit is contained in:
Luke 2014-04-10 11:17:36 -04:00
commit b7c828e294
19 changed files with 607 additions and 127 deletions

View file

@ -139,7 +139,7 @@
text-align: left; text-align: left;
margin-left: 0; margin-left: 0;
right: 0; right: 0;
bottom: 83px; bottom: 85px;
} }
/* Media queries /* Media queries
@ -259,7 +259,7 @@
} }
#mediaPlayer #videoControls .mediaPlayerFlyout { #mediaPlayer #videoControls .mediaPlayerFlyout {
bottom: 148px; bottom: 150px;
} }
} }

View file

@ -66,6 +66,17 @@
this.hasReceivers = false; this.hasReceivers = false;
this.currentMediaOffset = 0;
// Progress bar element id
this.progressBar = "positionSlider";
// Timec display element id
this.duration = "currentTime";
// Playback display element id
this.playback = "playTime";
this.initializeCastPlayer(); this.initializeCastPlayer();
}; };
@ -89,7 +100,7 @@
// v1 Id AE4DA10A // v1 Id AE4DA10A
// v2 Id 472F0435 // v2 Id 472F0435
var applicationID = 'AE4DA10A'; var applicationID = '472F0435';
// request session // request session
var sessionRequest = new chrome.cast.SessionRequest(applicationID); var sessionRequest = new chrome.cast.SessionRequest(applicationID);
@ -445,6 +456,8 @@
function getMetadata(item) { function getMetadata(item) {
console.log("md item", item);
var metadata = {}; var metadata = {};
if (item.Type == 'Episode') { if (item.Type == 'Episode') {
@ -512,7 +525,7 @@
else if (item.MediaType == 'Movie') { else if (item.MediaType == 'Movie') {
metadata = new chrome.cast.media.MovieMediaMetadata(); metadata = new chrome.cast.media.MovieMediaMetadata();
metadata.type = chrome.cast.media.MetadataType.MUSIC_TRACK; metadata.type = chrome.cast.media.MetadataType.MOVIE;
if (item.ProductionYear) { if (item.ProductionYear) {
metadata.releaseYear = item.ProductionYear; metadata.releaseYear = item.ProductionYear;
@ -617,6 +630,8 @@
return; return;
} }
this.currentMediaOffset = startTimeTicks || 0;
var maxBitrate = 12000000; var maxBitrate = 12000000;
var mediaInfo = getMediaSourceInfo(user, item, maxBitrate, mediaSourceId, audioStreamIndex, subtitleStreamIndex); var mediaInfo = getMediaSourceInfo(user, item, maxBitrate, mediaSourceId, audioStreamIndex, subtitleStreamIndex);
@ -653,40 +668,62 @@
console.log("chromecast new media session ID:" + mediaSession.mediaSessionId + ' (' + how + ')'); console.log("chromecast new media session ID:" + mediaSession.mediaSessionId + ' (' + how + ')');
this.currentMediaSession = mediaSession; this.currentMediaSession = mediaSession;
this.currentMediaTime = this.session.media[0].currentTime;
if (how == 'loadMedia') { if (how == 'loadMedia') {
this.castPlayerState = PLAYER_STATE.PLAYING; this.castPlayerState = PLAYER_STATE.PLAYING;
clearInterval(this.timer);
this.startProgressTimer(this.incrementMediaTime);
} }
if (how == 'activeSession') { if (how == 'activeSession') {
this.castPlayerState = this.session.media[0].playerState; this.castPlayerState = this.session.media[0].playerState;
this.currentMediaTime = this.session.media[0].currentTime;
} }
if (this.castPlayerState == PLAYER_STATE.PLAYING) { if (this.castPlayerState == PLAYER_STATE.PLAYING) {
// start progress timer // start progress timer
//this.startProgressTimer(this.incrementMediaTime); this.startProgressTimer(this.incrementMediaTime);
} }
this.currentMediaSession.addUpdateListener(this.onMediaStatusUpdate.bind(this)); this.currentMediaSession.addUpdateListener(this.onMediaStatusUpdate.bind(this));
this.currentMediaDuration = this.currentMediaSession.media.duration;
//this.currentMediaDuration = this.currentMediaSession.media.duration; var playTime = document.getElementById(this.playback);
//var duration = this.currentMediaDuration; if (!playTime) {
//var hr = parseInt(duration / 3600); // Set duration time
//duration -= hr * 3600; var totalTime = document.getElementById(this.duration);
//var min = parseInt(duration / 60); totalTime.innerHTML = " / " + formatTime(this.currentMediaDuration);
//var sec = parseInt(duration % 60);
//if (hr > 0) { // Set play time
// duration = hr + ":" + min + ":" + sec; playTime = document.createElement("div");
//} playTime.id = this.playback;
//else { playTime.className = "currentTime";
// if (min > 0) { playTime.style.marginRight = "5px";
// duration = min + ":" + sec; totalTime.parentNode.insertBefore(playTime, totalTime);
// } playTime.innerHTML = formatTime(this.currentMediaTime);
// else { }
// duration = sec; };
// }
//} function formatTime(duration) {
//document.getElementById("duration").innerHTML = duration; var hr = parseInt(duration / 3600);
duration -= hr * 3600;
var min = parseInt(duration / 60);
var sec = parseInt(duration % 60);
hr = "" + hr;
min = "" + min;
sec = "" + sec;
var hh = pad(hr);
var mm = pad(min);
var ss = pad(sec);
duration = hh + ":" + mm + ":" + ss;
return duration;
};
function pad(s) {
return "00".substring(0, 2 - s.length) + s;
}; };
/** /**
@ -707,7 +744,7 @@
this.castPlayerState = PLAYER_STATE.IDLE; this.castPlayerState = PLAYER_STATE.IDLE;
} }
console.log("chromecast updating media"); console.log("chromecast updating media");
//this.updateProgressBar(e); this.updateProgressBarByTimer();
}; };
/** /**
@ -745,6 +782,7 @@
this.currentMediaSession.addUpdateListener(this.onMediaStatusUpdate.bind(this)); this.currentMediaSession.addUpdateListener(this.onMediaStatusUpdate.bind(this));
this.castPlayerState = PLAYER_STATE.PLAYING; this.castPlayerState = PLAYER_STATE.PLAYING;
// start progress timer // start progress timer
clearInterval(this.timer);
this.startProgressTimer(this.incrementMediaTime); this.startProgressTimer(this.incrementMediaTime);
break; break;
case PLAYER_STATE.IDLE: case PLAYER_STATE.IDLE:
@ -791,6 +829,10 @@
this.onError.bind(this)); this.onError.bind(this));
this.castPlayerState = PLAYER_STATE.STOPPED; this.castPlayerState = PLAYER_STATE.STOPPED;
clearInterval(this.timer); clearInterval(this.timer);
var playTime = document.getElementById(this.playback);
if (playTime) {
playTime.parentNode.removeChild(playTime);
}
}; };
/** /**
@ -849,19 +891,10 @@
* @param {Event} e An event object from seek * @param {Event} e An event object from seek
*/ */
CastPlayer.prototype.seekMedia = function (event) { CastPlayer.prototype.seekMedia = function (event) {
var pos = parseInt(event.offsetX); var pos = parseInt(event);
var pi = document.getElementById("progress_indicator"); var p = document.getElementById(this.progressBar);
var p = document.getElementById("progress"); var curr = parseInt(this.currentMediaTime + this.currentMediaDuration * pos);
if (event.currentTarget.id == 'progress_indicator') { var pw = parseInt(p.value) + pos;
var curr = parseInt(this.currentMediaTime + this.currentMediaDuration * pos / PROGRESS_BAR_WIDTH);
var pp = parseInt(pi.style.marginLeft) + pos;
var pw = parseInt(p.style.width) + pos;
}
else {
var curr = parseInt(pos * this.currentMediaDuration / PROGRESS_BAR_WIDTH);
var pp = pos - 21 - PROGRESS_BAR_WIDTH;
var pw = pos;
}
if (this.castPlayerState != PLAYER_STATE.PLAYING && this.castPlayerState != PLAYER_STATE.PAUSED) { if (this.castPlayerState != PLAYER_STATE.PLAYING && this.castPlayerState != PLAYER_STATE.PAUSED) {
return; return;
@ -899,20 +932,20 @@
* @param {Object} e An media status update object * @param {Object} e An media status update object
*/ */
CastPlayer.prototype.updateProgressBar = function (e) { CastPlayer.prototype.updateProgressBar = function (e) {
var p = document.getElementById("progress"); var p = document.getElementById(this.progressBar);
var pi = document.getElementById("progress_indicator");
if (e.idleReason == 'FINISHED' && e.playerState == 'IDLE') { if (e.idleReason == 'FINISHED' && e.playerState == 'IDLE') {
p.style.width = '0px'; p.value = 0;
pi.style.marginLeft = -21 - PROGRESS_BAR_WIDTH + 'px';
clearInterval(this.timer); clearInterval(this.timer);
this.castPlayerState = PLAYER_STATE.STOPPED; this.castPlayerState = PLAYER_STATE.STOPPED;
if (e.idleReason == 'FINISHED') {
$.publish("/playback/complete", e);
console.log("playback complete", e);
}
} }
else { else {
p.style.width = Math.ceil(PROGRESS_BAR_WIDTH * e.currentTime / this.currentMediaSession.media.duration + 1) + 'px'; p.value = Number(e.currentTime / this.currentMediaSession.media.duration + 1).toFixed(3);
this.progressFlag = false; this.progressFlag = false;
setTimeout(this.setProgressFlag.bind(this), 1000); // don't update progress in 1 second setTimeout(this.setProgressFlag.bind(this), 1000); // don't update progress in 1 second
var pp = Math.ceil(PROGRESS_BAR_WIDTH * e.currentTime / this.currentMediaSession.media.duration);
pi.style.marginLeft = -21 - PROGRESS_BAR_WIDTH + pp + 'px';
} }
}; };
@ -928,47 +961,159 @@
* Update progress bar based on timer * Update progress bar based on timer
*/ */
CastPlayer.prototype.updateProgressBarByTimer = function () { CastPlayer.prototype.updateProgressBarByTimer = function () {
var p = document.getElementById("progress"); var p = document.getElementById(this.progressBar);
if (isNaN(parseInt(p.style.width))) { if (isNaN(parseInt(p.value))) {
p.style.width = 0; p.value = 0;
} }
if (this.currentMediaDuration > 0) { if (this.currentMediaDuration > 0) {
var pp = Math.floor(PROGRESS_BAR_WIDTH * this.currentMediaTime / this.currentMediaDuration); var pp = Number(this.currentMediaTime / this.currentMediaDuration).toFixed(3);
var startTime = this.currentMediaOffset / 10000000;
var playTime = document.getElementById(this.playback);
if (playTime) {
playTime.innerHTML = formatTime(startTime + this.currentMediaTime);
}
} }
if (this.progressFlag) { if (this.progressFlag) {
// don't update progress if it's been updated on media status update event // don't update progress if it's been updated on media status update event
p.style.width = pp + 'px'; p.value = pp;
var pi = document.getElementById("progress_indicator");
pi.style.marginLeft = -21 - PROGRESS_BAR_WIDTH + pp + 'px';
} }
if (pp > PROGRESS_BAR_WIDTH) { if (pp > 100 || this.castPlayerState == PLAYER_STATE.IDLE) {
clearInterval(this.timer); clearInterval(this.timer);
this.deviceState = DEVICE_STATE.IDLE; this.deviceState = DEVICE_STATE.IDLE;
this.castPlayerState = PLAYER_STATE.IDLE; this.castPlayerState = PLAYER_STATE.IDLE;
$.publish("/playback/complete", true);
console.log("playback complete");
} }
}; };
/**
* @param {function} A callback function for the fucntion to start timer
*/
CastPlayer.prototype.startProgressTimer = function(callback) {
if(this.timer) {
clearInterval(this.timer);
this.timer = null;
}
// start progress timer
this.timer = setInterval(callback.bind(this), this.timerStep);
};
var castPlayer = new CastPlayer(); var castPlayer = new CastPlayer();
function chromecastPlayer() { function chromecastPlayer(castPlayer) {
var self = this; var self = this;
var isPositionSliderActive = false;
self.name = PlayerName; self.name = PlayerName;
self.play = function (options) { self.isPaused = false;
if (options.items) { self.playlist = [];
Dashboard.getCurrentUser().done(function (user) { self.playlistIndex = 0;
castPlayer.loadMedia(user, options.items[0], options.startTimeTicks); $.subscribe("/playback/complete", function (e) {
if (self.playlistIndex < (self.playlist.items || []).length) {
self.play(self.playlist);
}
}); });
} else { ////$(".positionSlider", "#footer").off("slidestart slidestop")
//// .on('slidestart', function (e) {
//// isPositionSliderActive = true;
////}).on('slidestop', positionSliderChange);
////function positionSliderChange() {
//// isPositionSliderActive = false;
//// var newPercent = parseInt(this.value);
//// self.changeStream(newPercent);
////}
function getItemsForPlayback(query) {
var userId = Dashboard.getCurrentUserId();
query.Limit = query.Limit || 100;
query.Fields = getItemFields;
query.ExcludeLocationTypes = "Virtual";
return ApiClient.getItems(userId, query);
};
function queueItems (items) {
for (var i = 0, length = items.length; i < length; i++) {
self.playlist.push(items[i]);
}
};
function queueItemsNext(items) {
var insertIndex = 1;
for (var i = 0, length = items.length; i < length; i++) {
self.playlist.splice(insertIndex, 0, items[i]);
insertIndex++;
}
};
function translateItemsForPlayback(items) {
var deferred = $.Deferred();
var firstItem = items[0];
var promise;
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 (promise) {
promise.done(function (result) {
deferred.resolveWith(null, [result.Items]);
});
} else {
deferred.resolveWith(null, [items]);
}
return deferred.promise();
};
self.play = function (options) {
console.log("play", options);
$("#nowPlayingBar", "#footer").show();
if (self.isPaused) {
self.isPaused = !self.isPaused;
castPlayer.playMedia();
} else if (options.items) {
Dashboard.getCurrentUser().done(function (user) {
castPlayer.loadMedia(user, options.items[self.playlistIndex++], options.startPositionTicks);
});
} else {
var userId = Dashboard.getCurrentUserId(); var userId = Dashboard.getCurrentUserId();
var query = {}; var query = {};
@ -978,46 +1123,154 @@
query.Ids = options.ids.join(','); query.Ids = options.ids.join(',');
ApiClient.getItems(userId, query).done(function (result) { ApiClient.getItems(userId, query).done(function (result) {
options.items = result.Items; options.items = result.Items;
self.play(options); self.play(options);
}); });
} }
};
self.unpause = function () {
console.log("unpause");
self.isPaused = !self.isPaused;
castPlayer.playMedia();
};
self.pause = function () {
console.log("pause");
self.isPaused = true;
castPlayer.pauseMedia();
}; };
self.shuffle = function (id) { self.shuffle = function (id) {
self.play({ ids: [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.playlist = { items: result.Items };
console.log("shuffle items", result.Items);
self.play(self.playlist);
});
});
}; };
self.instantMix = function (id) { self.instantMix = function (id) {
self.play({ ids: [id] }); var userId = Dashboard.getCurrentUserId();
}; ApiClient.getItem(userId, id).done(function (item) {
var promise;
var getItemFields = "MediaSources,Chapters";
var mixLimit = 3;
self.queue = function (options) { if (item.Type == "MusicArtist") {
promise = ApiClient.getInstantMixFromArtist(name, {
UserId: userId,
Fields: getItemFields,
Limit: mixLimit
});
}
else if (item.Type == "MusicGenre") {
promise = ApiClient.getInstantMixFromMusicGenre(name, {
UserId: userId,
Fields: getItemFields,
Limit: mixLimit
});
}
else if (item.Type == "MusicAlbum") {
promise = ApiClient.getInstantMixFromAlbum(id, {
UserId: userId,
Fields: getItemFields,
Limit: mixLimit
});
}
else if (item.Type == "Audio") {
promise = ApiClient.getInstantMixFromSong(id, {
UserId: userId,
Fields: getItemFields,
Limit: mixLimit
});
}
else {
return;
}
}; promise.done(function (result) {
self.playlist = { items: result.Items };
self.queueNext = function (options) { console.log("instant mix items", result.Items);
self.play(self.playlist);
}; });
});
self.stop = function () {
castPlayer.stop();
}; };
self.canQueueMediaType = function (mediaType) { self.canQueueMediaType = function (mediaType) {
return mediaType == "Audio";
};
return false; self.queue = function (options) {
Dashboard.getCurrentUser().done(function (user) {
if (options.items) {
translateItemsForPlayback(options.items).done(function (items) {
queueItems(items);
});
} else {
getItemsForPlayback({
Ids: options.ids.join(',')
}).done(function (result) {
translateItemsForPlayback(result.Items).done(function (items) {
queueItems(items);
});
});
}
});
};
self.queueNext = function (options) {
Dashboard.getCurrentUser().done(function (user) {
if (options.items) {
queueItemsNext(options.items);
} else {
self.getItemsForPlayback({
Ids: options.ids.join(',')
}).done(function (result) {
options.items = result.Items;
queueItemsNext(options.items);
});
}
});
};
self.stop = function () {
$("#nowPlayingBar", "#footer").hide();
self.playlist = [];
self.playlistIndex = 0;
castPlayer.stopMedia();
}; };
self.mute = function () { self.mute = function () {
castPlayer.mute(); castPlayer.mute();
}; };
self.unMute = function () { self.unmute = function () {
castPlayer.unMute(); castPlayer.unMute();
}; };
@ -1026,18 +1279,13 @@
}; };
self.getTargets = function () { self.getTargets = function () {
var targets = []; var targets = [];
targets.push(self.getCurrentTargetInfo()); targets.push(self.getCurrentTargetInfo());
return targets; return targets;
}; };
self.getCurrentTargetInfo = function () { self.getCurrentTargetInfo = function () {
var appName = null; var appName = null;
if (castPlayer.session && castPlayer.session.receiver && castPlayer.session.friendlyName) { if (castPlayer.session && castPlayer.session.receiver && castPlayer.session.friendlyName) {
appName = castPlayer.session.friendlyName; appName = castPlayer.session.friendlyName;
} }
@ -1051,9 +1299,80 @@
appName: appName appName: appName
}; };
}; };
self.setCurrentTime = function (ticks, item, updateSlider) {
// Convert to ticks
ticks = Math.floor(ticks);
var timeText = Dashboard.getDisplayTime(ticks);
if (self.currentDurationTicks) {
timeText += " / " + Dashboard.getDisplayTime(self.currentDurationTicks);
if (updateSlider) {
var percent = ticks / self.currentDurationTicks;
percent *= 100;
self.positionSlider.val(percent).slider('enable').slider('refresh');
}
} else {
self.positionSlider.slider('disable').slider('refresh');
} }
MediaController.registerPlayer(new chromecastPlayer()); self.currentTimeElement.html(timeText);
};
self.changeStream = function (position) {
console.log("seek", position);
////castPlayer.seekMedia(position);
};
self.removeFromPlaylist = function (i) {
self.playlist.remove(i);
};
self.currentPlaylistIndex = function (i) {
if (i == null) {
return currentPlaylistIndex;
}
var newItem = self.playlist[i];
Dashboard.getCurrentUser().done(function (user) {
self.playInternal(newItem, 0, user);
currentPlaylistIndex = i;
});
};
self.nextTrack = function () {
var newIndex = currentPlaylistIndex + 1;
var newItem = self.playlist[newIndex];
if (newItem) {
Dashboard.getCurrentUser().done(function (user) {
self.playInternal(newItem, 0, user);
currentPlaylistIndex = newIndex;
});
}
};
self.previousTrack = function () {
var newIndex = currentPlaylistIndex - 1;
if (newIndex >= 0) {
var newItem = self.playlist[newIndex];
if (newItem) {
Dashboard.getCurrentUser().done(function (user) {
self.playInternal(newItem, 0, user);
currentPlaylistIndex = newIndex;
});
}
}
};
self.volumeDown = function () {
};
self.volumeUp = function () {
};
}
MediaController.registerPlayer(new chromecastPlayer(castPlayer));
$(MediaController).on('playerchange', function () { $(MediaController).on('playerchange', function () {

View file

@ -34,7 +34,8 @@
showTitle: true, showTitle: true,
showParentTitle: true, showParentTitle: true,
overlayText: true, overlayText: true,
selectionPanel: true selectionPanel: true,
lazy: true
}); });
$('.itemsContainer', page).removeClass('timelineItemsContainer'); $('.itemsContainer', page).removeClass('timelineItemsContainer');

View file

@ -432,6 +432,8 @@
options.shape = options.shape || "portrait"; options.shape = options.shape || "portrait";
options.lazy = options.lazy || false;
var html = ""; var html = "";
var primaryImageAspectRatio = options.shape == 'auto' ? LibraryBrowser.getAveragePrimaryImageAspectRatio(items) : null; var primaryImageAspectRatio = options.shape == 'auto' ? LibraryBrowser.getAveragePrimaryImageAspectRatio(items) : null;
@ -667,7 +669,7 @@
var style = ""; var style = "";
if (imgUrl) { if (imgUrl && !options.lazy) {
style += 'background-image:url(\'' + imgUrl + '\');'; style += 'background-image:url(\'' + imgUrl + '\');';
} }
@ -680,9 +682,16 @@
imageCssClass += " coveredPosterItemImage"; imageCssClass += " coveredPosterItemImage";
} }
var dataSrc = "";
if (options.lazy) {
imageCssClass += " lazy";
dataSrc = ' data-src="' + imgUrl + '"';
}
var progressHtml = options.showProgress === false ? '' : LibraryBrowser.getItemProgressBarHtml(item); var progressHtml = options.showProgress === false ? '' : LibraryBrowser.getItemProgressBarHtml(item);
html += '<div class="' + imageCssClass + '" style="' + style + '">'; html += '<div class="' + imageCssClass + '" style="' + style + '"' + dataSrc + '>';
html += '<div class="posterItemOverlayTarget"></div>'; html += '<div class="posterItemOverlayTarget"></div>';
@ -755,6 +764,10 @@
var itemCountHtml = LibraryBrowser.getItemCountsHtml(options, item); var itemCountHtml = LibraryBrowser.getItemCountsHtml(options, item);
if (item.Type == "Person" && !itemCountHtml) {
itemCountHtml = "&nbsp;";
}
if (itemCountHtml) { if (itemCountHtml) {
html += "<div class='" + cssClass + "'>"; html += "<div class='" + cssClass + "'>";
html += itemCountHtml; html += itemCountHtml;

View file

@ -174,6 +174,62 @@
return p.isDefaultPlayer; return p.isDefaultPlayer;
})[0]; })[0];
}; };
self.pause = function () {
currentPlayer.pause();
};
self.stop = function () {
currentPlayer.stop();
};
self.unpause = function () {
currentPlayer.unpause();
};
self.seek = function (position) {
currentPlayer.changeStream(position);
};
self.currentPlaylistIndex = function (i) {
currentPlayer.currentPlaylistIndex(i);
};
self.removeFromPlaylist = function (i) {
currentPlayer.removeFromPlaylist(i);
};
self.nextTrack = function () {
currentPlayer.nextTrack();
};
self.previousTrack = function () {
currentPlayer.previousTrack();
};
self.mute = function () {
currentPlayer.mute();
};
self.unmute = function () {
currentPlayer.unmute();
};
self.toggleMute = function () {
currentPlayer.toggleMute();
};
self.volumeDown = function () {
currentPlayer.volumeDown();
};
self.volumeUp = function () {
currentPlayer.volumeUp();
};
self.shuffle = function (id) {
currentPlayer.shuffle(id);
};
} }
window.MediaController = new mediaController(); window.MediaController = new mediaController();

View file

@ -872,18 +872,18 @@
$('#video-fullscreenButton', videoControls).show(); $('#video-fullscreenButton', videoControls).show();
} }
var videoElement = $("video", videoElement); var video = $("video", videoElement);
initialVolume = localStorage.getItem("volume") || 0.5; initialVolume = localStorage.getItem("volume") || 0.5;
videoElement.each(function () { video.each(function () {
this.volume = initialVolume; this.volume = initialVolume;
}); });
self.volumeSlider.val(initialVolume).slider('refresh'); self.volumeSlider.val(initialVolume).slider('refresh');
self.updateVolumeButtons(initialVolume); self.updateVolumeButtons(initialVolume);
videoElement.on("volumechange", function (e) { video.on("volumechange", function (e) {
var muted = this.muted; var muted = this.muted;
@ -899,13 +899,13 @@
}).on("play.once", function () { }).on("play.once", function () {
videoElement.off("play.once"); video.off("play.once");
}).on("playing.once", function () { }).on("playing.once", function () {
self.updateCanClientSeek(this); self.updateCanClientSeek(this);
videoElement.off("playing.once"); video.off("playing.once");
ApiClient.reportPlaybackStart(Dashboard.getCurrentUserId(), item.Id, mediaSource.Id, true, item.MediaType); ApiClient.reportPlaybackStart(Dashboard.getCurrentUserId(), item.Id, mediaSource.Id, true, item.MediaType);
@ -1037,7 +1037,7 @@
currentItem = item; currentItem = item;
currentMediaSource = mediaSource; currentMediaSource = mediaSource;
return videoElement[0]; return video[0];
} }
}; };
})(); })();

View file

@ -33,7 +33,8 @@
shape: "portrait", shape: "portrait",
context: 'movies', context: 'movies',
showTitle: true, showTitle: true,
centerText: true centerText: true,
lazy: true
}); });
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount); html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount);

View file

@ -34,7 +34,8 @@
context: 'movies', context: 'movies',
showTitle: true, showTitle: true,
showItemCounts: true, showItemCounts: true,
coverImage: true coverImage: true,
lazy: true
}); });
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount, false, [], false); html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount, false, [], false);

View file

@ -35,7 +35,8 @@
shape: "backdrop", shape: "backdrop",
preferThumb: true, preferThumb: true,
context: 'movies', context: 'movies',
selectionPanel: true selectionPanel: true,
lazy: true
}); });
$('.itemsContainer', page).removeClass('timelineItemsContainer'); $('.itemsContainer', page).removeClass('timelineItemsContainer');
} }
@ -45,7 +46,8 @@
items: result.Items, items: result.Items,
shape: "banner", shape: "banner",
preferBanner: true, preferBanner: true,
context: 'movies' context: 'movies',
lazy: true
}); });
$('.itemsContainer', page).removeClass('timelineItemsContainer'); $('.itemsContainer', page).removeClass('timelineItemsContainer');
} }
@ -56,7 +58,8 @@
context: 'movies', context: 'movies',
showTitle: true, showTitle: true,
centerText: true, centerText: true,
selectionPanel: true selectionPanel: true,
lazy: true
}); });
$('.itemsContainer', page).removeClass('timelineItemsContainer'); $('.itemsContainer', page).removeClass('timelineItemsContainer');
} }
@ -68,7 +71,8 @@
showTitle: true, showTitle: true,
timeline: true, timeline: true,
centerText: true, centerText: true,
selectionPanel: true selectionPanel: true,
lazy: true
}); });
$('.itemsContainer', page).addClass('timelineItemsContainer'); $('.itemsContainer', page).addClass('timelineItemsContainer');
} }

View file

@ -32,7 +32,8 @@
context: 'music', context: 'music',
showTitle: true, showTitle: true,
coverImage: true, coverImage: true,
centerText: true centerText: true,
lazy: true
}); });
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount); html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount);

View file

@ -34,7 +34,8 @@
shape: "square", shape: "square",
context: 'music', context: 'music',
showTitle: true, showTitle: true,
showParentTitle: true showParentTitle: true,
lazy: true
}); });
$('.itemsContainer', page).removeClass('timelineItemsContainer'); $('.itemsContainer', page).removeClass('timelineItemsContainer');
} }
@ -45,7 +46,8 @@
context: 'music', context: 'music',
showTitle: true, showTitle: true,
showParentTitle: true, showParentTitle: true,
timeline: true timeline: true,
lazy: true
}); });
$('.itemsContainer', page).addClass('timelineItemsContainer'); $('.itemsContainer', page).addClass('timelineItemsContainer');
} }

View file

@ -31,7 +31,8 @@
context: 'music', context: 'music',
showTitle: true, showTitle: true,
coverImage: true, coverImage: true,
centerText: true centerText: true,
lazy: true
}); });
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount); html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount);
@ -119,4 +120,10 @@
updateFilterControls(this); updateFilterControls(this);
}); });
$(function () {
$("body").on("create", function () {
$(".lazy").unveil(200);
});
});
})(jQuery, document); })(jQuery, document);

View file

@ -32,7 +32,8 @@
preferThumb: true, preferThumb: true,
context: 'music', context: 'music',
showItemCounts: true, showItemCounts: true,
centerText: true centerText: true,
lazy: true
}); });
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount); html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount);

View file

@ -17,7 +17,7 @@
html += '<tbody>'; html += '<tbody>';
$.each(MediaPlayer.playlist, function (i, item) { $.each(MediaController.playlist, function (i, item) {
var name = LibraryBrowser.getPosterViewDisplayName(item); var name = LibraryBrowser.getPosterViewDisplayName(item);
@ -65,14 +65,14 @@
var index = parseInt(this.getAttribute('data-index')); var index = parseInt(this.getAttribute('data-index'));
MediaPlayer.currentPlaylistIndex(index); MediaController.currentPlaylistIndex(index);
reloadPlaylist(page); reloadPlaylist(page);
}).on('click', '.lnkRemove', function () { }).on('click', '.lnkRemove', function () {
var index = parseInt(this.getAttribute('data-index')); var index = parseInt(this.getAttribute('data-index'));
MediaPlayer.removeFromPlaylist(index); MediaController.removeFromPlaylist(index);
reloadPlaylist(page); reloadPlaylist(page);
}); });

View file

@ -1330,42 +1330,42 @@ $(function () {
footerHtml += '<div class="barBackground ui-bar-b"></div>'; footerHtml += '<div class="barBackground ui-bar-b"></div>';
footerHtml += '<div style="display:inline-block;width:12px;"></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 += '<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="previousTrackButton" class="mediaButton previousTrackButton" title="Previous Track" type="button" onclick="MediaController.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="playButton" class="mediaButton" title="Play" type="button" onclick="MediaController.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 += '<button id="pauseButton" class="mediaButton" title="Pause" type="button" onclick="MediaController.pause();" data-icon="pause" data-iconpos="notext" data-inline="true">Pause</button>';
footerHtml += '<div id="mediaElement"></div>'; 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="stopButton" class="mediaButton" title="Stop" type="button" onclick="MediaController.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 += '<button id="nextTrackButton" class="mediaButton nextTrackButton" title="Next Track" type="button" onclick="MediaController.nextTrack();" data-icon="next-track" data-iconpos="notext" data-inline="true">Next Track</button>';
footerHtml += '<div class="positionSliderContainer sliderContainer">'; 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 += '<input id="positionSlider" 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>';
footerHtml += '<div class="currentTime"></div>'; footerHtml += '<div class="currentTime" id="currentTime"></div>';
footerHtml += '<div class="nowPlayingMediaInfo"></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="muteButton" class="mediaButton muteButton" title="Mute" type="button" onclick="MediaController.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 += '<button id="unmuteButton" class="mediaButton unmuteButton" title="Unmute" type="button" onclick="MediaController.unMute();" data-icon="volume-off" data-iconpos="notext" data-inline="true">Unmute</button>';
footerHtml += '<div class="volumeSliderContainer sliderContainer">'; 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 += '<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 += '</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 += '<button onclick="MediaController.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 += '<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 += '<button onclick="MediaController.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 += '<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 += '<button onclick="MediaController.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 += '<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 += '<button onclick="MediaController.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 += '<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 += '<button onclick="MediaController.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>';
@ -1386,6 +1386,10 @@ $(function () {
ApiClient.closeWebSocket(); ApiClient.closeWebSocket();
} }
}); });
$("body").on("create", function () {
$(".lazy").unveil(200);
});
}); });
Dashboard.jQueryMobileInit(); Dashboard.jQueryMobileInit();
@ -1428,4 +1432,3 @@ $(document).on('pagebeforeshow', ".page", function () {
Dashboard.refreshSystemInfoFromServer(); Dashboard.refreshSystemInfoFromServer();
} }
}); });

View file

@ -34,7 +34,8 @@
context: 'tv', context: 'tv',
showTitle: true, showTitle: true,
showItemCounts: true, showItemCounts: true,
coverImage: true coverImage: true,
lazy: true
}); });
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount, false, [], false); html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount, false, [], false);

View file

@ -34,7 +34,8 @@
items: result.Items, items: result.Items,
shape: "backdrop", shape: "backdrop",
preferThumb: true, preferThumb: true,
context: 'tv' context: 'tv',
lazy: true
}); });
$('.itemsContainer', page).removeClass('timelineItemsContainer'); $('.itemsContainer', page).removeClass('timelineItemsContainer');
@ -45,7 +46,8 @@
items: result.Items, items: result.Items,
shape: "banner", shape: "banner",
preferBanner: true, preferBanner: true,
context: 'tv' context: 'tv',
lazy: true
}); });
$('.itemsContainer', page).removeClass('timelineItemsContainer'); $('.itemsContainer', page).removeClass('timelineItemsContainer');
} }
@ -56,7 +58,8 @@
shape: "portrait", shape: "portrait",
context: 'tv', context: 'tv',
showTitle: true, showTitle: true,
centerText: true centerText: true,
lazy: true
}); });
$('.itemsContainer', page).removeClass('timelineItemsContainer'); $('.itemsContainer', page).removeClass('timelineItemsContainer');
} }
@ -67,7 +70,8 @@
shape: "portrait", shape: "portrait",
context: 'tv', context: 'tv',
timeline: true, timeline: true,
showTitle: true showTitle: true,
lazy: true
}); });
$('.itemsContainer', page).addClass('timelineItemsContainer'); $('.itemsContainer', page).addClass('timelineItemsContainer');

View file

@ -0,0 +1,4 @@
/* 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)

View file

@ -0,0 +1,62 @@
/**
* jQuery Unveil
* A very lightweight jQuery plugin to lazy load images
* http://luis-almeida.github.com/unveil
*
* Licensed under the MIT license.
* Copyright 2013 Luís Almeida
* https://github.com/luis-almeida
*/
; (function ($) {
$.fn.unveil = function (threshold, callback) {
var $w = $(window),
th = threshold || 0,
retina = window.devicePixelRatio > 1,
attrib = retina ? "data-src-retina" : "data-src",
images = this,
loaded;
this.one("unveil", function () {
var elemType = $(this).get(0).tagName;
var source = this.getAttribute(attrib);
source = source || this.getAttribute("data-src");
if (source) {
if (elemType === "DIV") {
this.style.backgroundImage = "url('" + source + "')";
} else {
this.setAttribute("src", source);
}
if (typeof callback === "function") callback.call(this);
}
});
function unveil() {
var inview = images.filter(function () {
var $e = $(this);
if ($e.is(":hidden")) return;
var wt = $w.scrollTop(),
wb = wt + $w.height(),
et = $e.offset().top,
eb = et + $e.height();
return eb >= wt - th && et <= wb + th;
});
loaded = inview.trigger("unveil");
images = images.not(loaded);
}
$w.scroll(unveil);
$w.resize(unveil);
unveil();
return this;
};
})(window.jQuery || window.Zepto);