diff options
8 files changed, 163 insertions, 45 deletions
diff --git a/MediaBrowser.Api/SessionsService.cs b/MediaBrowser.Api/SessionsService.cs index cad3c4384..b93b5326e 100644 --- a/MediaBrowser.Api/SessionsService.cs +++ b/MediaBrowser.Api/SessionsService.cs @@ -325,49 +325,11 @@ namespace MediaBrowser.Api /// <param name="request">The request.</param> 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<string> - { - 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."); - } - } - /// <summary> /// Posts the specified request. /// </summary> diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 80cf82da1..b5ad862be 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -165,6 +165,7 @@ <Compile Include="Kernel.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Providers\BaseMetadataProvider.cs" /> + <Compile Include="Session\ISessionRemoteController.cs" /> <Compile Include="Session\PlaybackInfo.cs" /> <Compile Include="Session\SessionInfo.cs" /> <Compile Include="Sorting\IBaseItemComparer.cs" /> diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index fba1d26e8..f8f7ded2b 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 @@ -12,6 +14,12 @@ namespace MediaBrowser.Controller.Session public interface ISessionManager { /// <summary> + /// Adds the parts. + /// </summary> + /// <param name="remoteControllers">The remote controllers.</param> + void AddParts(IEnumerable<ISessionRemoteController> remoteControllers); + + /// <summary> /// Occurs when [playback start]. /// </summary> event EventHandler<PlaybackProgressEventArgs> PlaybackStart; @@ -72,5 +80,14 @@ namespace MediaBrowser.Controller.Session /// <returns>Task.</returns> /// <exception cref="System.ArgumentNullException"></exception> Task OnPlaybackStopped(BaseItem item, long? positionTicks, Guid sessionId); + + /// <summary> + /// Sends the system command. + /// </summary> + /// <param name="sessionId">The session id.</param> + /// <param name="command">The command.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task.</returns> + 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 000000000..1f6faeb9c --- /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 + { + /// <summary> + /// Supportses the specified session. + /// </summary> + /// <param name="session">The session.</param> + /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> + bool Supports(SessionInfo session); + + /// <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); + } +} diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 9d2fc8c6b..3c2021750 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -183,6 +183,7 @@ <SubType>Code</SubType> </Compile> <Compile Include="Session\SessionWebSocketListener.cs" /> + <Compile Include="Session\WebSocketController.cs" /> <Compile Include="Sorting\AlbumArtistComparer.cs" /> <Compile Include="Sorting\AlbumComparer.cs" /> <Compile Include="Sorting\AlbumCountComparer.cs" /> diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index 65ec02d12..5b0d957ae 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<ISessionRemoteController> _remoteControllers; + public void AddParts(IEnumerable<ISessionRemoteController> remoteControllers) + { + _remoteControllers = remoteControllers.ToList(); + } + /// <summary> /// Gets all connections. /// </summary> @@ -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; } + + /// <summary> + /// Gets the session for remote control. + /// </summary> + /// <param name="sessionId">The session id.</param> + /// <returns>SessionInfo.</returns> + /// <exception cref="ResourceNotFoundException"></exception> + 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; + } + + /// <summary> + /// Gets the controllers. + /// </summary> + /// <param name="session">The session.</param> + /// <returns>IEnumerable{ISessionRemoteController}.</returns> + private IEnumerable<ISessionRemoteController> GetControllers(SessionInfo session) + { + return _remoteControllers.Where(i => i.Supports(session)); + } + + /// <summary> + /// Sends the system command. + /// </summary> + /// <param name="sessionId">The session id.</param> + /// <param name="command">The command.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task.</returns> + 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 000000000..daa4c7d81 --- /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<string> + { + 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 7a99693a6..e96516603 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<ILibrarySearchEngine>(() => new LuceneSearchEngine(ApplicationPaths, LogManager, LibraryManager)); - var clientConnectionManager = new SessionManager(UserDataRepository, ServerConfigurationManager, Logger, UserRepository); - RegisterSingleInstance<ISessionManager>(clientConnectionManager); + SessionManager = new SessionManager(UserDataRepository, ServerConfigurationManager, Logger, UserRepository); + RegisterSingleInstance<ISessionManager>(SessionManager); HttpServer = await _httpServerCreationTask.ConfigureAwait(false); RegisterSingleInstance(HttpServer, false); @@ -477,6 +478,8 @@ namespace MediaBrowser.ServerApplication IsoManager.AddParts(GetExports<IIsoMounter>()); + SessionManager.AddParts(GetExports<ISessionRemoteController>()); + ImageProcessor.AddParts(GetExports<IImageEnhancer>()); } |
