mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-07-30 01:09:09 +02:00
support more kinds of remote control besides web socket
This commit is contained in:
parent
04319900f9
commit
c61cc4a304
|
@ -325,49 +325,11 @@ namespace MediaBrowser.Api
|
||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
public void Post(SendSystemCommand request)
|
public void Post(SendSystemCommand request)
|
||||||
{
|
{
|
||||||
var task = SendSystemCommand(request);
|
var task = _sessionManager.SendSystemCommand(request.Id, request.Command, CancellationToken.None);
|
||||||
|
|
||||||
Task.WaitAll(task);
|
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>
|
/// <summary>
|
||||||
/// Posts the specified request.
|
/// Posts the specified request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -165,6 +165,7 @@
|
||||||
<Compile Include="Kernel.cs" />
|
<Compile Include="Kernel.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Providers\BaseMetadataProvider.cs" />
|
<Compile Include="Providers\BaseMetadataProvider.cs" />
|
||||||
|
<Compile Include="Session\ISessionRemoteController.cs" />
|
||||||
<Compile Include="Session\PlaybackInfo.cs" />
|
<Compile Include="Session\PlaybackInfo.cs" />
|
||||||
<Compile Include="Session\SessionInfo.cs" />
|
<Compile Include="Session\SessionInfo.cs" />
|
||||||
<Compile Include="Sorting\IBaseItemComparer.cs" />
|
<Compile Include="Sorting\IBaseItemComparer.cs" />
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
|
using MediaBrowser.Model.Session;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Session
|
namespace MediaBrowser.Controller.Session
|
||||||
|
@ -11,6 +13,12 @@ namespace MediaBrowser.Controller.Session
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISessionManager
|
public interface ISessionManager
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the parts.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="remoteControllers">The remote controllers.</param>
|
||||||
|
void AddParts(IEnumerable<ISessionRemoteController> remoteControllers);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when [playback start].
|
/// Occurs when [playback start].
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -72,5 +80,14 @@ namespace MediaBrowser.Controller.Session
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
/// <exception cref="System.ArgumentNullException"></exception>
|
/// <exception cref="System.ArgumentNullException"></exception>
|
||||||
Task OnPlaybackStopped(BaseItem item, long? positionTicks, Guid sessionId);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
25
MediaBrowser.Controller/Session/ISessionRemoteController.cs
Normal file
25
MediaBrowser.Controller/Session/ISessionRemoteController.cs
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -183,6 +183,7 @@
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Session\SessionWebSocketListener.cs" />
|
<Compile Include="Session\SessionWebSocketListener.cs" />
|
||||||
|
<Compile Include="Session\WebSocketController.cs" />
|
||||||
<Compile Include="Sorting\AlbumArtistComparer.cs" />
|
<Compile Include="Sorting\AlbumArtistComparer.cs" />
|
||||||
<Compile Include="Sorting\AlbumComparer.cs" />
|
<Compile Include="Sorting\AlbumComparer.cs" />
|
||||||
<Compile Include="Sorting\AlbumCountComparer.cs" />
|
<Compile Include="Sorting\AlbumCountComparer.cs" />
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using MediaBrowser.Common.Events;
|
using MediaBrowser.Common.Events;
|
||||||
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Audio;
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
|
@ -6,6 +7,7 @@ using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Persistence;
|
using MediaBrowser.Controller.Persistence;
|
||||||
using MediaBrowser.Controller.Session;
|
using MediaBrowser.Controller.Session;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
|
using MediaBrowser.Model.Session;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -75,6 +77,12 @@ namespace MediaBrowser.Server.Implementations.Session
|
||||||
_userRepository = userRepository;
|
_userRepository = userRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<ISessionRemoteController> _remoteControllers;
|
||||||
|
public void AddParts(IEnumerable<ISessionRemoteController> remoteControllers)
|
||||||
|
{
|
||||||
|
_remoteControllers = remoteControllers.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all connections.
|
/// Gets all connections.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -408,5 +416,54 @@ namespace MediaBrowser.Server.Implementations.Session
|
||||||
|
|
||||||
data.PlaybackPositionTicks = positionTicks;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -161,6 +161,7 @@ namespace MediaBrowser.ServerApplication
|
||||||
private IMediaEncoder MediaEncoder { get; set; }
|
private IMediaEncoder MediaEncoder { get; set; }
|
||||||
|
|
||||||
private IIsoManager IsoManager { get; set; }
|
private IIsoManager IsoManager { get; set; }
|
||||||
|
private ISessionManager SessionManager { get; set; }
|
||||||
|
|
||||||
private ILocalizationManager LocalizationManager { get; set; }
|
private ILocalizationManager LocalizationManager { get; set; }
|
||||||
|
|
||||||
|
@ -286,8 +287,8 @@ namespace MediaBrowser.ServerApplication
|
||||||
|
|
||||||
RegisterSingleInstance<ILibrarySearchEngine>(() => new LuceneSearchEngine(ApplicationPaths, LogManager, LibraryManager));
|
RegisterSingleInstance<ILibrarySearchEngine>(() => new LuceneSearchEngine(ApplicationPaths, LogManager, LibraryManager));
|
||||||
|
|
||||||
var clientConnectionManager = new SessionManager(UserDataRepository, ServerConfigurationManager, Logger, UserRepository);
|
SessionManager = new SessionManager(UserDataRepository, ServerConfigurationManager, Logger, UserRepository);
|
||||||
RegisterSingleInstance<ISessionManager>(clientConnectionManager);
|
RegisterSingleInstance<ISessionManager>(SessionManager);
|
||||||
|
|
||||||
HttpServer = await _httpServerCreationTask.ConfigureAwait(false);
|
HttpServer = await _httpServerCreationTask.ConfigureAwait(false);
|
||||||
RegisterSingleInstance(HttpServer, false);
|
RegisterSingleInstance(HttpServer, false);
|
||||||
|
@ -477,6 +478,8 @@ namespace MediaBrowser.ServerApplication
|
||||||
|
|
||||||
IsoManager.AddParts(GetExports<IIsoMounter>());
|
IsoManager.AddParts(GetExports<IIsoMounter>());
|
||||||
|
|
||||||
|
SessionManager.AddParts(GetExports<ISessionRemoteController>());
|
||||||
|
|
||||||
ImageProcessor.AddParts(GetExports<IImageEnhancer>());
|
ImageProcessor.AddParts(GetExports<IImageEnhancer>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue