aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MediaBrowser.Common/Net/IServerManager.cs11
-rw-r--r--MediaBrowser.Common/Net/IWebSocketConnection.cs6
-rw-r--r--MediaBrowser.Controller/Session/ISessionController.cs46
-rw-r--r--MediaBrowser.Controller/Session/ISessionManager.cs13
-rw-r--r--MediaBrowser.Controller/Session/SessionInfo.cs29
-rw-r--r--MediaBrowser.Model/Querying/ItemQuery.cs18
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs47
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/WebSocketEvents.cs9
-rw-r--r--MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs2
-rw-r--r--MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs7
-rw-r--r--MediaBrowser.Server.Implementations/Session/SessionManager.cs54
-rw-r--r--MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs258
-rw-r--r--MediaBrowser.Server.Implementations/Session/WebSocketController.cs85
-rw-r--r--MediaBrowser.ServerApplication/ApplicationHost.cs2
-rw-r--r--MediaBrowser.ServerApplication/Native/BrowserLauncher.cs2
-rw-r--r--Nuget/MediaBrowser.Common.Internal.nuspec4
-rw-r--r--Nuget/MediaBrowser.Common.nuspec2
-rw-r--r--Nuget/MediaBrowser.Server.Core.nuspec4
18 files changed, 377 insertions, 222 deletions
diff --git a/MediaBrowser.Common/Net/IServerManager.cs b/MediaBrowser.Common/Net/IServerManager.cs
index 32be88a34..6965677bb 100644
--- a/MediaBrowser.Common/Net/IServerManager.cs
+++ b/MediaBrowser.Common/Net/IServerManager.cs
@@ -63,17 +63,6 @@ namespace MediaBrowser.Common.Net
Task SendWebSocketMessageAsync<T>(string messageType, Func<T> dataFunction, CancellationToken cancellationToken);
/// <summary>
- /// Sends the web socket message async.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="messageType">Type of the message.</param>
- /// <param name="dataFunction">The data function.</param>
- /// <param name="connections">The connections.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task.</returns>
- Task SendWebSocketMessageAsync<T>(string messageType, Func<T> dataFunction, IEnumerable<IWebSocketConnection> connections, CancellationToken cancellationToken);
-
- /// <summary>
/// Adds the web socket listeners.
/// </summary>
/// <param name="listeners">The listeners.</param>
diff --git a/MediaBrowser.Common/Net/IWebSocketConnection.cs b/MediaBrowser.Common/Net/IWebSocketConnection.cs
index 434b8ff5c..482da131e 100644
--- a/MediaBrowser.Common/Net/IWebSocketConnection.cs
+++ b/MediaBrowser.Common/Net/IWebSocketConnection.cs
@@ -8,6 +8,12 @@ namespace MediaBrowser.Common.Net
public interface IWebSocketConnection : IDisposable
{
/// <summary>
+ /// Gets the id.
+ /// </summary>
+ /// <value>The id.</value>
+ Guid Id { get; }
+
+ /// <summary>
/// Gets the last activity date.
/// </summary>
/// <value>The last activity date.</value>
diff --git a/MediaBrowser.Controller/Session/ISessionController.cs b/MediaBrowser.Controller/Session/ISessionController.cs
index f37d63b72..597a14cc6 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
{
/// <summary>
- /// Supportses the specified session.
+ /// Gets a value indicating whether [supports media remote control].
/// </summary>
- /// <param name="session">The session.</param>
- /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
- bool Supports(SessionInfo session);
+ /// <value><c>true</c> if [supports media remote control]; otherwise, <c>false</c>.</value>
+ bool SupportsMediaRemoteControl { get; }
+
+ /// <summary>
+ /// Gets a value indicating whether this instance is session active.
+ /// </summary>
+ /// <value><c>true</c> if this instance is session active; otherwise, <c>false</c>.</value>
+ bool IsSessionActive { get; }
/// <summary>
/// Sends the system command.
/// </summary>
- /// <param name="session">The session.</param>
/// <param name="command">The command.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task SendSystemCommand(SessionInfo session, SystemCommand command, CancellationToken cancellationToken);
+ Task SendSystemCommand(SystemCommand command, CancellationToken cancellationToken);
/// <summary>
/// Sends the message command.
/// </summary>
- /// <param name="session">The session.</param>
/// <param name="command">The command.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task SendMessageCommand(SessionInfo session, MessageCommand command, CancellationToken cancellationToken);
+ Task SendMessageCommand(MessageCommand command, CancellationToken cancellationToken);
/// <summary>
/// Sends the play command.
/// </summary>
- /// <param name="session">The session.</param>
/// <param name="command">The command.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task SendPlayCommand(SessionInfo session, PlayRequest command, CancellationToken cancellationToken);
+ Task SendPlayCommand(PlayRequest command, CancellationToken cancellationToken);
/// <summary>
/// Sends the browse command.
/// </summary>
- /// <param name="session">The session.</param>
/// <param name="command">The command.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task SendBrowseCommand(SessionInfo session, BrowseRequest command, CancellationToken cancellationToken);
+ Task SendBrowseCommand(BrowseRequest command, CancellationToken cancellationToken);
/// <summary>
/// Sends the playstate command.
/// </summary>
- /// <param name="session">The session.</param>
/// <param name="command">The command.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task SendPlaystateCommand(SessionInfo session, PlaystateRequest command, CancellationToken cancellationToken);
+ Task SendPlaystateCommand(PlaystateRequest command, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Sends the library update info.
+ /// </summary>
+ /// <param name="info">The info.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ Task SendLibraryUpdateInfo(LibraryUpdateInfo info, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Sends the restart required message.
+ /// </summary>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ Task SendRestartRequiredMessage(CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs
index 6ee57eb46..b2d111e54 100644
--- a/MediaBrowser.Controller/Session/ISessionManager.cs
+++ b/MediaBrowser.Controller/Session/ISessionManager.cs
@@ -14,12 +14,6 @@ namespace MediaBrowser.Controller.Session
public interface ISessionManager
{
/// <summary>
- /// Adds the parts.
- /// </summary>
- /// <param name="remoteControllers">The remote controllers.</param>
- void AddParts(IEnumerable<ISessionController> remoteControllers);
-
- /// <summary>
/// Occurs when [playback start].
/// </summary>
event EventHandler<PlaybackProgressEventArgs> PlaybackStart;
@@ -119,5 +113,12 @@ namespace MediaBrowser.Controller.Session
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task SendPlaystateCommand(Guid sessionId, PlaystateRequest command, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Sends the restart required message.
+ /// </summary>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ 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 d50f19c1f..ed2fcda67 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<IWebSocketConnection>();
QueueableMediaTypes = new List<string>();
}
@@ -115,18 +111,18 @@ namespace MediaBrowser.Controller.Session
public string DeviceId { get; set; }
/// <summary>
- /// Gets or sets the web socket.
- /// </summary>
- /// <value>The web socket.</value>
- public List<IWebSocketConnection> WebSockets { get; set; }
-
- /// <summary>
/// Gets or sets the application version.
/// </summary>
/// <value>The application version.</value>
public string ApplicationVersion { get; set; }
/// <summary>
+ /// Gets or sets the session controller.
+ /// </summary>
+ /// <value>The session controller.</value>
+ public ISessionController SessionController { get; set; }
+
+ /// <summary>
/// Gets a value indicating whether this instance is active.
/// </summary>
/// <value><c>true</c> if this instance is active; otherwise, <c>false</c>.</value>
@@ -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 69c79104a..20eac55e8 100644
--- a/MediaBrowser.Model/Querying/ItemQuery.cs
+++ b/MediaBrowser.Model/Querying/ItemQuery.cs
@@ -207,6 +207,24 @@ namespace MediaBrowser.Model.Querying
public int? ParentIndexNumber { get; set; }
/// <summary>
+ /// Gets or sets the min players.
+ /// </summary>
+ /// <value>The min players.</value>
+ public int? MinPlayers { get; set; }
+
+ /// <summary>
+ /// Gets or sets the name starts with or greater.
+ /// </summary>
+ /// <value>The name starts with or greater.</value>
+ public string NameStartsWithOrGreater { get; set; }
+
+ /// <summary>
+ /// Gets or sets the album artist starts with or greater.
+ /// </summary>
+ /// <value>The album artist starts with or greater.</value>
+ public string AlbumArtistStartsWithOrGreater { get; set; }
+
+ /// <summary>
/// Initializes a new instance of the <see cref="ItemQuery" /> class.
/// </summary>
public ItemQuery()
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs
index 1306017ca..7a3081ab5 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
/// </summary>
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
/// <param name="foldersAddedTo">The folders added to.</param>
/// <param name="foldersRemovedFrom">The folders removed from.</param>
/// <param name="cancellationToken">The cancellation token.</param>
- private async void SendChangeNotifications(IEnumerable<BaseItem> itemsAdded, IEnumerable<BaseItem> itemsUpdated, IEnumerable<BaseItem> itemsRemoved, IEnumerable<Folder> foldersAddedTo, IEnumerable<Folder> foldersRemovedFrom, CancellationToken cancellationToken)
+ private async void SendChangeNotifications(List<BaseItem> itemsAdded, List<BaseItem> itemsUpdated, List<BaseItem> itemsRemoved, List<Folder> foldersAddedTo, List<Folder> 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
- {
- await _serverManager.SendWebSocketMessageAsync("LibraryChanged", () => GetLibraryUpdateInfo(itemsAdded, itemsUpdated, itemsRemoved, foldersAddedTo, foldersRemovedFrom, id), webSockets, cancellationToken).ConfigureAwait(false);
- }
- catch (Exception ex)
+ if (userSessions.Count > 0)
{
- _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 29372a40a..4349b6976 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;
+
/// <summary>
/// Initializes a new instance of the <see cref="WebSocketEvents" /> class.
/// </summary>
/// <param name="serverManager">The server manager.</param>
/// <param name="logger">The logger.</param>
/// <param name="userManager">The user manager.</param>
- 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
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
void kernel_HasPendingRestartChanged(object sender, EventArgs e)
{
- _serverManager.SendWebSocketMessage("RestartRequired", _appHost.GetSystemInfo());
+ _sessionManager.SendRestartRequiredMessage(CancellationToken.None);
}
/// <summary>
diff --git a/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs b/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs
index a840ae214..638e6fa0d 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</exception>
- public async Task SendWebSocketMessageAsync<T>(string messageType, Func<T> dataFunction, IEnumerable<IWebSocketConnection> connections, CancellationToken cancellationToken)
+ private async Task SendWebSocketMessageAsync<T>(string messageType, Func<T> dataFunction, IEnumerable<IWebSocketConnection> connections, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(messageType))
{
diff --git a/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs b/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs
index 4bab10ee0..61c06ba6d 100644
--- a/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs
+++ b/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs
@@ -57,6 +57,12 @@ namespace MediaBrowser.Server.Implementations.ServerManager
public DateTime LastActivityDate { get; private set; }
/// <summary>
+ /// Gets the id.
+ /// </summary>
+ /// <value>The id.</value>
+ public Guid Id { get; private set; }
+
+ /// <summary>
/// Initializes a new instance of the <see cref="WebSocketConnection" /> class.
/// </summary>
/// <param name="socket">The socket.</param>
@@ -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 efb8dbe10..ac69b0dc5 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<ISessionController> _remoteControllers;
- public void AddParts(IEnumerable<ISessionController> remoteControllers)
- {
- _remoteControllers = remoteControllers.ToList();
- }
-
/// <summary>
/// Gets all connections.
/// </summary>
@@ -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;
- }
- /// <summary>
- /// Gets the controllers.
- /// </summary>
- /// <param name="session">The session.</param>
- /// <returns>IEnumerable{ISessionRemoteController}.</returns>
- private IEnumerable<ISessionController> GetControllers(SessionInfo session)
- {
- return _remoteControllers.Where(i => i.Supports(session));
+ return session;
}
/// <summary>
@@ -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);
}
/// <summary>
@@ -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);
}
/// <summary>
@@ -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);
}
/// <summary>
@@ -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);
}
/// <summary>
@@ -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 0781e8228..e90dd8eb9 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
/// </summary>
private readonly IDtoService _dtoService;
+ private readonly IServerApplicationHost _appHost;
/// <summary>
/// Initializes a new instance of the <see cref="SessionWebSocketListener" /> class.
@@ -40,11 +41,12 @@ namespace MediaBrowser.Server.Implementations.Session
/// <param name="sessionManager">The session manager.</param>
/// <param name="logManager">The log manager.</param>
/// <param name="dtoService">The dto service.</param>
- 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;
}
/// <summary>
@@ -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,77 +70,96 @@ 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));
+ ReportPlaybackProgress(message);
+ }
+ else if (string.Equals(message.MessageType, "PlaybackStopped", StringComparison.OrdinalIgnoreCase))
+ {
+ ReportPlaybackStopped(message);
+ }
- if (session != null && session.User != null)
- {
- var vals = message.Data.Split('|');
+ return _trueTaskResult;
+ }
- var item = _dtoService.GetItemByDtoId(vals[0]);
+ /// <summary>
+ /// Processes the identity message.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ private void ProcessIdentityMessage(WebSocketMessageInfo message)
+ {
+ _logger.Debug("Received Identity message");
- long? positionTicks = null;
+ var vals = message.Data.Split('|');
- if (vals.Length > 1)
- {
- long pos;
+ var client = vals[0];
+ var deviceId = vals[1];
+ var version = vals[2];
- if (long.TryParse(vals[1], out pos))
- {
- positionTicks = pos;
- }
- }
+ var session = _sessionManager.Sessions
+ .FirstOrDefault(i => string.Equals(i.DeviceId, deviceId) &&
+ string.Equals(i.Client, client) &&
+ string.Equals(i.ApplicationVersion, version));
- var isPaused = vals.Length > 2 && string.Equals(vals[2], "true", StringComparison.OrdinalIgnoreCase);
- var isMuted = vals.Length > 3 && string.Equals(vals[3], "true", StringComparison.OrdinalIgnoreCase);
+ if (session != null)
+ {
+ var controller = new WebSocketController(session, _appHost);
+ controller.Sockets.Add(message.Connection);
- var info = new PlaybackProgressInfo
- {
- Item = item,
- PositionTicks = positionTicks,
- IsMuted = isMuted,
- IsPaused = isPaused,
- SessionId = session.Id
- };
-
- _sessionManager.OnPlaybackProgress(info);
- }
+ session.SessionController = controller;
}
- else if (string.Equals(message.MessageType, "PlaybackStopped", StringComparison.OrdinalIgnoreCase))
+ else
{
- _logger.Debug("Received PlaybackStopped message");
-
- var session = _sessionManager.Sessions.FirstOrDefault(i => i.WebSockets.Contains(message.Connection));
+ _logger.Warn("Unable to determine session based on identity message: {0}", message.Data);
+ }
+ }
- if (session != null && session.User != null)
- {
- var vals = message.Data.Split('|');
+ /// <summary>
+ /// Processes the context message.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ private void ProcessContextMessage(WebSocketMessageInfo message)
+ {
+ var session = GetSessionFromMessage(message);
- var item = _dtoService.GetItemByDtoId(vals[0]);
+ if (session != null)
+ {
+ var vals = message.Data.Split('|');
- long? positionTicks = null;
+ session.NowViewingItemType = vals[0];
+ session.NowViewingItemId = vals[1];
+ session.NowViewingItemName = vals[2];
+ session.NowViewingContext = vals.Length > 3 ? vals[3] : null;
+ }
+ }
- if (vals.Length > 1)
- {
- long pos;
+ /// <summary>
+ /// Gets the session from message.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ /// <returns>SessionInfo.</returns>
+ private SessionInfo GetSessionFromMessage(WebSocketMessageInfo message)
+ {
+ var result = _sessionManager.Sessions.FirstOrDefault(i =>
+ {
+ var controller = i.SessionController as WebSocketController;
- if (long.TryParse(vals[1], out pos))
- {
- positionTicks = pos;
- }
+ if (controller != null)
+ {
+ if (controller.Sockets.Any(s => s.Id == message.Connection.Id))
+ {
+ return true;
}
+ }
- var info = new PlaybackStopInfo
- {
- Item = item,
- PositionTicks = positionTicks,
- SessionId = session.Id
- };
+ return false;
- _sessionManager.OnPlaybackStopped(info);
- }
+ });
+
+ if (result == null)
+ {
+ _logger.Error("Unable to session based on web socket message");
}
- return _trueTaskResult;
+ return result;
}
/// <summary>
@@ -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);
}
}
+
+ /// <summary>
+ /// Reports the playback progress.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ 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);
+ }
+ }
+
+ /// <summary>
+ /// Reports the playback stopped.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ 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 fb0bc9b7c..46c8f752d 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<IWebSocketConnection> 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<IWebSocketConnection>();
}
- 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<string>
{
@@ -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<MessageCommand>
{
@@ -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<PlayRequest>
{
@@ -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<BrowseRequest>
{
@@ -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<PlaystateRequest>
{
@@ -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<LibraryUpdateInfo>
+ {
+ MessageType = "Playstate",
+ Data = info
+
+ }, cancellationToken);
+ }
+
+ /// <summary>
+ /// Sends the restart required message.
+ /// </summary>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ public Task SendRestartRequiredMessage(CancellationToken cancellationToken)
+ {
+ var socket = GetActiveSocket();
+
+ return socket.SendAsync(new WebSocketMessage<SystemInfo>
+ {
+ MessageType = "RestartRequired",
+ Data = _appHost.GetSystemInfo()
+
+ }, cancellationToken);
+ }
}
}
diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs
index c9d079fc7..a10b7c15b 100644
--- a/MediaBrowser.ServerApplication/ApplicationHost.cs
+++ b/MediaBrowser.ServerApplication/ApplicationHost.cs
@@ -427,8 +427,6 @@ namespace MediaBrowser.ServerApplication
ProviderManager.AddParts(GetExports<BaseMetadataProvider>());
- SessionManager.AddParts(GetExports<ISessionController>());
-
ImageProcessor.AddParts(GetExports<IImageEnhancer>());
LiveTvManager.AddParts(GetExports<ILiveTvService>());
diff --git a/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs b/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs
index 8b0beab48..43a698434 100644
--- a/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs
+++ b/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs
@@ -46,7 +46,7 @@ namespace MediaBrowser.ServerApplication.Native
/// <param name="logger">The logger.</param>
public static void OpenCommunity(ILogger logger)
{
- OpenUrl("http://community.mediabrowser.tv/", logger);
+ OpenUrl("http://mediabrowser3.com/community", logger);
}
/// <summary>
diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec
index f9ccca41e..18187392a 100644
--- a/Nuget/MediaBrowser.Common.Internal.nuspec
+++ b/Nuget/MediaBrowser.Common.Internal.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common.Internal</id>
- <version>3.0.215</version>
+ <version>3.0.216</version>
<title>MediaBrowser.Common.Internal</title>
<authors>Luke</authors>
<owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
<description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
- <dependency id="MediaBrowser.Common" version="3.0.215" />
+ <dependency id="MediaBrowser.Common" version="3.0.216" />
<dependency id="NLog" version="2.0.1.2" />
<dependency id="ServiceStack.Text" version="3.9.58" />
<dependency id="SimpleInjector" version="2.3.2" />
diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec
index 2045689ae..a9cc361a9 100644
--- a/Nuget/MediaBrowser.Common.nuspec
+++ b/Nuget/MediaBrowser.Common.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common</id>
- <version>3.0.215</version>
+ <version>3.0.216</version>
<title>MediaBrowser.Common</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>
diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec
index 4d306b695..56e9222d4 100644
--- a/Nuget/MediaBrowser.Server.Core.nuspec
+++ b/Nuget/MediaBrowser.Server.Core.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>MediaBrowser.Server.Core</id>
- <version>3.0.215</version>
+ <version>3.0.216</version>
<title>Media Browser.Server.Core</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
<description>Contains core components required to build plugins for Media Browser Server.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
- <dependency id="MediaBrowser.Common" version="3.0.215" />
+ <dependency id="MediaBrowser.Common" version="3.0.216" />
</dependencies>
</metadata>
<files>