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

add new mirror mode

This commit is contained in:
Luke Pulverenti 2014-04-13 13:27:13 -04:00
parent 2835534c6d
commit 9f83edf9ec
18 changed files with 316 additions and 191 deletions

View file

@ -1267,6 +1267,10 @@
castPlayer.stopMedia();
};
self.displayContent = function (options) {
};
self.mute = function () {
castPlayer.mute();
};
@ -1280,12 +1284,19 @@
};
self.getTargets = function () {
var targets = [];
targets.push(self.getCurrentTargetInfo());
if (castPlayer.hasReceivers) {
targets.push(self.getCurrentTargetInfo());
}
return targets;
};
self.getCurrentTargetInfo = function () {
var appName = null;
if (castPlayer.session && castPlayer.session.receiver && castPlayer.session.friendlyName) {
appName = castPlayer.session.friendlyName;
@ -1297,7 +1308,8 @@
playerName: self.name,
playableMediaTypes: ["Audio", "Video"],
isLocalPlayer: false,
appName: appName
appName: appName,
supportedCommands: []
};
};

View file

@ -66,18 +66,11 @@
renderDetails(page, item);
renderTabs(page, item);
if (ApiClient.isWebSocketOpen()) {
$(page).trigger('displayingitem', [{
var vals = [item.Type, item.Id, item.Name];
var context = getParameterByName('context');
if (context) {
vals.push(vals);
}
ApiClient.sendWebSocketMessage("Context", vals.join('|'));
}
item: item,
context: getParameterByName('context')
}]);
Dashboard.getCurrentUser().done(function (user) {
@ -403,7 +396,7 @@
};
query = $.extend(query, options || {});
if (query.IncludeItemTypes == "Audio") {
query.SortBy = "Album,SortName";
}

View file

@ -75,11 +75,11 @@
}
if (!item.LocalTrailerCount && item.RemoteTrailers.length && item.PlayAccess == 'Full') {
$('.btnPlayExternalTrailer', page).removeClass('hide').attr('href', item.RemoteTrailers[0].Url);
} else {
$('.btnPlayExternalTrailer', page).addClass('hide').attr('href', '#');
}
@ -120,9 +120,11 @@
setPeopleHeader(page, item);
if (ApiClient.isWebSocketOpen()) {
ApiClient.sendWebSocketMessage("Context", [item.Type, item.Id, item.Name, context].join('|'));
}
$(page).trigger('displayingitem', [{
item: item,
context: context
}]);
Dashboard.hideLoadingMsg();
});

View file

@ -93,9 +93,10 @@
Dashboard.setPageTitle(name);
if (ApiClient.isWebSocketOpen()) {
ApiClient.sendWebSocketMessage("Context", [item.Type, item.Id, item.Name].join('|'));
}
$(page).trigger('displayingitem', [{
item: item
}]);
});
@ -203,7 +204,7 @@
}).on('pageshow', "#itemListPage", function () {
var page = this;
query.Limit = LibraryBrowser.getDefaultPageSize();
query.ParentId = getParameterByName('parentId');
query.Filters = "";

View file

@ -672,7 +672,7 @@
html += '<a data-itemid="' + item.Id + '" class="' + cssClass + '" data-mediasourcecount="' + mediaSourceCount + '" href="' + href + '">';
var style = "";
options.lazy = false;
if (imgUrl && !options.lazy) {
style += 'background-image:url(\'' + imgUrl + '\');';
}

View file

@ -135,14 +135,11 @@
$('.userDataIcons', page).html(LibraryBrowser.getUserDataIconsHtml(item));
if (ApiClient.isWebSocketOpen()) {
$(page).trigger('displayingitem', [{
var vals = [item.Type, item.Id, item.Name];
vals.push('livetv');
ApiClient.sendWebSocketMessage("Context", vals.join('|'));
}
item: item,
context: 'livetv'
}]);
Dashboard.getCurrentUser().done(function (user) {

View file

@ -50,14 +50,11 @@
LiveTvHelpers.renderMiscProgramInfo($('.miscTvProgramInfo', page), item);
if (ApiClient.isWebSocketOpen()) {
$(page).trigger('displayingitem', [{
var vals = [item.Type, item.Id, item.Name];
vals.push('livetv');
ApiClient.sendWebSocketMessage("Context", vals.join('|'));
}
item: item,
context: 'livetv'
}]);
if (item.TimerId) {
$('#cancelRecordingButtonContainer', page).show();

View file

@ -55,14 +55,11 @@
LiveTvHelpers.renderMiscProgramInfo($('.miscTvProgramInfo', page), item);
if (ApiClient.isWebSocketOpen()) {
$(page).trigger('displayingitem', [{
var vals = [item.Type, item.Id, item.Name];
vals.push('livetv');
ApiClient.sendWebSocketMessage("Context", vals.join('|'));
}
item: item,
context: 'livetv'
}]);
$('.recordingStatus', page).html('Status:&nbsp;&nbsp;&nbsp;' + item.Status);

View file

@ -1,11 +1,26 @@
(function ($, window) {
var enableMirrorMode;
var currentDisplayInfo;
function mirrorItem(info) {
var item = info.item;
MediaController.getCurrentPlayer().displayContent({
itemName: item.Name,
itemId: item.Id,
itemType: item.Type,
context: info.context
});
}
function mediaController() {
var self = this;
var currentPlayer;
var currentTargetInfo;
var players = [];
self.registerPlayer = function (player) {
@ -308,11 +323,11 @@
else if (cmd.Name === 'ToggleMute') {
localPlayer.toggleMute();
}
else if (msg.Data.Command === 'Fullscreen') {
else if (cmd.Name === 'Fullscreen') {
localPlayer.remoteFullscreen();
}
else if (msg.Data.Command === 'SetVolume') {
localPlayer.setVolume(cmd.Arguments.Volume);
else if (cmd.Name === 'SetVolume') {
localPlayer.setVolume(parseFloat(cmd.Arguments.Volume));
}
}
}
@ -324,7 +339,9 @@
var playerInfo = MediaController.getPlayerInfo();
var html = '';
html += '<h3>Select Player:</h3>';
html += '<form>';
html += '<form><h3>Select Player:</h3>';
html += '<fieldset data-role="controlgroup" data-mini="true">';
for (var i = 0, length = targets.length; i < length; i++) {
@ -336,7 +353,9 @@
var isChecked = target.id == playerInfo.id;
var checkedHtml = isChecked ? ' checked="checked"' : '';
html += '<input type="radio" class="radioSelectPlayerTarget" name="radioSelectPlayerTarget" data-mediatypes="' + target.playableMediaTypes.join(',') + '" data-playername="' + target.playerName + '" data-targetid="' + target.id + '" data-targetname="' + target.name + '" id="' + id + '" value="' + target.id + '"' + checkedHtml + '>';
var mirror = (!target.isLocalPlayer && target.supportedCommands.indexOf('DisplayContent') != -1) ? 'true' : 'false';
html += '<input type="radio" class="radioSelectPlayerTarget" name="radioSelectPlayerTarget" data-mirror="' + mirror + '" data-mediatypes="' + target.playableMediaTypes.join(',') + '" data-playername="' + target.playerName + '" data-targetid="' + target.id + '" data-targetname="' + target.name + '" id="' + id + '" value="' + target.id + '"' + checkedHtml + '>';
html += '<label for="' + id + '" style="font-weight:normal;">' + target.name;
if (target.appName) {
@ -350,6 +369,11 @@
html += '<p class="fieldDescription">All plays will be sent to the selected player.</p>';
var checkedHtml = enableMirrorMode ? ' checked="checked"' : '';
html += '<div style="margin-top:1.5em;" class="fldMirrorMode"><label for="chkEnableMirrorMode">Enable Mirror Mode</label><input type="checkbox" class="chkEnableMirrorMode" id="chkEnableMirrorMode" data-mini="true"' + checkedHtml + ' /></div>';
html += '</form>';
return html;
}
@ -374,8 +398,36 @@
$('.players', elem).html(getTargetsHtml(targets)).trigger('create');
$('.chkEnableMirrorMode', elem).on().on('change', function () {
enableMirrorMode = this.checked;
if (this.checked && currentDisplayInfo) {
mirrorItem(currentDisplayInfo);
}
});
$('.radioSelectPlayerTarget', elem).on('change', function () {
var supportsMirror = this.getAttribute('data-mirror') == 'true';
if (supportsMirror) {
$('.fldMirrorMode', elem).show();
} else {
$('.fldMirrorMode', elem).hide();
$('.chkEnableMirrorMode', elem).checked(false).trigger('change').checkboxradio('refresh');
}
}).each(function () {
if (this.checked) {
$(this).trigger('change');
}
}).on('change', function () {
var playerName = this.getAttribute('data-playername');
var targetId = this.getAttribute('data-targetid');
var targetName = this.getAttribute('data-targetname');
@ -401,4 +453,21 @@
});
});
$(document).on('pagebeforeshow', ".page", function () {
var page = this;
currentDisplayInfo = null;
}).on('displayingitem', ".libraryPage", function (e, info) {
var page = this;
currentDisplayInfo = info;
if (enableMirrorMode) {
mirrorItem(info);
}
});
})(jQuery, window);

View file

@ -28,7 +28,8 @@
id: ApiClient.deviceId(),
playerName: self.name,
playableMediaTypes: ['Audio', 'Video'],
isLocalPlayer: true
isLocalPlayer: true,
supportedCommands: Dashboard.getSupportedRemoteCommands()
}];
return targets;
@ -521,19 +522,60 @@
url = "css/images/items/detail/video.png";
}
var name = state.itemName;
var nowPlayingTextElement = $('.nowPlayingText', mediaControls);
var nameHtml = self.getNowPlayingNameHtml(state);
if (state.itemSubName) {
name += '<br/>' + state.itemSubName;
if (nameHtml.indexOf('<br/>') != -1) {
nowPlayingTextElement.addClass('nowPlayingDoubleText');
} else {
nowPlayingTextElement.removeClass('nowPlayingDoubleText');
}
$('.nowPlayingImage', mediaControls).html('<img src="' + url + '" />');
nowPlayingTextElement.html(name);
nowPlayingTextElement.html(nameHtml);
};
self.getNowPlayingNameHtml = function (playerState) {
var topText = playerState.itemName;
if (playerState.mediaType == 'Video') {
if (playerState.indexNumber != null) {
topText = playerState.indexNumber + " - " + topText;
}
if (playerState.parentIndexNumber != null) {
topText = playerState.parentIndexNumber + "." + topText;
}
}
var bottomText = '';
if (playerState.artists && playerState.artists.length) {
bottomText = topText;
topText = playerState.artists[0];
}
else if (playerState.seriesName || playerState.album) {
bottomText = topText;
topText = playerState.seriesName || playerState.album;
}
else if (playerState.productionYear) {
bottomText = playerState.productionYear;
}
return bottomText ? topText + '<br/>' + bottomText : topText;
};
self.displayContent = function (options) {
// Handle it the same as a remote control command
Dashboard.onBrowseCommand({
ItemName: options.itemName,
ItemType: options.itemType,
ItemId: options.itemId,
Context: options.context
});
};
self.getItemsForPlayback = function (query) {
@ -894,7 +936,7 @@
return currentMediaElement;
};
self.getPlayerState = function() {
self.getPlayerState = function () {
var deferred = $.Deferred();
@ -930,41 +972,15 @@
state.itemId = item.Id;
state.mediaType = item.MediaType;
state.itemType = item.Type;
var itemName = '';
var itemSubName = '';
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) {
seriesName = item.SeriesName || item.Album;
}
if (seriesName) {
itemName = seriesName;
itemSubName = name;
} else {
itemName = name;
}
if (!itemSubName && item.ProductionYear) {
itemSubName = item.ProductionYear;
}
state.indexNumber = item.IndexNumber;
state.indexNumberEnd = item.IndexNumberEnd;
state.parentIndexNumber = item.ParentIndexNumber;
state.productionYear = item.ProductionYear;
state.premiereDate = item.PremiereDate;
state.seriesName = item.SeriesName;
state.album = item.Album;
state.itemName = item.Name;
state.artists = item.Artists;
var imageTags = item.ImageTags || {};
@ -973,6 +989,16 @@
state.primaryImageItemId = item.Id;
state.primaryImageTag = imageTags.Primary;
}
else if (item.AlbumPrimaryImageTag) {
state.primaryImageItemId = item.AlbumId;
state.primaryImageTag = item.AlbumPrimaryImageTag;
}
else if (item.SeriesPrimaryImageTag) {
state.primaryImageItemId = item.SeriesId;
state.primaryImageTag = item.SeriesPrimaryImageTag;
}
if (item.BackdropImageTags && item.BackdropImageTags.length) {
@ -985,9 +1011,6 @@
state.thumbItemId = item.Id;
state.thumbImageTag = imageTags.Thumb;
}
state.itemName = itemName;
state.itemSubName = itemSubName;
}
return state;
@ -1123,6 +1146,7 @@
return $('.mediaPlayerAudio');
}
var supportsAac = document.createElement('audio').canPlayType('audio/aac').replace(/no/, '');
function playAudio(item, mediaSource, startPositionTicks) {
startPositionTicks = startPositionTicks || 0;
@ -1134,29 +1158,35 @@
mediaSourceId: mediaSource.Id
};
var mp3Url = ApiClient.getUrl('Audio/' + item.Id + '/stream.mp3', $.extend({}, baseParams, {
audioCodec: 'mp3'
var sourceContainer = (mediaSource.Container || '').toLowerCase();
var isStatic = false;
if (sourceContainer == 'mp3' ||
(sourceContainer == 'aac' && supportsAac)) {
for (var i = 0, length = mediaSource.MediaStreams.length; i < length; i++) {
var stream = mediaSource.MediaStreams[i];
if (stream.Type == "Audio") {
// Stream statically when possible
if (stream.BitRate <= 256000) {
isStatic = true;
}
break;
}
}
}
var outputContainer = isStatic ? sourceContainer : 'mp3';
var audioUrl = ApiClient.getUrl('Audio/' + item.Id + '/stream.' + outputContainer, $.extend({}, baseParams, {
audioCodec: outputContainer
}));
var mediaStreams = mediaSource.MediaStreams;
var isStatic = false;
var seekParam = startPositionTicks ? '#t=' + (startPositionTicks / 10000000) : '';
for (var i = 0, length = mediaStreams.length; i < length; i++) {
var stream = mediaStreams[i];
if (stream.Type == "Audio") {
var container = (mediaSource.Container || '').toLowerCase();
// Stream statically when possible
if (container == 'mp3' && stream.BitRate <= 256000) {
mp3Url += "&static=true" + seekParam;
isStatic = true;
}
break;
}
if (isStatic) {
var seekParam = startPositionTicks ? '#t=' + (startPositionTicks / 10000000) : '';
audioUrl += "&static=true" + seekParam;
}
self.startTimeTicksOffset = isStatic ? 0 : startPositionTicks;
@ -1165,7 +1195,7 @@
return getAudioElement().each(function () {
this.src = mp3Url;
this.src = audioUrl;
this.volume = initialVolume;
this.play();

View file

@ -222,18 +222,18 @@
updateNowPlayingInfo(state);
}
var currentImgUrl;
function updateNowPlayingInfo(state) {
var name = state.itemName;
var nameHtml = MediaPlayer.getNowPlayingNameHtml(state);
if (state.itemSubName) {
name += '<br/>' + state.itemSubName;
if (nameHtml.indexOf('<br/>') != -1) {
nowPlayingTextElement.addClass('nowPlayingDoubleText');
} else {
nowPlayingTextElement.removeClass('nowPlayingDoubleText');
}
nowPlayingTextElement.html(name);
nowPlayingTextElement.html(nameHtml);
var url;
@ -273,6 +273,12 @@
url = "css/images/items/detail/video.png";
}
if (url == currentImgUrl) {
return;
}
currentImgUrl = url;
nowPlayingImageElement.html('<img src="' + url + '" />');
}

View file

@ -529,6 +529,18 @@
});
};
self.displayContent = function (options) {
sendCommand('DisplayContent', {
ItemName: options.itemName,
ItemType: options.itemType,
ItemId: options.itemId,
Context: options.context
});
};
self.getPlayerState = function () {
var deferred = $.Deferred();
@ -615,7 +627,8 @@
playerName: self.name,
appName: s.Client,
playableMediaTypes: s.PlayableMediaTypes,
isLocalPlayer: false
isLocalPlayer: false,
supportedCommands: s.SupportedCommands
};
});
@ -648,13 +661,17 @@
if (item) {
state.itemId = item.Id;
state.itemType = item.Type;
state.mediaType = item.MediaType;
state.runtimeTicks = item.RunTimeTicks;
state.mediaSource = item.MediaSourceId;
state.positionTicks = session.NowPlayingPositionTicks || 0;
state.itemType = item.Type;
state.indexNumber = item.IndexNumber;
state.indexNumberEnd = item.IndexNumberEnd;
state.parentIndexNumber = item.ParentIndexNumber;
state.productionYear = item.ProductionYear;
state.premiereDate = item.PremiereDate;
state.seriesName = item.SeriesName;
state.album = item.Album;
state.itemName = item.Name;
state.artists = item.Artists;
state.primaryImageItemId = item.PrimaryImageItemId;
state.primaryImageTag = item.PrimaryImageTag;
@ -664,6 +681,10 @@
state.thumbItemId = item.ThumbItemId;
state.thumbImageTag = item.ThumbImageTag;
state.mediaSource = item.MediaSourceId;
state.positionTicks = session.NowPlayingPositionTicks || 0;
state.runtimeTicks = item.RunTimeTicks;
}
return state;

View file

@ -263,6 +263,8 @@ var Dashboard = {
var html = '<span style="margin-right: 1em;">Please refresh this page to receive new updates from the server.</span>';
html += '<button type="button" data-icon="refresh" onclick="$(this).buttonEnabled(false);Dashboard.reloadPage();" data-theme="b" data-inline="true" data-mini="true">Refresh</button>';
Dashboard.showFooterNotification({ id: "dashboardVersionWarning", html: html, forceShow: true, allowHide: false });
},
@ -801,6 +803,16 @@ var Dashboard = {
ApiClient.openWebSocket(webSocketUrl);
},
onWebSocketOpened: function () {
ApiClient.reportCapabilities({
PlayableMediaTypes: "Audio,Video",
SupportedCommands: Dashboard.getSupportedRemoteCommands().join(',')
});
},
onWebSocketMessageReceived: function (e, data) {
var msg = data;
@ -878,10 +890,6 @@ var Dashboard = {
}
});
}
else if (msg.MessageType === "Browse") {
Dashboard.onBrowseCommand(msg.Data);
}
else if (msg.MessageType === "GeneralCommand") {
var cmd = msg.Data;
@ -892,6 +900,9 @@ var Dashboard = {
else if (cmd.Name === 'GoToSettings') {
Dashboard.navigate('dashboard.html');
}
else if (cmd.Name === 'DisplayContent') {
Dashboard.onBrowseCommand(cmd.Arguments);
}
}
else if (msg.MessageType === "MessageCommand") {
@ -1237,6 +1248,27 @@ var Dashboard = {
}
$(select).html(html).selectmenu("refresh");
},
getSupportedRemoteCommands: function () {
// Full list
// https://github.com/MediaBrowser/MediaBrowser/blob/master/MediaBrowser.Model/Session/GeneralCommand.cs
return [
"GoHome",
"GoToSettings",
"VolumeUp",
"VolumeDown",
"Mute",
"Unmute",
"ToggleMute",
"SetVolume",
"ToggleFullscreen",
"SetAudioStreamIndex",
"SetSubtitleStreamIndex",
"DisplayContent"
];
}
};
@ -1252,7 +1284,7 @@ else if (!IsStorageEnabled()) {
var ApiClient = MediaBrowser.ApiClient.create("Dashboard", window.dashboardVersion);
$(ApiClient).on("websocketmessage", Dashboard.onWebSocketMessageReceived);
$(ApiClient).on("websocketopen", Dashboard.onWebSocketOpened).on("websocketmessage", Dashboard.onWebSocketMessageReceived);
$(function () {
@ -1327,7 +1359,7 @@ $(function () {
mediaPlayerElem.trigger('create');
var footerHtml = '<div id="footer" data-theme="b" class="ui-bar-b">';
footerHtml += '<div id="footerNotifications"></div>';
footerHtml += '</div>';
@ -1335,7 +1367,7 @@ $(function () {
var footerElem = $('#footer', document.body);
footerElem.trigger('create');
$(window).on("beforeunload", function () {
// Close the connection gracefully when possible

View file

@ -1,29 +1,11 @@
var SupporterPage = {
(function () {
onPageShow: function () {
SupporterPage.load();
},
$(document).on('pageshow', "#supporterPage", function () {
onPageHide: function () {
var page = this;
$('#paypalReturnUrl', page).val(ApiClient.getUrl("supporterkey.html"));
},
});
load: function() {
Dashboard.showLoadingMsg();
var page = $.mobile.activePage;
ApiClient.getPluginSecurityInfo().done(function (info) {
$('#txtSupporterKey', page).val(info.SupporterKey);
if (info.IsMBSupporter) {
$('.supporterOnly', page).show();
} else {
$('.supporterOnly', page).hide();
}
$('#paypalReturnUrl', page).val(ApiClient.getUrl("supporterkey.html"));
Dashboard.hideLoadingMsg();
});
}
};
$(document).on('pageshow', "#supporterPage", SupporterPage.onPageShow)
.on('pagehide', "#supporterPage", SupporterPage.onPageHide);
})();