diff --git a/MediaBrowser.Api/SessionsService.cs b/MediaBrowser.Api/SessionsService.cs
index cad3c43849..b93b5326e6 100644
--- a/MediaBrowser.Api/SessionsService.cs
+++ b/MediaBrowser.Api/SessionsService.cs
@@ -325,49 +325,11 @@ namespace MediaBrowser.Api
/// The request.
public void Post(SendSystemCommand request)
{
- var task = SendSystemCommand(request);
+ var task = _sessionManager.SendSystemCommand(request.Id, request.Command, CancellationToken.None);
Task.WaitAll(task);
}
- private async Task SendSystemCommand(SendSystemCommand request)
- {
- var session = _sessionManager.Sessions.FirstOrDefault(i => i.Id == request.Id);
-
- if (session == null)
- {
- throw new ResourceNotFoundException(string.Format("Session {0} not found.", request.Id));
- }
-
- if (!session.SupportsRemoteControl)
- {
- throw new ArgumentException(string.Format("Session {0} does not support remote control.", session.Id));
- }
-
- var socket = session.WebSockets.OrderByDescending(i => i.LastActivityDate).FirstOrDefault(i => i.State == WebSocketState.Open);
-
- if (socket != null)
- {
- try
- {
- await socket.SendAsync(new WebSocketMessage
- {
- MessageType = "SystemCommand",
- Data = request.Command.ToString()
-
- }, CancellationToken.None).ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- Logger.ErrorException("Error sending web socket message", ex);
- }
- }
- else
- {
- throw new InvalidOperationException("The requested session does not have an open web socket.");
- }
- }
-
///
/// Posts the specified request.
///
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 80cf82da15..b5ad862bee 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -165,6 +165,7 @@
+
diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs
index fba1d26e8b..f8f7ded2b7 100644
--- a/MediaBrowser.Controller/Session/ISessionManager.cs
+++ b/MediaBrowser.Controller/Session/ISessionManager.cs
@@ -1,7 +1,9 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Session;
using System;
using System.Collections.Generic;
+using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Session
@@ -11,6 +13,12 @@ namespace MediaBrowser.Controller.Session
///
public interface ISessionManager
{
+ ///
+ /// Adds the parts.
+ ///
+ /// The remote controllers.
+ void AddParts(IEnumerable remoteControllers);
+
///
/// Occurs when [playback start].
///
@@ -72,5 +80,14 @@ namespace MediaBrowser.Controller.Session
/// Task.
///
Task OnPlaybackStopped(BaseItem item, long? positionTicks, Guid sessionId);
+
+ ///
+ /// Sends the system command.
+ ///
+ /// The session id.
+ /// The command.
+ /// The cancellation token.
+ /// Task.
+ Task SendSystemCommand(Guid sessionId, SystemCommand command, CancellationToken cancellationToken);
}
}
\ No newline at end of file
diff --git a/MediaBrowser.Controller/Session/ISessionRemoteController.cs b/MediaBrowser.Controller/Session/ISessionRemoteController.cs
new file mode 100644
index 0000000000..1f6faeb9c2
--- /dev/null
+++ b/MediaBrowser.Controller/Session/ISessionRemoteController.cs
@@ -0,0 +1,25 @@
+using MediaBrowser.Model.Session;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Session
+{
+ public interface ISessionRemoteController
+ {
+ ///
+ /// Supportses the specified session.
+ ///
+ /// The session.
+ /// true if XXXX, false otherwise
+ bool Supports(SessionInfo session);
+
+ ///
+ /// Sends the system command.
+ ///
+ /// The session.
+ /// The command.
+ /// The cancellation token.
+ /// Task.
+ Task SendSystemCommand(SessionInfo session, SystemCommand command, CancellationToken cancellationToken);
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index 9d2fc8c6b3..3c20217509 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -183,6 +183,7 @@
Code
+
diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
index 65ec02d128..5b0d957ae1 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.Events;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
@@ -6,6 +7,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Session;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -75,6 +77,12 @@ namespace MediaBrowser.Server.Implementations.Session
_userRepository = userRepository;
}
+ private List _remoteControllers;
+ public void AddParts(IEnumerable remoteControllers)
+ {
+ _remoteControllers = remoteControllers.ToList();
+ }
+
///
/// Gets all connections.
///
@@ -122,7 +130,7 @@ namespace MediaBrowser.Server.Implementations.Session
var activityDate = DateTime.UtcNow;
var session = GetSessionInfo(clientType, appVersion, deviceId, deviceName, user);
-
+
session.LastActivityDate = activityDate;
if (user == null)
@@ -233,7 +241,7 @@ namespace MediaBrowser.Server.Implementations.Session
var key = item.GetUserDataKey();
var user = session.User;
-
+
var data = _userDataRepository.GetUserData(user.Id, key);
data.PlayCount++;
@@ -321,7 +329,7 @@ namespace MediaBrowser.Server.Implementations.Session
{
throw new ArgumentOutOfRangeException("positionTicks");
}
-
+
var session = Sessions.First(i => i.Id.Equals(sessionId));
RemoveNowPlayingItem(session, item);
@@ -329,7 +337,7 @@ namespace MediaBrowser.Server.Implementations.Session
var key = item.GetUserDataKey();
var user = session.User;
-
+
var data = _userDataRepository.GetUserData(user.Id, key);
if (positionTicks.HasValue)
@@ -408,5 +416,54 @@ namespace MediaBrowser.Server.Implementations.Session
data.PlaybackPositionTicks = positionTicks;
}
+
+ ///
+ /// Gets the session for remote control.
+ ///
+ /// The session id.
+ /// SessionInfo.
+ ///
+ private SessionInfo GetSessionForRemoteControl(Guid sessionId)
+ {
+ var session = Sessions.First(i => i.Id.Equals(sessionId));
+
+ if (session == null)
+ {
+ throw new ResourceNotFoundException(string.Format("Session {0} not found.", sessionId));
+ }
+
+ if (!session.SupportsRemoteControl)
+ {
+ 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));
+ }
+
+ ///
+ /// Sends the system command.
+ ///
+ /// The session id.
+ /// The command.
+ /// The cancellation token.
+ /// Task.
+ public Task SendSystemCommand(Guid sessionId, SystemCommand command, CancellationToken cancellationToken)
+ {
+ var session = GetSessionForRemoteControl(sessionId);
+
+ var tasks = GetControllers(session).Select(i => i.SendSystemCommand(session, command, cancellationToken));
+
+ return Task.WhenAll(tasks);
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
new file mode 100644
index 0000000000..daa4c7d819
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
@@ -0,0 +1,52 @@
+using MediaBrowser.Controller.Session;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Net;
+using MediaBrowser.Model.Session;
+using System;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Server.Implementations.Session
+{
+ public class WebSocketController : ISessionRemoteController
+ {
+ private readonly ILogger _logger;
+
+ public WebSocketController(ILogger logger)
+ {
+ _logger = logger;
+ }
+
+ public bool Supports(SessionInfo session)
+ {
+ return session.WebSockets.Any(i => i.State == WebSocketState.Open);
+ }
+
+ public async Task SendSystemCommand(SessionInfo session, SystemCommand command, CancellationToken cancellationToken)
+ {
+ var socket = session.WebSockets.OrderByDescending(i => i.LastActivityDate).FirstOrDefault(i => i.State == WebSocketState.Open);
+
+ if (socket != null)
+ {
+ try
+ {
+ await socket.SendAsync(new WebSocketMessage
+ {
+ MessageType = "SystemCommand",
+ Data = command.ToString()
+
+ }, cancellationToken).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error sending web socket message", ex);
+ }
+ }
+ else
+ {
+ throw new InvalidOperationException("The requested session does not have an open web socket.");
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs
index 7a99693a67..e965166036 100644
--- a/MediaBrowser.ServerApplication/ApplicationHost.cs
+++ b/MediaBrowser.ServerApplication/ApplicationHost.cs
@@ -161,6 +161,7 @@ namespace MediaBrowser.ServerApplication
private IMediaEncoder MediaEncoder { get; set; }
private IIsoManager IsoManager { get; set; }
+ private ISessionManager SessionManager { get; set; }
private ILocalizationManager LocalizationManager { get; set; }
@@ -286,8 +287,8 @@ namespace MediaBrowser.ServerApplication
RegisterSingleInstance(() => new LuceneSearchEngine(ApplicationPaths, LogManager, LibraryManager));
- var clientConnectionManager = new SessionManager(UserDataRepository, ServerConfigurationManager, Logger, UserRepository);
- RegisterSingleInstance(clientConnectionManager);
+ SessionManager = new SessionManager(UserDataRepository, ServerConfigurationManager, Logger, UserRepository);
+ RegisterSingleInstance(SessionManager);
HttpServer = await _httpServerCreationTask.ConfigureAwait(false);
RegisterSingleInstance(HttpServer, false);
@@ -477,6 +478,8 @@ namespace MediaBrowser.ServerApplication
IsoManager.AddParts(GetExports());
+ SessionManager.AddParts(GetExports());
+
ImageProcessor.AddParts(GetExports());
}