diff --git a/dashboard-ui/css/site.css b/dashboard-ui/css/site.css index a318b45544..3121e13caf 100644 --- a/dashboard-ui/css/site.css +++ b/dashboard-ui/css/site.css @@ -857,8 +857,8 @@ progress { display: inline-block; position: relative; margin: 5px; - width: 250px; - height: 140.625px; + width: 275px; + height: 154.6875px; } .sessionNowPlayingContent { diff --git a/dashboard-ui/scripts/dashboardpage.js b/dashboard-ui/scripts/dashboardpage.js index c14716bad9..cd9dbf813c 100644 --- a/dashboard-ui/scripts/dashboardpage.js +++ b/dashboard-ui/scripts/dashboardpage.js @@ -211,7 +211,7 @@ var className = nowPlayingItem ? 'activeSession' : 'notPlayingSession activeSession'; - html += ''; + html += ''; html += '
'; } else { @@ -284,12 +285,12 @@ getNowPlayingName: function (session) { var nowPlayingItem = session.NowPlayingItem; - + if (!nowPlayingItem) { return 'Last seen ' + humane_date(session.LastActivityDate); } - + var topText = nowPlayingItem.Name; if (nowPlayingItem.MediaType == 'Video') { @@ -339,7 +340,7 @@ if (session.UserId && session.UserPrimaryImageTag) { return ApiClient.getUserImageUrl(session.UserId, { - + tag: session.UserPrimaryImageTag, height: 24, type: 'Primary' @@ -368,7 +369,8 @@ if (nowPlayingItem && nowPlayingItem.RunTimeTicks) { - var value = (100 * session.NowPlayingPositionTicks) / nowPlayingItem.RunTimeTicks; + var position = session.PlayState.PositionTicks || 0; + var value = (100 * position) / nowPlayingItem.RunTimeTicks; $('progress', row).show().val(value); } else { diff --git a/dashboard-ui/scripts/mediacontroller.js b/dashboard-ui/scripts/mediacontroller.js index 59e958d626..3047c4d481 100644 --- a/dashboard-ui/scripts/mediacontroller.js +++ b/dashboard-ui/scripts/mediacontroller.js @@ -2,11 +2,11 @@ var enableMirrorMode; var currentDisplayInfo; - + function mirrorItem(info) { var item = info.item; - + MediaController.getCurrentPlayer().displayContent({ itemName: item.Name, @@ -345,6 +345,8 @@ html += '

Select Player:

'; html += '
'; + var checkedHtml; + for (var i = 0, length = targets.length; i < length; i++) { var target = targets[i]; @@ -352,7 +354,7 @@ var id = 'radioPlayerTarget' + i; var isChecked = target.id == playerInfo.id; - var checkedHtml = isChecked ? ' checked="checked"' : ''; + checkedHtml = isChecked ? ' checked="checked"' : ''; var mirror = (!target.isLocalPlayer && target.supportedCommands.indexOf('DisplayContent') != -1) ? 'true' : 'false'; @@ -370,7 +372,7 @@ html += '

All plays will be sent to the selected player.

'; - var checkedHtml = enableMirrorMode ? ' checked="checked"' : ''; + checkedHtml = enableMirrorMode ? ' checked="checked"' : ''; html += '
'; html += ''; @@ -401,7 +403,7 @@ $('.chkEnableMirrorMode', elem).on().on('change', function () { enableMirrorMode = this.checked; - + if (this.checked && currentDisplayInfo) { mirrorItem(currentDisplayInfo); diff --git a/dashboard-ui/scripts/mediaplayer.js b/dashboard-ui/scripts/mediaplayer.js index 6fbbfab0ea..a7503a7047 100644 --- a/dashboard-ui/scripts/mediaplayer.js +++ b/dashboard-ui/scripts/mediaplayer.js @@ -1029,7 +1029,15 @@ self.updateCanClientSeek(playerElement); - ApiClient.reportPlaybackStart(Dashboard.getCurrentUserId(), item.Id, mediaSource.Id, true, item.MediaType); + ApiClient.reportPlaybackStart({ + itemId: item.Id, + QueueableMediaTypes: item.MediaType, + CanSeek: mediaSource.RunTimeTicks != null, + MediaSourceId: mediaSource.Id, + IsPaused: playerElement.paused, + IsMuted: playerElement.volume == 0, + VolumeLevel: playerElement.volume * 100 + }); self.startProgressInterval(item.Id, mediaSource.Id); @@ -1064,7 +1072,13 @@ var item = currentItem; var mediaSource = currentMediaSource; - ApiClient.reportPlaybackStopped(Dashboard.getCurrentUserId(), item.Id, mediaSource.Id, position); + ApiClient.reportPlaybackStopped({ + + itemId: item.Id, + mediaSourceId: mediaSource.Id, + positionTicks: position + + }); if (item.MediaType == "Video") { ApiClient.stopActiveEncodings(); @@ -1105,7 +1119,14 @@ function sendProgressUpdate(itemId, mediaSourceId) { - ApiClient.reportPlaybackProgress(Dashboard.getCurrentUserId(), itemId, mediaSourceId, self.getCurrentTicks(), currentMediaElement.paused, currentMediaElement.volume == 0); + ApiClient.reportPlaybackProgress({ + itemId: itemId, + MediaSourceId: mediaSourceId, + IsPaused: currentMediaElement.paused, + IsMuted: currentMediaElement.volume == 0, + VolumeLevel: currentMediaElement.volume * 100, + PositionTicks: self.getCurrentTicks() + }); } function clearProgressInterval() { diff --git a/dashboard-ui/scripts/remotecontrol.js b/dashboard-ui/scripts/remotecontrol.js index c1abe1ae3a..acaef475b9 100644 --- a/dashboard-ui/scripts/remotecontrol.js +++ b/dashboard-ui/scripts/remotecontrol.js @@ -1,416 +1,5 @@ (function (window, document, $) { - function showMenu(sessions, options) { - - var html = '
'; - - html += 'Close'; - - html += '
'; - html += '
Remote Control
'; - html += '
'; - - html += '
'; - - html += '
'; - - // Add controls here - html += '
'; - html += '
'; - - html += '
'; - - html += '
'; - - html += ''; - - html += ''; - - html += '
'; - - html += ''; - - html += '
'; - - html += '
'; - - $(document.body).append(html); - - var popup = $('.remoteControlFlyout').popup({ history: false, tolerance: 0, corners: false }).trigger('create').popup("open").on("popupafterclose", function () { - - if (ApiClient.isWebSocketOpen()) { - ApiClient.sendWebSocketMessage("SessionsStop"); - } - - $(ApiClient).off("websocketmessage.remotecontrol"); - - $(this).off("popupafterclose").remove(); - - $('.remoteControlFlyout').popup("destroy").remove(); - }); - - renderSessionsInControlMenu(popup, sessions, options); - updateSessionInfo(popup, sessions, options); - - if (ApiClient.isWebSocketOpen()) { - ApiClient.sendWebSocketMessage("SessionsStart", "1000,1000"); - - $(ApiClient).on("websocketmessage.remotecontrol", function (e, msg) { - - if (msg.MessageType === "Sessions") { - - // Update existing data - updateSessionInfo(popup, msg.Data); - } - }); - - } - - $('.btnGoHome', popup).on('click', function () { - - var id = $('#selectSession', popup).val(); - - ApiClient.sendCommand(id, 'GoHome'); - }); - - $('.btnGoToSettings', popup).on('click', function () { - - var id = $('#selectSession', popup).val(); - - ApiClient.sendCommand(id, 'GoToSettings'); - }); - - $('.btnSendMessage', popup).on('click', function () { - - var id = $('#selectSession', popup).val(); - - var messageText = $('#txtMessage', popup).val(); - - if (messageText) { - Dashboard.getCurrentUser().done(function (user) { - - ApiClient.sendMessageCommand(id, { - Header: "Message from " + user.Name, - Text: messageText - }); - }); - } else { - $('#txtMessage', popup)[0].focus(); - } - }); - - $('.btnVolumeDown', popup).on('click', function () { - - var id = $('#selectSession', popup).val(); - - ApiClient.sendCommand(id, 'VolumeDown'); - }); - - $('.btnVolumeUp', popup).on('click', function () { - - var id = $('#selectSession', popup).val(); - - ApiClient.sendCommand(id, 'VolumeUp'); - }); - - $('.btnToggleMute', popup).on('click', function () { - - var id = $('#selectSession', popup).val(); - - ApiClient.sendCommand(id, 'ToggleMute'); - }); - - $('.btnStop', popup).on('click', function () { - - var id = $('#selectSession', popup).val(); - - ApiClient.sendPlayStateCommand(id, 'Stop'); - }); - - $('.btnPause', popup).on('click', function () { - - var id = $('#selectSession', popup).val(); - - ApiClient.sendPlayStateCommand(id, 'Pause'); - }); - - $('.btnPlay', popup).on('click', function () { - - var id = $('#selectSession', popup).val(); - - ApiClient.sendPlayStateCommand(id, 'Unpause'); - }); - - $('.btnNextTrack', popup).on('click', function () { - - var id = $('#selectSession', popup).val(); - - ApiClient.sendPlayStateCommand(id, 'NextTrack'); - }); - - $('.btnPreviousTrack', popup).on('click', function () { - - var id = $('#selectSession', popup).val(); - - ApiClient.sendPlayStateCommand(id, 'PreviousTrack'); - }); - - $("#positionSlider", popup).on("slidestart", function () { - - this.isSliding = true; - - }).on("slidestop", function () { - - var id = $('#selectSession', popup).val(); - - var percent = $(this).val(); - - var duration = parseInt($(this).attr('data-duration')); - - var position = duration * percent / 100; - - ApiClient.sendPlayStateCommand(id, 'Seek', - { - SeekPositionTicks: parseInt(position) - }); - - this.isSliding = false; - }); - - $('.btnFullscreen', popup).on('click', function () { - - var id = $('#selectSession', popup).val(); - - ApiClient.sendPlayStateCommand(id, 'Fullscreen'); - }); - } - - function getPlaybackHtml(session) { - - var html = ''; - - html += '

'; - - html += '

'; - - html += '
'; - - html += '
'; - html += ''; - html += ' / '; - html += ''; - html += '
'; - - html += '
'; - html += '
'; - - html += '
'; - html += ''; - html += ''; - html += ''; - html += ''; - html += ''; - html += ''; - html += ''; - html += ''; - - if (session && session.SupportsFullscreenToggle) { - html += ''; - } - - html += '
'; - - - return html; - } - - function updateSessionInfo(popup, sessions) { - - var id = $('#selectSession', popup).val(); - - // don't display the current session - var session = sessions.filter(function (s) { - return s.Id == id; - })[0]; - - if (!session) { - - $('.nothingPlaying', popup).hide(); - $('.nowPlaying', popup).hide(); - $('.commandsCollapsible', popup).hide(); - - } - else if (session.NowPlayingItem) { - - $('.commandsCollapsible', popup).show(); - $('.nothingPlaying', popup).hide(); - - var elem = $('.nowPlaying', popup).show(); - - updateNowPlaying(elem, session); - - } else { - - $('.commandsCollapsible', popup).show(); - $('.nothingPlaying', popup).show(); - $('.nowPlaying', popup).hide(); - } - } - - function updateNowPlaying(elem, session) { - - var item = session.NowPlayingItem; - - $('.nowPlayingTitle', elem).html(item.Name); - - var imageContainer = $('.nowPlayingImage', elem); - - if (item.PrimaryImageTag) { - imageContainer.show(); - - var img = $('img', imageContainer)[0]; - - var imgUrl = ApiClient.getImageUrl(item.Id, { - maxheight: 300, - type: 'Primary', - tag: item.PrimaryImageTag - }); - - if (!img || img.src.toLowerCase().indexOf(imgUrl.toLowerCase()) == -1) { - imageContainer.html(''); - } - - } else { - imageContainer.hide(); - } - - if (session.CanSeek) { - $('.remotePositionSliderContainer', elem).show(); - } else { - $('.remotePositionSliderContainer', elem).hide(); - } - - var time = session.NowPlayingPositionTicks || 0; - var duration = item.RunTimeTicks || 0; - - var percent = duration ? 100 * time / duration : 0; - - var slider = $('#positionSlider', elem); - - if (!slider[0].isSliding) { - slider.val(percent).slider('refresh'); - } - - slider.attr('data-duration', duration); - - $('.nowPlayingTime', elem).html(Dashboard.getDisplayTime(time)); - $('.duration', elem).html(Dashboard.getDisplayTime(duration)); - - if (session.IsPaused) { - $('.btnPauseParent', elem).hide(); - $('.btnPlayParent', elem).show(); - } else { - $('.btnPauseParent', elem).show(); - $('.btnPlayParent', elem).hide(); - } - } - - function renderSessionsInControlMenu(popup, sessions, options) { - - options = options || {}; - - var deviceId = ApiClient.deviceId(); - - // don't display the current session - sessions = sessions.filter(function (s) { - return s.DeviceId != deviceId && s.SupportsRemoteControl; - }); - - var elem = $('#selectSession', popup); - - var currentValue = options.sessionId || elem.val(); - - if (currentValue) { - - // Make sure the session is still active - var currentSession = sessions.filter(function (s) { - return s.Id == currentValue; - })[0]; - - if (!currentSession) { - currentValue = null; - } - } - - if (!currentValue && sessions.length) { - currentValue = sessions[0].Id; - } - - var html = ''; - - for (var i = 0, length = sessions.length; i < length; i++) { - - var session = sessions[i]; - - var text = session.DeviceName; - - if (session.UserName) { - text += ' - ' + session.UserName; - } - - html += ''; - } - - elem.html(html).val(currentValue).selectmenu('refresh'); - - } - - function remoteControl() { - - var self = this; - - var sessionQuery = { - SupportsRemoteControl: true, - ControllableByUserId: Dashboard.getCurrentUserId() - }; - - self.showMenu = function (options) { - ApiClient.getSessions(sessionQuery).done(function (sessions) { - - showMenu(sessions, options); - - }); - }; - } - - window.RemoteControl = new remoteControl(); - function sendPlayCommand(options, playType) { var sessionId = MediaController.getPlayerInfo().id; @@ -554,7 +143,7 @@ var session = sessions.filter(function (s) { return s.Id == currentTargetId; })[0]; - + if (session) { session = getPlayerState(session); } @@ -649,12 +238,22 @@ function getPlayerState(session) { - var state = { - volumeLevel: session.VolumeLevel, - isMuted: session.IsMuted, - isPaused: session.IsPaused, - canSeek: session.CanSeek - }; + var state = {}; + + var playerState = session.PlayState; + + if (playerState) { + + state.isMuted = playerState.IsMuted; + state.isPaused = playerState.IsPaused; + state.canSeek = playerState.CanSeek; + state.positionTicks = playerState.PositionTicks || 0; + + state.mediaSource = playerState.MediaSourceId; + state.volumeLevel = playerState.VolumeLevel; + state.audioStreamIndex = playerState.AudioStreamIndex; + state.subtitleStreamIndex = playerState.SubtitleStreamIndex; + } var item = session.NowPlayingItem; @@ -682,8 +281,6 @@ state.thumbItemId = item.ThumbItemId; state.thumbImageTag = item.ThumbImageTag; - state.mediaSource = item.MediaSourceId; - state.positionTicks = session.NowPlayingPositionTicks || 0; state.runtimeTicks = item.RunTimeTicks; } diff --git a/dashboard-ui/thirdparty/mediabrowser.apiclient.js b/dashboard-ui/thirdparty/mediabrowser.apiclient.js index e70c2a2830..6e0ba6c829 100644 --- a/dashboard-ui/thirdparty/mediabrowser.apiclient.js +++ b/dashboard-ui/thirdparty/mediabrowser.apiclient.js @@ -3600,48 +3600,30 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi * @param {String} userId * @param {String} itemId */ - self.reportPlaybackStart = function (userId, itemId, mediaSourceId, canSeek, queueableMediaTypes) { + self.reportPlaybackStart = function (options) { - if (!userId) { - throw new Error("null userId"); + if (!options) { + throw new Error("null options"); } - if (!itemId) { - throw new Error("null itemId"); - } - - canSeek = canSeek || false; - queueableMediaTypes = queueableMediaTypes || ''; - if (self.isWebSocketOpen()) { var deferred = $.Deferred(); - var msg = [itemId, canSeek, queueableMediaTypes]; + var msg = JSON.stringify(options); - if (mediaSourceId) { - msg.push(mediaSourceId); - } - - self.sendWebSocketMessage("PlaybackStart", msg.join('|')); + self.sendWebSocketMessage("ReportPlaybackStart", msg); deferred.resolveWith(null, []); return deferred.promise(); } - var params = { - CanSeek: canSeek, - QueueableMediaTypes: queueableMediaTypes - }; - - if (mediaSourceId) { - params.mediaSourceId = mediaSourceId; - } - - var url = self.getUrl("Users/" + userId + "/PlayingItems/" + itemId, params); + var url = self.getUrl("Sessions/Playing"); return self.ajax({ type: "POST", + data: JSON.stringify(options), + contentType: "application/json", url: url }); }; @@ -3651,50 +3633,30 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi * @param {String} userId * @param {String} itemId */ - self.reportPlaybackProgress = function (userId, itemId, mediaSourceId, positionTicks, isPaused, isMuted) { + self.reportPlaybackProgress = function (options) { - if (!userId) { - throw new Error("null userId"); - } - - if (!itemId) { - throw new Error("null itemId"); + if (!options) { + throw new Error("null options"); } if (self.isWebSocketOpen()) { var deferred = $.Deferred(); - var msgData = itemId; + var msg = JSON.stringify(options); - msgData += "|" + (positionTicks == null ? "" : positionTicks); - msgData += "|" + (isPaused == null ? "" : isPaused); - msgData += "|" + (isMuted == null ? "" : isMuted); - msgData += "|" + (mediaSourceId == null ? "" : mediaSourceId); - - self.sendWebSocketMessage("PlaybackProgress", msgData); + self.sendWebSocketMessage("ReportPlaybackProgress", msg); deferred.resolveWith(null, []); return deferred.promise(); } - var params = { - isPaused: isPaused, - isMuted: isMuted - }; - - if (positionTicks) { - params.positionTicks = positionTicks; - } - - if (mediaSourceId) { - params.mediaSourceId = mediaSourceId; - } - - var url = self.getUrl("Users/" + userId + "/PlayingItems/" + itemId + "/Progress", params); + var url = self.getUrl("Sessions/Playing/Progress"); return self.ajax({ type: "POST", + data: JSON.stringify(options), + contentType: "application/json", url: url }); }; @@ -3704,44 +3666,30 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi * @param {String} userId * @param {String} itemId */ - self.reportPlaybackStopped = function (userId, itemId, mediaSourceId, positionTicks) { + self.reportPlaybackStopped = function (options) { - if (!userId) { - throw new Error("null userId"); - } - - if (!itemId) { - throw new Error("null itemId"); + if (!options) { + throw new Error("null options"); } if (self.isWebSocketOpen()) { var deferred = $.Deferred(); - var msg = itemId; - msg += "|" + (positionTicks == null ? "" : positionTicks); - msg += "|" + (mediaSourceId == null ? "" : mediaSourceId); + var msg = JSON.stringify(options); - self.sendWebSocketMessage("PlaybackStopped", msg); + self.sendWebSocketMessage("ReportPlaybackStopped", msg); deferred.resolveWith(null, []); return deferred.promise(); } - var params = {}; - - if (positionTicks) { - params.positionTicks = positionTicks; - } - - if (mediaSourceId) { - params.mediaSourceId = mediaSourceId; - } - - var url = self.getUrl("Users/" + userId + "/PlayingItems/" + itemId, params); + var url = self.getUrl("Sessions/Playing/Stopped"); return self.ajax({ - type: "DELETE", + type: "POST", + data: JSON.stringify(options), + contentType: "application/json", url: url }); };