diff --git a/MediaBrowser.Common/Net/IServerManager.cs b/MediaBrowser.Common/Net/IServerManager.cs
index 32be88a346..6965677bbf 100644
--- a/MediaBrowser.Common/Net/IServerManager.cs
+++ b/MediaBrowser.Common/Net/IServerManager.cs
@@ -62,17 +62,6 @@ namespace MediaBrowser.Common.Net
/// messageType
Task SendWebSocketMessageAsync(string messageType, Func dataFunction, CancellationToken cancellationToken);
- ///
- /// Sends the web socket message async.
- ///
- ///
- /// Type of the message.
- /// The data function.
- /// The connections.
- /// The cancellation token.
- /// Task.
- Task SendWebSocketMessageAsync(string messageType, Func dataFunction, IEnumerable connections, CancellationToken cancellationToken);
-
///
/// Adds the web socket listeners.
///
diff --git a/MediaBrowser.Common/Net/IWebSocketConnection.cs b/MediaBrowser.Common/Net/IWebSocketConnection.cs
index 434b8ff5cd..482da131ee 100644
--- a/MediaBrowser.Common/Net/IWebSocketConnection.cs
+++ b/MediaBrowser.Common/Net/IWebSocketConnection.cs
@@ -7,6 +7,12 @@ namespace MediaBrowser.Common.Net
{
public interface IWebSocketConnection : IDisposable
{
+ ///
+ /// Gets the id.
+ ///
+ /// The id.
+ Guid Id { get; }
+
///
/// Gets the last activity date.
///
diff --git a/MediaBrowser.Controller/Session/ISessionController.cs b/MediaBrowser.Controller/Session/ISessionController.cs
index f37d63b727..597a14cc60 100644
--- a/MediaBrowser.Controller/Session/ISessionController.cs
+++ b/MediaBrowser.Controller/Session/ISessionController.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Model.Session;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Session;
using System.Threading;
using System.Threading.Tasks;
@@ -7,55 +8,70 @@ namespace MediaBrowser.Controller.Session
public interface ISessionController
{
///
- /// Supportses the specified session.
+ /// Gets a value indicating whether [supports media remote control].
///
- /// The session.
- /// true if XXXX, false otherwise
- bool Supports(SessionInfo session);
+ /// true if [supports media remote control]; otherwise, false.
+ bool SupportsMediaRemoteControl { get; }
+
+ ///
+ /// Gets a value indicating whether this instance is session active.
+ ///
+ /// true if this instance is session active; otherwise, false.
+ bool IsSessionActive { get; }
///
/// Sends the system command.
///
- /// The session.
/// The command.
/// The cancellation token.
/// Task.
- Task SendSystemCommand(SessionInfo session, SystemCommand command, CancellationToken cancellationToken);
+ Task SendSystemCommand(SystemCommand command, CancellationToken cancellationToken);
///
/// Sends the message command.
///
- /// The session.
/// The command.
/// The cancellation token.
/// Task.
- Task SendMessageCommand(SessionInfo session, MessageCommand command, CancellationToken cancellationToken);
+ Task SendMessageCommand(MessageCommand command, CancellationToken cancellationToken);
///
/// Sends the play command.
///
- /// The session.
/// The command.
/// The cancellation token.
/// Task.
- Task SendPlayCommand(SessionInfo session, PlayRequest command, CancellationToken cancellationToken);
+ Task SendPlayCommand(PlayRequest command, CancellationToken cancellationToken);
///
/// Sends the browse command.
///
- /// The session.
/// The command.
/// The cancellation token.
/// Task.
- Task SendBrowseCommand(SessionInfo session, BrowseRequest command, CancellationToken cancellationToken);
+ Task SendBrowseCommand(BrowseRequest command, CancellationToken cancellationToken);
///
/// Sends the playstate command.
///
- /// The session.
/// The command.
/// The cancellation token.
/// Task.
- Task SendPlaystateCommand(SessionInfo session, PlaystateRequest command, CancellationToken cancellationToken);
+ Task SendPlaystateCommand(PlaystateRequest command, CancellationToken cancellationToken);
+
+ ///
+ /// Sends the library update info.
+ ///
+ /// The info.
+ /// The cancellation token.
+ /// Task.
+ Task SendLibraryUpdateInfo(LibraryUpdateInfo info, CancellationToken cancellationToken);
+
+ ///
+ /// Sends the restart required message.
+ ///
+ /// The cancellation token.
+ /// Task.
+ Task SendRestartRequiredMessage(CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs
index 6ee57eb466..b2d111e546 100644
--- a/MediaBrowser.Controller/Session/ISessionManager.cs
+++ b/MediaBrowser.Controller/Session/ISessionManager.cs
@@ -13,12 +13,6 @@ namespace MediaBrowser.Controller.Session
///
public interface ISessionManager
{
- ///
- /// Adds the parts.
- ///
- /// The remote controllers.
- void AddParts(IEnumerable remoteControllers);
-
///
/// Occurs when [playback start].
///
@@ -119,5 +113,12 @@ namespace MediaBrowser.Controller.Session
/// The cancellation token.
/// Task.
Task SendPlaystateCommand(Guid sessionId, PlaystateRequest command, CancellationToken cancellationToken);
+
+ ///
+ /// Sends the restart required message.
+ ///
+ /// The cancellation token.
+ /// Task.
+ Task SendRestartRequiredMessage(CancellationToken cancellationToken);
}
}
\ No newline at end of file
diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs
index d50f19c1f0..ed2fcda678 100644
--- a/MediaBrowser.Controller/Session/SessionInfo.cs
+++ b/MediaBrowser.Controller/Session/SessionInfo.cs
@@ -1,9 +1,6 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Model.Net;
+using MediaBrowser.Controller.Entities;
using System;
using System.Collections.Generic;
-using System.Linq;
namespace MediaBrowser.Controller.Session
{
@@ -14,7 +11,6 @@ namespace MediaBrowser.Controller.Session
{
public SessionInfo()
{
- WebSockets = new List();
QueueableMediaTypes = new List();
}
@@ -114,18 +110,18 @@ namespace MediaBrowser.Controller.Session
/// The device id.
public string DeviceId { get; set; }
- ///
- /// Gets or sets the web socket.
- ///
- /// The web socket.
- public List WebSockets { get; set; }
-
///
/// Gets or sets the application version.
///
/// The application version.
public string ApplicationVersion { get; set; }
+ ///
+ /// Gets or sets the session controller.
+ ///
+ /// The session controller.
+ public ISessionController SessionController { get; set; }
+
///
/// Gets a value indicating whether this instance is active.
///
@@ -134,9 +130,9 @@ namespace MediaBrowser.Controller.Session
{
get
{
- if (WebSockets.Count > 0)
+ if (SessionController != null)
{
- return WebSockets.Any(i => i.State == WebSocketState.Open);
+ return SessionController.IsSessionActive;
}
return (DateTime.UtcNow - LastActivityDate).TotalMinutes <= 10;
@@ -151,7 +147,12 @@ namespace MediaBrowser.Controller.Session
{
get
{
- return WebSockets.Any(i => i.State == WebSocketState.Open);
+ if (SessionController != null)
+ {
+ return SessionController.SupportsMediaRemoteControl;
+ }
+
+ return false;
}
}
}
diff --git a/MediaBrowser.Model/Querying/ItemQuery.cs b/MediaBrowser.Model/Querying/ItemQuery.cs
index 69c79104a4..20eac55e81 100644
--- a/MediaBrowser.Model/Querying/ItemQuery.cs
+++ b/MediaBrowser.Model/Querying/ItemQuery.cs
@@ -206,6 +206,24 @@ namespace MediaBrowser.Model.Querying
/// The parent index number.
public int? ParentIndexNumber { get; set; }
+ ///
+ /// Gets or sets the min players.
+ ///
+ /// The min players.
+ public int? MinPlayers { get; set; }
+
+ ///
+ /// Gets or sets the name starts with or greater.
+ ///
+ /// The name starts with or greater.
+ public string NameStartsWithOrGreater { get; set; }
+
+ ///
+ /// Gets or sets the album artist starts with or greater.
+ ///
+ /// The album artist starts with or greater.
+ public string AlbumArtistStartsWithOrGreater { get; set; }
+
///
/// Initializes a new instance of the class.
///
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs
index 1306017ca1..7a3081ab5d 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs
@@ -1,5 +1,4 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session;
@@ -21,7 +20,6 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
private readonly ILibraryManager _libraryManager;
private readonly ISessionManager _sessionManager;
- private readonly IServerManager _serverManager;
private readonly IUserManager _userManager;
private readonly ILogger _logger;
@@ -48,11 +46,10 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
///
private const int LibraryUpdateDuration = 20000;
- public LibraryChangedNotifier(ILibraryManager libraryManager, ISessionManager sessionManager, IServerManager serverManager, IUserManager userManager, ILogger logger)
+ public LibraryChangedNotifier(ILibraryManager libraryManager, ISessionManager sessionManager, IUserManager userManager, ILogger logger)
{
_libraryManager = libraryManager;
_sessionManager = sessionManager;
- _serverManager = serverManager;
_userManager = userManager;
_logger = logger;
}
@@ -187,31 +184,33 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
/// The folders added to.
/// The folders removed from.
/// The cancellation token.
- private async void SendChangeNotifications(IEnumerable itemsAdded, IEnumerable itemsUpdated, IEnumerable itemsRemoved, IEnumerable foldersAddedTo, IEnumerable foldersRemovedFrom, CancellationToken cancellationToken)
+ private async void SendChangeNotifications(List itemsAdded, List itemsUpdated, List itemsRemoved, List foldersAddedTo, List foldersRemovedFrom, CancellationToken cancellationToken)
{
- var currentSessions = _sessionManager.Sessions.ToList();
-
- var users = currentSessions.Select(i => i.User)
- .Where(i => i != null)
- .Select(i => i.Id)
- .Distinct()
- .ToList();
-
- foreach (var userId in users)
+ foreach (var user in _userManager.Users.ToList())
{
- var id = userId;
- var webSockets = currentSessions.Where(u => u.User != null && u.User.Id == id)
- .SelectMany(i => i.WebSockets)
+ var id = user.Id;
+ var userSessions = _sessionManager.Sessions
+ .Where(u => u.User != null && u.User.Id == id && u.SessionController != null && u.IsActive)
.ToList();
- try
+ if (userSessions.Count > 0)
{
- await _serverManager.SendWebSocketMessageAsync("LibraryChanged", () => GetLibraryUpdateInfo(itemsAdded, itemsUpdated, itemsRemoved, foldersAddedTo, foldersRemovedFrom, id), webSockets, cancellationToken).ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error sending LibraryChanged message", ex);
+ var info = GetLibraryUpdateInfo(itemsAdded, itemsUpdated, itemsRemoved, foldersAddedTo,
+ foldersRemovedFrom, id);
+
+ foreach (var userSession in userSessions)
+ {
+ try
+ {
+ await userSession.SessionController.SendLibraryUpdateInfo(info, cancellationToken).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error sending LibraryChanged message", ex);
+ }
+ }
}
+
}
}
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/WebSocketEvents.cs b/MediaBrowser.Server.Implementations/EntryPoints/WebSocketEvents.cs
index 29372a40af..4349b6976a 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/WebSocketEvents.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/WebSocketEvents.cs
@@ -8,8 +8,10 @@ using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Plugins;
+using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Tasks;
using System;
+using System.Threading;
namespace MediaBrowser.Server.Implementations.EntryPoints
{
@@ -45,13 +47,15 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
private readonly IDtoService _dtoService;
+ private ISessionManager _sessionManager;
+
///
/// Initializes a new instance of the class.
///
/// The server manager.
/// The logger.
/// The user manager.
- public WebSocketEvents(IServerManager serverManager, IServerApplicationHost appHost, IUserManager userManager, IInstallationManager installationManager, ITaskManager taskManager, IDtoService dtoService)
+ public WebSocketEvents(IServerManager serverManager, IServerApplicationHost appHost, IUserManager userManager, IInstallationManager installationManager, ITaskManager taskManager, IDtoService dtoService, ISessionManager sessionManager)
{
_serverManager = serverManager;
_userManager = userManager;
@@ -59,6 +63,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
_appHost = appHost;
_taskManager = taskManager;
_dtoService = dtoService;
+ _sessionManager = sessionManager;
}
public void Run()
@@ -126,7 +131,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
/// The instance containing the event data.
void kernel_HasPendingRestartChanged(object sender, EventArgs e)
{
- _serverManager.SendWebSocketMessage("RestartRequired", _appHost.GetSystemInfo());
+ _sessionManager.SendRestartRequiredMessage(CancellationToken.None);
}
///
diff --git a/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs b/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs
index a840ae214a..638e6fa0de 100644
--- a/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs
+++ b/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs
@@ -273,7 +273,7 @@ namespace MediaBrowser.Server.Implementations.ServerManager
/// dataFunction
/// or
/// cancellationToken
- public async Task SendWebSocketMessageAsync(string messageType, Func dataFunction, IEnumerable connections, CancellationToken cancellationToken)
+ private async Task SendWebSocketMessageAsync(string messageType, Func dataFunction, IEnumerable connections, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(messageType))
{
diff --git a/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs b/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs
index 4bab10ee09..61c06ba6de 100644
--- a/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs
+++ b/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs
@@ -56,6 +56,12 @@ namespace MediaBrowser.Server.Implementations.ServerManager
/// The last activity date.
public DateTime LastActivityDate { get; private set; }
+ ///
+ /// Gets the id.
+ ///
+ /// The id.
+ public Guid Id { get; private set; }
+
///
/// Initializes a new instance of the class.
///
@@ -83,6 +89,7 @@ namespace MediaBrowser.Server.Implementations.ServerManager
throw new ArgumentNullException("logger");
}
+ Id = Guid.NewGuid();
_jsonSerializer = jsonSerializer;
_socket = socket;
_socket.OnReceiveBytes = OnReceiveInternal;
diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
index efb8dbe10e..ac69b0dc53 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
@@ -78,12 +78,6 @@ namespace MediaBrowser.Server.Implementations.Session
_userRepository = userRepository;
}
- private List _remoteControllers;
- public void AddParts(IEnumerable remoteControllers)
- {
- _remoteControllers = remoteControllers.ToList();
- }
-
///
/// Gets all connections.
///
@@ -433,18 +427,8 @@ namespace MediaBrowser.Server.Implementations.Session
{
throw new ArgumentException(string.Format("Session {0} does not support remote control.", session.Id));
}
-
- return session;
- }
- ///
- /// Gets the controllers.
- ///
- /// The session.
- /// IEnumerable{ISessionRemoteController}.
- private IEnumerable GetControllers(SessionInfo session)
- {
- return _remoteControllers.Where(i => i.Supports(session));
+ return session;
}
///
@@ -458,9 +442,7 @@ namespace MediaBrowser.Server.Implementations.Session
{
var session = GetSessionForRemoteControl(sessionId);
- var tasks = GetControllers(session).Select(i => i.SendSystemCommand(session, command, cancellationToken));
-
- return Task.WhenAll(tasks);
+ return session.SessionController.SendSystemCommand(command, cancellationToken);
}
///
@@ -474,9 +456,7 @@ namespace MediaBrowser.Server.Implementations.Session
{
var session = GetSessionForRemoteControl(sessionId);
- var tasks = GetControllers(session).Select(i => i.SendMessageCommand(session, command, cancellationToken));
-
- return Task.WhenAll(tasks);
+ return session.SessionController.SendMessageCommand(command, cancellationToken);
}
///
@@ -490,9 +470,7 @@ namespace MediaBrowser.Server.Implementations.Session
{
var session = GetSessionForRemoteControl(sessionId);
- var tasks = GetControllers(session).Select(i => i.SendPlayCommand(session, command, cancellationToken));
-
- return Task.WhenAll(tasks);
+ return session.SessionController.SendPlayCommand(command, cancellationToken);
}
///
@@ -506,9 +484,7 @@ namespace MediaBrowser.Server.Implementations.Session
{
var session = GetSessionForRemoteControl(sessionId);
- var tasks = GetControllers(session).Select(i => i.SendBrowseCommand(session, command, cancellationToken));
-
- return Task.WhenAll(tasks);
+ return session.SessionController.SendBrowseCommand(command, cancellationToken);
}
///
@@ -522,7 +498,25 @@ namespace MediaBrowser.Server.Implementations.Session
{
var session = GetSessionForRemoteControl(sessionId);
- var tasks = GetControllers(session).Select(i => i.SendPlaystateCommand(session, command, cancellationToken));
+ return session.SessionController.SendPlaystateCommand(command, cancellationToken);
+ }
+
+ public Task SendRestartRequiredMessage(CancellationToken cancellationToken)
+ {
+ var sessions = Sessions.Where(i => i.IsActive && i.SessionController != null).ToList();
+
+ var tasks = sessions.Select(session => Task.Run(async () =>
+ {
+ try
+ {
+ await session.SessionController.SendRestartRequiredMessage(cancellationToken).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error in SendRestartRequiredMessage.", ex);
+ }
+
+ }));
return Task.WhenAll(tasks);
}
diff --git a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
index 0781e82286..e90dd8eb95 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
@@ -1,8 +1,8 @@
using MediaBrowser.Common.Net;
+using MediaBrowser.Controller;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Net;
using System;
using System.Linq;
using System.Threading.Tasks;
@@ -33,6 +33,7 @@ namespace MediaBrowser.Server.Implementations.Session
/// The _dto service
///
private readonly IDtoService _dtoService;
+ private readonly IServerApplicationHost _appHost;
///
/// Initializes a new instance of the class.
@@ -40,11 +41,12 @@ namespace MediaBrowser.Server.Implementations.Session
/// The session manager.
/// The log manager.
/// The dto service.
- public SessionWebSocketListener(ISessionManager sessionManager, ILogManager logManager, IDtoService dtoService)
+ public SessionWebSocketListener(ISessionManager sessionManager, ILogManager logManager, IDtoService dtoService, IServerApplicationHost appHost)
{
_sessionManager = sessionManager;
_logger = logManager.GetLogger(GetType().Name);
_dtoService = dtoService;
+ _appHost = appHost;
}
///
@@ -56,48 +58,11 @@ namespace MediaBrowser.Server.Implementations.Session
{
if (string.Equals(message.MessageType, "Identity", StringComparison.OrdinalIgnoreCase))
{
- _logger.Debug("Received Identity message");
-
- var vals = message.Data.Split('|');
-
- var client = vals[0];
- var deviceId = vals[1];
- var version = vals[2];
-
- var session = _sessionManager.Sessions
- .FirstOrDefault(i => string.Equals(i.DeviceId, deviceId) &&
- string.Equals(i.Client, client) &&
- string.Equals(i.ApplicationVersion, version));
-
- if (session != null)
- {
- var sockets = session.WebSockets.Where(i => i.State == WebSocketState.Open).ToList();
- sockets.Add(message.Connection);
-
- session.WebSockets = sockets;
- }
- else
- {
- _logger.Warn("Unable to determine session based on identity message: {0}", message.Data);
- }
+ ProcessIdentityMessage(message);
}
else if (string.Equals(message.MessageType, "Context", StringComparison.OrdinalIgnoreCase))
{
- var session = _sessionManager.Sessions.FirstOrDefault(i => i.WebSockets.Contains(message.Connection));
-
- if (session != null)
- {
- var vals = message.Data.Split('|');
-
- session.NowViewingItemType = vals[0];
- session.NowViewingItemId = vals[1];
- session.NowViewingItemName = vals[2];
- session.NowViewingContext = vals.Length > 3 ? vals[3] : null;
- }
- else
- {
- _logger.Warn("Unable to determine session based on context message: {0}", message.Data);
- }
+ ProcessContextMessage(message);
}
else if (string.Equals(message.MessageType, "PlaybackStart", StringComparison.OrdinalIgnoreCase))
{
@@ -105,79 +70,98 @@ namespace MediaBrowser.Server.Implementations.Session
}
else if (string.Equals(message.MessageType, "PlaybackProgress", StringComparison.OrdinalIgnoreCase))
{
- var session = _sessionManager.Sessions.FirstOrDefault(i => i.WebSockets.Contains(message.Connection));
-
- if (session != null && session.User != null)
- {
- var vals = message.Data.Split('|');
-
- var item = _dtoService.GetItemByDtoId(vals[0]);
-
- long? positionTicks = null;
-
- if (vals.Length > 1)
- {
- long pos;
-
- if (long.TryParse(vals[1], out pos))
- {
- positionTicks = pos;
- }
- }
-
- var isPaused = vals.Length > 2 && string.Equals(vals[2], "true", StringComparison.OrdinalIgnoreCase);
- var isMuted = vals.Length > 3 && string.Equals(vals[3], "true", StringComparison.OrdinalIgnoreCase);
-
- var info = new PlaybackProgressInfo
- {
- Item = item,
- PositionTicks = positionTicks,
- IsMuted = isMuted,
- IsPaused = isPaused,
- SessionId = session.Id
- };
-
- _sessionManager.OnPlaybackProgress(info);
- }
+ ReportPlaybackProgress(message);
}
else if (string.Equals(message.MessageType, "PlaybackStopped", StringComparison.OrdinalIgnoreCase))
{
- _logger.Debug("Received PlaybackStopped message");
-
- var session = _sessionManager.Sessions.FirstOrDefault(i => i.WebSockets.Contains(message.Connection));
-
- if (session != null && session.User != null)
- {
- var vals = message.Data.Split('|');
-
- var item = _dtoService.GetItemByDtoId(vals[0]);
-
- long? positionTicks = null;
-
- if (vals.Length > 1)
- {
- long pos;
-
- if (long.TryParse(vals[1], out pos))
- {
- positionTicks = pos;
- }
- }
-
- var info = new PlaybackStopInfo
- {
- Item = item,
- PositionTicks = positionTicks,
- SessionId = session.Id
- };
-
- _sessionManager.OnPlaybackStopped(info);
- }
+ ReportPlaybackStopped(message);
}
return _trueTaskResult;
}
+ ///
+ /// Processes the identity message.
+ ///
+ /// The message.
+ private void ProcessIdentityMessage(WebSocketMessageInfo message)
+ {
+ _logger.Debug("Received Identity message");
+
+ var vals = message.Data.Split('|');
+
+ var client = vals[0];
+ var deviceId = vals[1];
+ var version = vals[2];
+
+ var session = _sessionManager.Sessions
+ .FirstOrDefault(i => string.Equals(i.DeviceId, deviceId) &&
+ string.Equals(i.Client, client) &&
+ string.Equals(i.ApplicationVersion, version));
+
+ if (session != null)
+ {
+ var controller = new WebSocketController(session, _appHost);
+ controller.Sockets.Add(message.Connection);
+
+ session.SessionController = controller;
+ }
+ else
+ {
+ _logger.Warn("Unable to determine session based on identity message: {0}", message.Data);
+ }
+ }
+
+ ///
+ /// Processes the context message.
+ ///
+ /// The message.
+ private void ProcessContextMessage(WebSocketMessageInfo message)
+ {
+ var session = GetSessionFromMessage(message);
+
+ if (session != null)
+ {
+ var vals = message.Data.Split('|');
+
+ session.NowViewingItemType = vals[0];
+ session.NowViewingItemId = vals[1];
+ session.NowViewingItemName = vals[2];
+ session.NowViewingContext = vals.Length > 3 ? vals[3] : null;
+ }
+ }
+
+ ///
+ /// Gets the session from message.
+ ///
+ /// The message.
+ /// SessionInfo.
+ private SessionInfo GetSessionFromMessage(WebSocketMessageInfo message)
+ {
+ var result = _sessionManager.Sessions.FirstOrDefault(i =>
+ {
+ var controller = i.SessionController as WebSocketController;
+
+ if (controller != null)
+ {
+ if (controller.Sockets.Any(s => s.Id == message.Connection.Id))
+ {
+ return true;
+ }
+ }
+
+ return false;
+
+ });
+
+ if (result == null)
+ {
+ _logger.Error("Unable to session based on web socket message");
+ }
+
+ return result;
+ }
+
///
/// Reports the playback start.
///
@@ -185,9 +169,8 @@ namespace MediaBrowser.Server.Implementations.Session
private void ReportPlaybackStart(WebSocketMessageInfo message)
{
_logger.Debug("Received PlaybackStart message");
-
- var session = _sessionManager.Sessions
- .FirstOrDefault(i => i.WebSockets.Contains(message.Connection));
+
+ var session = GetSessionFromMessage(message);
if (session != null && session.User != null)
{
@@ -206,7 +189,7 @@ namespace MediaBrowser.Server.Implementations.Session
{
queueableMediaTypes = vals[2];
}
-
+
var info = new PlaybackInfo
{
CanSeek = canSeek,
@@ -218,5 +201,86 @@ namespace MediaBrowser.Server.Implementations.Session
_sessionManager.OnPlaybackStart(info);
}
}
+
+ ///
+ /// Reports the playback progress.
+ ///
+ /// The message.
+ private void ReportPlaybackProgress(WebSocketMessageInfo message)
+ {
+ var session = GetSessionFromMessage(message);
+
+ if (session != null && session.User != null)
+ {
+ var vals = message.Data.Split('|');
+
+ var item = _dtoService.GetItemByDtoId(vals[0]);
+
+ long? positionTicks = null;
+
+ if (vals.Length > 1)
+ {
+ long pos;
+
+ if (long.TryParse(vals[1], out pos))
+ {
+ positionTicks = pos;
+ }
+ }
+
+ var isPaused = vals.Length > 2 && string.Equals(vals[2], "true", StringComparison.OrdinalIgnoreCase);
+ var isMuted = vals.Length > 3 && string.Equals(vals[3], "true", StringComparison.OrdinalIgnoreCase);
+
+ var info = new PlaybackProgressInfo
+ {
+ Item = item,
+ PositionTicks = positionTicks,
+ IsMuted = isMuted,
+ IsPaused = isPaused,
+ SessionId = session.Id
+ };
+
+ _sessionManager.OnPlaybackProgress(info);
+ }
+ }
+
+ ///
+ /// Reports the playback stopped.
+ ///
+ /// The message.
+ private void ReportPlaybackStopped(WebSocketMessageInfo message)
+ {
+ _logger.Debug("Received PlaybackStopped message");
+
+ var session = GetSessionFromMessage(message);
+
+ if (session != null && session.User != null)
+ {
+ var vals = message.Data.Split('|');
+
+ var item = _dtoService.GetItemByDtoId(vals[0]);
+
+ long? positionTicks = null;
+
+ if (vals.Length > 1)
+ {
+ long pos;
+
+ if (long.TryParse(vals[1], out pos))
+ {
+ positionTicks = pos;
+ }
+ }
+
+ var info = new PlaybackStopInfo
+ {
+ Item = item,
+ PositionTicks = positionTicks,
+ SessionId = session.Id
+ };
+
+ _sessionManager.OnPlaybackStopped(info);
+ }
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
index fb0bc9b7c1..46c8f752dd 100644
--- a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
+++ b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
@@ -1,8 +1,12 @@
using MediaBrowser.Common.Net;
+using MediaBrowser.Controller;
using MediaBrowser.Controller.Session;
+using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Session;
+using MediaBrowser.Model.System;
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -11,15 +15,39 @@ namespace MediaBrowser.Server.Implementations.Session
{
public class WebSocketController : ISessionController
{
- public bool Supports(SessionInfo session)
+ public SessionInfo Session { get; private set; }
+ public List Sockets { get; private set; }
+
+ private readonly IServerApplicationHost _appHost;
+
+ public WebSocketController(SessionInfo session, IServerApplicationHost appHost)
{
- return session.WebSockets.Any(i => i.State == WebSocketState.Open);
+ Session = session;
+ _appHost = appHost;
+ Sockets = new List();
}
- private IWebSocketConnection GetSocket(SessionInfo session)
+ public bool SupportsMediaRemoteControl
{
- var socket = session.WebSockets.OrderByDescending(i => i.LastActivityDate).FirstOrDefault(i => i.State == WebSocketState.Open);
+ get
+ {
+ return Sockets.Any(i => i.State == WebSocketState.Open);
+ }
+ }
+ public bool IsSessionActive
+ {
+ get
+ {
+ return Sockets.Any(i => i.State == WebSocketState.Open);
+ }
+ }
+
+ private IWebSocketConnection GetActiveSocket()
+ {
+ var socket = Sockets
+ .OrderByDescending(i => i.LastActivityDate)
+ .FirstOrDefault(i => i.State == WebSocketState.Open);
if (socket == null)
{
@@ -29,9 +57,9 @@ namespace MediaBrowser.Server.Implementations.Session
return socket;
}
- public Task SendSystemCommand(SessionInfo session, SystemCommand command, CancellationToken cancellationToken)
+ public Task SendSystemCommand(SystemCommand command, CancellationToken cancellationToken)
{
- var socket = GetSocket(session);
+ var socket = GetActiveSocket();
return socket.SendAsync(new WebSocketMessage
{
@@ -41,9 +69,9 @@ namespace MediaBrowser.Server.Implementations.Session
}, cancellationToken);
}
- public Task SendMessageCommand(SessionInfo session, MessageCommand command, CancellationToken cancellationToken)
+ public Task SendMessageCommand(MessageCommand command, CancellationToken cancellationToken)
{
- var socket = GetSocket(session);
+ var socket = GetActiveSocket();
return socket.SendAsync(new WebSocketMessage
{
@@ -53,9 +81,9 @@ namespace MediaBrowser.Server.Implementations.Session
}, cancellationToken);
}
- public Task SendPlayCommand(SessionInfo session, PlayRequest command, CancellationToken cancellationToken)
+ public Task SendPlayCommand(PlayRequest command, CancellationToken cancellationToken)
{
- var socket = GetSocket(session);
+ var socket = GetActiveSocket();
return socket.SendAsync(new WebSocketMessage
{
@@ -65,9 +93,9 @@ namespace MediaBrowser.Server.Implementations.Session
}, cancellationToken);
}
- public Task SendBrowseCommand(SessionInfo session, BrowseRequest command, CancellationToken cancellationToken)
+ public Task SendBrowseCommand(BrowseRequest command, CancellationToken cancellationToken)
{
- var socket = GetSocket(session);
+ var socket = GetActiveSocket();
return socket.SendAsync(new WebSocketMessage
{
@@ -77,9 +105,9 @@ namespace MediaBrowser.Server.Implementations.Session
}, cancellationToken);
}
- public Task SendPlaystateCommand(SessionInfo session, PlaystateRequest command, CancellationToken cancellationToken)
+ public Task SendPlaystateCommand(PlaystateRequest command, CancellationToken cancellationToken)
{
- var socket = GetSocket(session);
+ var socket = GetActiveSocket();
return socket.SendAsync(new WebSocketMessage
{
@@ -88,5 +116,34 @@ namespace MediaBrowser.Server.Implementations.Session
}, cancellationToken);
}
+
+ public Task SendLibraryUpdateInfo(LibraryUpdateInfo info, CancellationToken cancellationToken)
+ {
+ var socket = GetActiveSocket();
+
+ return socket.SendAsync(new WebSocketMessage
+ {
+ MessageType = "Playstate",
+ Data = info
+
+ }, cancellationToken);
+ }
+
+ ///
+ /// Sends the restart required message.
+ ///
+ /// The cancellation token.
+ /// Task.
+ public Task SendRestartRequiredMessage(CancellationToken cancellationToken)
+ {
+ var socket = GetActiveSocket();
+
+ return socket.SendAsync(new WebSocketMessage
+ {
+ MessageType = "RestartRequired",
+ Data = _appHost.GetSystemInfo()
+
+ }, cancellationToken);
+ }
}
}
diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs
index c9d079fc71..a10b7c15b8 100644
--- a/MediaBrowser.ServerApplication/ApplicationHost.cs
+++ b/MediaBrowser.ServerApplication/ApplicationHost.cs
@@ -427,8 +427,6 @@ namespace MediaBrowser.ServerApplication
ProviderManager.AddParts(GetExports());
- SessionManager.AddParts(GetExports());
-
ImageProcessor.AddParts(GetExports());
LiveTvManager.AddParts(GetExports());
diff --git a/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs b/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs
index 8b0beab48c..43a6984346 100644
--- a/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs
+++ b/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs
@@ -46,7 +46,7 @@ namespace MediaBrowser.ServerApplication.Native
/// The logger.
public static void OpenCommunity(ILogger logger)
{
- OpenUrl("http://community.mediabrowser.tv/", logger);
+ OpenUrl("http://mediabrowser3.com/community", logger);
}
///
diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec
index f9ccca41e9..18187392a0 100644
--- a/Nuget/MediaBrowser.Common.Internal.nuspec
+++ b/Nuget/MediaBrowser.Common.Internal.nuspec
@@ -2,7 +2,7 @@
MediaBrowser.Common.Internal
- 3.0.215
+ 3.0.216
MediaBrowser.Common.Internal
Luke
ebr,Luke,scottisafool
@@ -12,7 +12,7 @@
Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.
Copyright © Media Browser 2013
-
+
diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec
index 2045689ae7..a9cc361a99 100644
--- a/Nuget/MediaBrowser.Common.nuspec
+++ b/Nuget/MediaBrowser.Common.nuspec
@@ -2,7 +2,7 @@
MediaBrowser.Common
- 3.0.215
+ 3.0.216
MediaBrowser.Common
Media Browser Team
ebr,Luke,scottisafool
diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec
index 4d306b695a..56e9222d4e 100644
--- a/Nuget/MediaBrowser.Server.Core.nuspec
+++ b/Nuget/MediaBrowser.Server.Core.nuspec
@@ -2,7 +2,7 @@
MediaBrowser.Server.Core
- 3.0.215
+ 3.0.216
Media Browser.Server.Core
Media Browser Team
ebr,Luke,scottisafool
@@ -12,7 +12,7 @@
Contains core components required to build plugins for Media Browser Server.
Copyright © Media Browser 2013
-
+