diff options
| -rw-r--r-- | MediaBrowser.Api/SessionsService.cs | 64 | ||||
| -rw-r--r-- | MediaBrowser.Api/UserLibrary/UserLibraryService.cs | 5 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Dto/SessionInfoDtoBuilder.cs | 11 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Session/ISessionManager.cs | 16 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Session/SessionInfo.cs | 54 | ||||
| -rw-r--r-- | MediaBrowser.Model/Session/SessionInfoDto.cs | 24 | ||||
| -rw-r--r-- | MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj | 4 | ||||
| -rw-r--r-- | MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs | 12 | ||||
| -rw-r--r-- | MediaBrowser.Server.Implementations/Session/SessionManager.cs | 66 | ||||
| -rw-r--r-- | MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs | 104 | ||||
| -rw-r--r-- | MediaBrowser.WebDashboard/Api/DashboardService.cs | 2 | ||||
| -rw-r--r-- | MediaBrowser.WebDashboard/ApiClient.js | 32 | ||||
| -rw-r--r-- | MediaBrowser.WebDashboard/packages.config | 2 | ||||
| -rw-r--r-- | Nuget/MediaBrowser.Common.Internal.nuspec | 6 | ||||
| -rw-r--r-- | Nuget/MediaBrowser.Common.nuspec | 2 | ||||
| -rw-r--r-- | Nuget/MediaBrowser.Server.Core.nuspec | 4 |
16 files changed, 335 insertions, 73 deletions
diff --git a/MediaBrowser.Api/SessionsService.cs b/MediaBrowser.Api/SessionsService.cs index 590fd6f06..271e5bbd6 100644 --- a/MediaBrowser.Api/SessionsService.cs +++ b/MediaBrowser.Api/SessionsService.cs @@ -1,9 +1,13 @@ -using MediaBrowser.Controller.Dto; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Net; using MediaBrowser.Model.Session; using ServiceStack.ServiceHost; +using System; using System.Collections.Generic; using System.Linq; +using System.Threading; namespace MediaBrowser.Api { @@ -14,11 +18,39 @@ namespace MediaBrowser.Api [Api(("Gets a list of sessions"))] public class GetSessions : IReturn<List<SessionInfoDto>> { + [ApiMember(Name = "SupportsRemoteControl", Description = "Optional. Filter by sessions that can be remote controlled.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] + public bool? SupportsRemoteControl { get; set; } + } + + [Route("/Sessions/{Id}/Viewing", "POST")] + [Api(("Instructs a session to browse to an item or view"))] + public class BrowseTo : IReturnVoid + { + [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public Guid Id { get; set; } + /// <summary> - /// Gets or sets a value indicating whether this instance is recent. + /// Artist, Genre, Studio, Person, or any kind of BaseItem /// </summary> - /// <value><c>true</c> if this instance is recent; otherwise, <c>false</c>.</value> - public bool IsRecent { get; set; } + /// <value>The type of the item.</value> + [ApiMember(Name = "ItemType", Description = "Only required if the item is an Artist, Genre, Studio, or Person.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] + public string ItemType { get; set; } + + /// <summary> + /// Artist name, genre name, item Id, etc + /// </summary> + /// <value>The item identifier.</value> + [ApiMember(Name = "ItemIdentifier", Description = "The Id of the item, unless it is an Artist, Genre, Studio, or Person, in which case it should be the name.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] + public string ItemIdentifier { get; set; } + + /// <summary> + /// Gets or sets the context (Movies, Music, TvShows, etc) + /// Applicable to genres, studios and persons only because the context of items and artists can be inferred. + /// This is optional to supply and clients are free to ignore it. + /// </summary> + /// <value>The context.</value> + [ApiMember(Name = "Context", Description = "The navigation context for the client (movies, music, tvshows, games etc). This is optional to supply and clients are free to ignore it.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] + public string Context { get; set; } } /// <summary> @@ -47,9 +79,31 @@ namespace MediaBrowser.Api /// <returns>System.Object.</returns> public object Get(GetSessions request) { - var result = request.IsRecent ? _sessionManager.RecentConnections : _sessionManager.AllConnections; + var result = _sessionManager.Sessions.Where(i => i.IsActive); + + if (request.SupportsRemoteControl.HasValue) + { + result = result.Where(i => i.IsActive == request.SupportsRemoteControl.Value); + } return ToOptimizedResult(result.Select(SessionInfoDtoBuilder.GetSessionInfoDto).ToList()); } + + public void Post(BrowseTo 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)); + } + + session.WebSocket.SendAsync(new WebSocketMessage<BrowseTo> + { + MessageType = "Browse", + Data = request + + }, CancellationToken.None); + } } } diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs index 53f2e9bca..3eadfd4be 100644 --- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs +++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs @@ -262,6 +262,9 @@ namespace MediaBrowser.Api.UserLibrary /// <value>The position ticks.</value> [ApiMember(Name = "PositionTicks", Description = "Optional. The current position, in ticks. 1 tick = 10000 ms", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")] public long? PositionTicks { get; set; } + + [ApiMember(Name = "IsPaused", Description = "Indicates if the player is paused.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")] + public bool IsPaused { get; set; } } /// <summary> @@ -715,7 +718,7 @@ namespace MediaBrowser.Api.UserLibrary if (auth != null) { - var task = _sessionManager.OnPlaybackProgress(user, item, request.PositionTicks, auth["Client"], auth["DeviceId"], auth["Device"] ?? string.Empty); + var task = _sessionManager.OnPlaybackProgress(user, item, request.PositionTicks, request.IsPaused, auth["Client"], auth["DeviceId"], auth["Device"] ?? string.Empty); Task.WaitAll(task); } diff --git a/MediaBrowser.Controller/Dto/SessionInfoDtoBuilder.cs b/MediaBrowser.Controller/Dto/SessionInfoDtoBuilder.cs index 850af573f..27a237ba7 100644 --- a/MediaBrowser.Controller/Dto/SessionInfoDtoBuilder.cs +++ b/MediaBrowser.Controller/Dto/SessionInfoDtoBuilder.cs @@ -1,5 +1,4 @@ using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Net; using MediaBrowser.Model.Session; namespace MediaBrowser.Controller.Dto @@ -23,7 +22,12 @@ namespace MediaBrowser.Controller.Dto DeviceName = session.DeviceName, Id = session.Id, LastActivityDate = session.LastActivityDate, - NowPlayingPositionTicks = session.NowPlayingPositionTicks + NowPlayingPositionTicks = session.NowPlayingPositionTicks, + SupportsRemoteControl = session.SupportsRemoteControl, + IsPaused = session.IsPaused, + NowViewingContext = session.NowViewingContext, + NowViewingItemIdentifier = session.NowViewingItemIdentifier, + NowViewingItemType = session.NowViewingItemType }; if (session.NowPlayingItem != null) @@ -36,9 +40,6 @@ namespace MediaBrowser.Controller.Dto dto.UserId = session.UserId.Value.ToString("N"); } - dto.SupportsRemoteControl = session.WebSocket != null && - session.WebSocket.State == WebSocketState.Open; - return dto; } } diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index 66facdf6d..8227170d4 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -3,7 +3,6 @@ using MediaBrowser.Controller.Library; using System; using System.Collections.Generic; using System.Threading.Tasks; -using MediaBrowser.Model.Session; namespace MediaBrowser.Controller.Session { @@ -28,16 +27,10 @@ namespace MediaBrowser.Controller.Session event EventHandler<PlaybackProgressEventArgs> PlaybackStopped; /// <summary> - /// Gets all connections. + /// Gets the sessions. /// </summary> - /// <value>All connections.</value> - IEnumerable<SessionInfo> AllConnections { get; } - - /// <summary> - /// Gets the active connections. - /// </summary> - /// <value>The active connections.</value> - IEnumerable<SessionInfo> RecentConnections { get; } + /// <value>The sessions.</value> + IEnumerable<SessionInfo> Sessions { get; } /// <summary> /// Logs the user activity. @@ -67,12 +60,13 @@ namespace MediaBrowser.Controller.Session /// <param name="user">The user.</param> /// <param name="item">The item.</param> /// <param name="positionTicks">The position ticks.</param> + /// <param name="isPaused">if set to <c>true</c> [is paused].</param> /// <param name="clientType">Type of the client.</param> /// <param name="deviceId">The device id.</param> /// <param name="deviceName">Name of the device.</param> /// <returns>Task.</returns> /// <exception cref="System.ArgumentNullException"></exception> - Task OnPlaybackProgress(User user, BaseItem item, long? positionTicks, string clientType, string deviceId, string deviceName); + Task OnPlaybackProgress(User user, BaseItem item, long? positionTicks, bool isPaused, string clientType, string deviceId, string deviceName); /// <summary> /// Used to report that playback has ended for an item diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs index 21c65df97..93ef4f694 100644 --- a/MediaBrowser.Controller/Session/SessionInfo.cs +++ b/MediaBrowser.Controller/Session/SessionInfo.cs @@ -1,5 +1,6 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Net; using System; namespace MediaBrowser.Controller.Session @@ -40,6 +41,24 @@ namespace MediaBrowser.Controller.Session public string DeviceName { get; set; } /// <summary> + /// Gets or sets the now viewing context. + /// </summary> + /// <value>The now viewing context.</value> + public string NowViewingContext { get; set; } + + /// <summary> + /// Gets or sets the type of the now viewing item. + /// </summary> + /// <value>The type of the now viewing item.</value> + public string NowViewingItemType { get; set; } + + /// <summary> + /// Gets or sets the now viewing item identifier. + /// </summary> + /// <value>The now viewing item identifier.</value> + public string NowViewingItemIdentifier { get; set; } + + /// <summary> /// Gets or sets the now playing item. /// </summary> /// <value>The now playing item.</value> @@ -52,6 +71,12 @@ namespace MediaBrowser.Controller.Session public long? NowPlayingPositionTicks { get; set; } /// <summary> + /// Gets or sets a value indicating whether this instance is paused. + /// </summary> + /// <value><c>true</c> if this instance is paused; otherwise, <c>false</c>.</value> + public bool? IsPaused { get; set; } + + /// <summary> /// Gets or sets the device id. /// </summary> /// <value>The device id.</value> @@ -62,5 +87,34 @@ namespace MediaBrowser.Controller.Session /// </summary> /// <value>The web socket.</value> public IWebSocketConnection WebSocket { 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> + public bool IsActive + { + get + { + if (WebSocket != null) + { + return WebSocket.State == WebSocketState.Open; + } + + return (DateTime.UtcNow - LastActivityDate).TotalMinutes <= 5; + } + } + + /// <summary> + /// Gets a value indicating whether [supports remote control]. + /// </summary> + /// <value><c>true</c> if [supports remote control]; otherwise, <c>false</c>.</value> + public bool SupportsRemoteControl + { + get + { + return WebSocket != null && WebSocket.State == WebSocketState.Open; + } + } } } diff --git a/MediaBrowser.Model/Session/SessionInfoDto.cs b/MediaBrowser.Model/Session/SessionInfoDto.cs index 0548876a1..2b9c1a64e 100644 --- a/MediaBrowser.Model/Session/SessionInfoDto.cs +++ b/MediaBrowser.Model/Session/SessionInfoDto.cs @@ -30,12 +30,36 @@ namespace MediaBrowser.Model.Session public DateTime LastActivityDate { get; set; } /// <summary> + /// Gets or sets the now viewing context. + /// </summary> + /// <value>The now viewing context.</value> + public string NowViewingContext { get; set; } + + /// <summary> + /// Gets or sets the type of the now viewing item. + /// </summary> + /// <value>The type of the now viewing item.</value> + public string NowViewingItemType { get; set; } + + /// <summary> + /// Gets or sets the now viewing item identifier. + /// </summary> + /// <value>The now viewing item identifier.</value> + public string NowViewingItemIdentifier { get; set; } + + /// <summary> /// Gets or sets the name of the device. /// </summary> /// <value>The name of the device.</value> public string DeviceName { get; set; } /// <summary> + /// Gets or sets a value indicating whether this instance is paused. + /// </summary> + /// <value><c>true</c> if this instance is paused; otherwise, <c>false</c>.</value> + public bool? IsPaused { get; set; } + + /// <summary> /// Gets or sets the now playing item. /// </summary> /// <value>The now playing item.</value> diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 45515b81f..3474f2e05 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -207,7 +207,9 @@ </ProjectReference> </ItemGroup> <ItemGroup> - <Content Include="swagger-ui\css\hightlight.default.css" /> + <Content Include="swagger-ui\css\hightlight.default.css"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </Content> <Content Include="swagger-ui\css\screen.css"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> diff --git a/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs b/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs index 5a074d194..6b6826bdc 100644 --- a/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs +++ b/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs @@ -32,7 +32,7 @@ namespace MediaBrowser.Server.Implementations.ServerManager /// <summary> /// The _send semaphore /// </summary> - private readonly SemaphoreSlim _sendSemaphore = new SemaphoreSlim(1,1); + private readonly SemaphoreSlim _sendSemaphore = new SemaphoreSlim(1, 1); /// <summary> /// The logger @@ -100,7 +100,13 @@ namespace MediaBrowser.Server.Implementations.ServerManager using (var memoryStream = new MemoryStream(bytes)) { - info = (WebSocketMessageInfo)_jsonSerializer.DeserializeFromStream(memoryStream, typeof(WebSocketMessageInfo)); + var stub = (WebSocketMessage<object>)_jsonSerializer.DeserializeFromStream(memoryStream, typeof(WebSocketMessage<object>)); + + info = new WebSocketMessageInfo + { + MessageType = stub.MessageType, + Data = stub.Data == null ? null : stub.Data.ToString() + }; } info.Connection = this; @@ -163,7 +169,7 @@ namespace MediaBrowser.Server.Implementations.ServerManager { throw new ArgumentNullException("cancellationToken"); } - + cancellationToken.ThrowIfCancellationRequested(); // Per msdn docs, attempting to send simultaneous messages will result in one failing. diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index 99407e349..2f9c7e389 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -1,14 +1,12 @@ using MediaBrowser.Common.Events; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; 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; @@ -18,10 +16,19 @@ using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.Session { + /// <summary> + /// Class SessionManager + /// </summary> public class SessionManager : ISessionManager { + /// <summary> + /// The _user data repository + /// </summary> private readonly IUserDataRepository _userDataRepository; + /// <summary> + /// The _user repository + /// </summary> private readonly IUserRepository _userRepository; /// <summary> @@ -54,6 +61,13 @@ namespace MediaBrowser.Server.Implementations.Session /// </summary> public event EventHandler<PlaybackProgressEventArgs> PlaybackStopped; + /// <summary> + /// Initializes a new instance of the <see cref="SessionManager"/> class. + /// </summary> + /// <param name="userDataRepository">The user data repository.</param> + /// <param name="configurationManager">The configuration manager.</param> + /// <param name="logger">The logger.</param> + /// <param name="userRepository">The user repository.</param> public SessionManager(IUserDataRepository userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository) { _userDataRepository = userDataRepository; @@ -66,20 +80,14 @@ namespace MediaBrowser.Server.Implementations.Session /// Gets all connections. /// </summary> /// <value>All connections.</value> - public IEnumerable<SessionInfo> AllConnections + public IEnumerable<SessionInfo> Sessions { - get { return _activeConnections.Values.OrderByDescending(c => c.LastActivityDate); } + get { return _activeConnections.Values.OrderByDescending(c => c.LastActivityDate).ToList(); } } /// <summary> - /// Gets the active connections. + /// The _true task result /// </summary> - /// <value>The active connections.</value> - public IEnumerable<SessionInfo> RecentConnections - { - get { return AllConnections.Where(c => (DateTime.UtcNow - c.LastActivityDate).TotalMinutes <= 5); } - } - private readonly Task _trueTaskResult = Task.FromResult(true); /// <summary> @@ -124,11 +132,13 @@ namespace MediaBrowser.Server.Implementations.Session /// <param name="deviceId">The device id.</param> /// <param name="deviceName">Name of the device.</param> /// <param name="item">The item.</param> + /// <param name="isPaused">if set to <c>true</c> [is paused].</param> /// <param name="currentPositionTicks">The current position ticks.</param> - private void UpdateNowPlayingItemId(User user, string clientType, string deviceId, string deviceName, BaseItem item, long? currentPositionTicks = null) + private void UpdateNowPlayingItemId(User user, string clientType, string deviceId, string deviceName, BaseItem item, bool isPaused, long? currentPositionTicks = null) { var conn = GetConnection(clientType, deviceId, deviceName, user); + conn.IsPaused = isPaused; conn.NowPlayingPositionTicks = currentPositionTicks; conn.NowPlayingItem = item; conn.LastActivityDate = DateTime.UtcNow; @@ -150,6 +160,7 @@ namespace MediaBrowser.Server.Implementations.Session { conn.NowPlayingItem = null; conn.NowPlayingPositionTicks = null; + conn.IsPaused = null; } } @@ -187,7 +198,8 @@ namespace MediaBrowser.Server.Implementations.Session /// <param name="clientType">Type of the client.</param> /// <param name="deviceId">The device id.</param> /// <param name="deviceName">Name of the device.</param> - /// <exception cref="System.ArgumentNullException"></exception> + /// <exception cref="System.ArgumentNullException"> + /// </exception> public void OnPlaybackStart(User user, BaseItem item, string clientType, string deviceId, string deviceName) { if (user == null) @@ -199,7 +211,7 @@ namespace MediaBrowser.Server.Implementations.Session throw new ArgumentNullException(); } - UpdateNowPlayingItemId(user, clientType, deviceId, deviceName, item); + UpdateNowPlayingItemId(user, clientType, deviceId, deviceName, item, false); // Nothing to save here // Fire events to inform plugins @@ -216,12 +228,14 @@ namespace MediaBrowser.Server.Implementations.Session /// <param name="user">The user.</param> /// <param name="item">The item.</param> /// <param name="positionTicks">The position ticks.</param> + /// <param name="isPaused">if set to <c>true</c> [is paused].</param> /// <param name="clientType">Type of the client.</param> /// <param name="deviceId">The device id.</param> /// <param name="deviceName">Name of the device.</param> /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException"></exception> - public async Task OnPlaybackProgress(User user, BaseItem item, long? positionTicks, string clientType, string deviceId, string deviceName) + /// <exception cref="System.ArgumentNullException"> + /// </exception> + public async Task OnPlaybackProgress(User user, BaseItem item, long? positionTicks, bool isPaused, string clientType, string deviceId, string deviceName) { if (user == null) { @@ -232,7 +246,7 @@ namespace MediaBrowser.Server.Implementations.Session throw new ArgumentNullException(); } - UpdateNowPlayingItemId(user, clientType, deviceId, deviceName, item, positionTicks); + UpdateNowPlayingItemId(user, clientType, deviceId, deviceName, item, isPaused, positionTicks); var key = item.GetUserDataKey(); @@ -262,7 +276,8 @@ namespace MediaBrowser.Server.Implementations.Session /// <param name="deviceId">The device id.</param> /// <param name="deviceName">Name of the device.</param> /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException"></exception> + /// <exception cref="System.ArgumentNullException"> + /// </exception> public async Task OnPlaybackStopped(User user, BaseItem item, long? positionTicks, string clientType, string deviceId, string deviceName) { if (user == null) @@ -355,20 +370,5 @@ namespace MediaBrowser.Server.Implementations.Session data.LastPlayedDate = DateTime.UtcNow; } } - - /// <summary> - /// Identifies the web socket. - /// </summary> - /// <param name="sessionId">The session id.</param> - /// <param name="webSocket">The web socket.</param> - public void IdentifyWebSocket(Guid sessionId, IWebSocketConnection webSocket) - { - var session = AllConnections.FirstOrDefault(i => i.Id == sessionId); - - if (session != null) - { - session.WebSocket = webSocket; - } - } } } diff --git a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs index 59c79c23e..ed1280ea9 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs @@ -1,5 +1,9 @@ -using MediaBrowser.Common.Net; +using System.Globalization; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Logging; using System; using System.Linq; using System.Threading.Tasks; @@ -22,12 +26,26 @@ namespace MediaBrowser.Server.Implementations.Session private readonly ISessionManager _sessionManager; /// <summary> - /// Initializes a new instance of the <see cref="SessionWebSocketListener"/> class. + /// The _logger + /// </summary> + private readonly ILogger _logger; + + private readonly IUserManager _userManager; + private readonly ILibraryManager _libraryManager; + + /// <summary> + /// Initializes a new instance of the <see cref="SessionWebSocketListener" /> class. /// </summary> /// <param name="sessionManager">The session manager.</param> - public SessionWebSocketListener(ISessionManager sessionManager) + /// <param name="logger">The logger.</param> + /// <param name="libraryManager">The library manager.</param> + /// <param name="userManager">The user manager.</param> + public SessionWebSocketListener(ISessionManager sessionManager, ILogger logger, ILibraryManager libraryManager, IUserManager userManager) { _sessionManager = sessionManager; + _logger = logger; + _libraryManager = libraryManager; + _userManager = userManager; } /// <summary> @@ -44,11 +62,87 @@ namespace MediaBrowser.Server.Implementations.Session var client = vals[0]; var deviceId = vals[1]; - var session = _sessionManager.AllConnections.FirstOrDefault(i => string.Equals(i.DeviceId, deviceId) && string.Equals(i.Client, client)); + var session = _sessionManager.Sessions.FirstOrDefault(i => string.Equals(i.DeviceId, deviceId) && string.Equals(i.Client, client)); + + if (session != null) + { + session.WebSocket = message.Connection; + } + } + else if (string.Equals(message.MessageType, "Context", StringComparison.OrdinalIgnoreCase)) + { + var session = _sessionManager.Sessions.FirstOrDefault(i => i.WebSocket == message.Connection); if (session != null) { - ((SessionManager)_sessionManager).IdentifyWebSocket(session.Id, message.Connection); + var vals = message.Data.Split('|'); + + session.NowViewingItemType = vals[0]; + session.NowViewingItemIdentifier = vals[1]; + session.NowViewingContext = vals.Length > 2 ? vals[2] : null; + } + } + else if (string.Equals(message.MessageType, "PlaybackStart", StringComparison.OrdinalIgnoreCase)) + { + var session = _sessionManager.Sessions.FirstOrDefault(i => i.WebSocket == message.Connection); + + if (session != null && session.UserId.HasValue) + { + var item = DtoBuilder.GetItemByClientId(message.Data, _userManager, _libraryManager); + + _sessionManager.OnPlaybackStart(_userManager.GetUserById(session.UserId.Value), item, session.Client, session.DeviceId, session.DeviceName); + } + } + else if (string.Equals(message.MessageType, "PlaybackProgress", StringComparison.OrdinalIgnoreCase)) + { + var session = _sessionManager.Sessions.FirstOrDefault(i => i.WebSocket == message.Connection); + + if (session != null && session.UserId.HasValue) + { + var vals = message.Data.Split('|'); + + var item = DtoBuilder.GetItemByClientId(vals[0], _userManager, _libraryManager); + + 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); + + _sessionManager.OnPlaybackProgress(_userManager.GetUserById(session.UserId.Value), item, positionTicks, isPaused, session.Client, session.DeviceId, session.DeviceName); + } + } + else if (string.Equals(message.MessageType, "PlaybackStopped", StringComparison.OrdinalIgnoreCase)) + { + var session = _sessionManager.Sessions.FirstOrDefault(i => i.WebSocket == message.Connection); + + if (session != null && session.UserId.HasValue) + { + var vals = message.Data.Split('|'); + + var item = DtoBuilder.GetItemByClientId(vals[0], _userManager, _libraryManager); + + long? positionTicks = null; + + if (vals.Length > 1) + { + long pos; + + if (long.TryParse(vals[1], out pos)) + { + positionTicks = pos; + } + } + + _sessionManager.OnPlaybackStopped(_userManager.GetUserById(session.UserId.Value), item, positionTicks, session.Client, session.DeviceId, session.DeviceName); } } diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index a0892060f..56c7b99f9 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -206,7 +206,7 @@ namespace MediaBrowser.WebDashboard.Api ILibraryManager libraryManager, ISessionManager connectionManager) { - var connections = connectionManager.RecentConnections.ToArray(); + var connections = connectionManager.Sessions.Where(i => i.IsActive).ToArray(); var dtoBuilder = new UserDtoBuilder(logger); diff --git a/MediaBrowser.WebDashboard/ApiClient.js b/MediaBrowser.WebDashboard/ApiClient.js index 2982a40a9..999a7d918 100644 --- a/MediaBrowser.WebDashboard/ApiClient.js +++ b/MediaBrowser.WebDashboard/ApiClient.js @@ -2379,6 +2379,16 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) { throw new Error("null itemId"); } + if (self.isWebSocketOpen()) { + + var deferred = $.Deferred(); + + self.sendWebSocketMessage("PlaybackStart", itemId); + + deferred.resolveWith(null, []); + return deferred.promise(); + } + var url = self.getUrl("Users/" + userId + "/PlayingItems/" + itemId); return self.ajax({ @@ -2392,7 +2402,7 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) { * @param {String} userId * @param {String} itemId */ - self.reportPlaybackProgress = function (userId, itemId, positionTicks) { + self.reportPlaybackProgress = function (userId, itemId, positionTicks, isPaused) { if (!userId) { throw new Error("null userId"); @@ -2402,6 +2412,16 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) { throw new Error("null itemId"); } + if (self.isWebSocketOpen()) { + + var deferred = $.Deferred(); + + self.sendWebSocketMessage("PlaybackProgress", itemId + "|" + (positionTicks == null ? "" : positionTicks) + "|" + (isPaused == null ? "" : isPaused)); + + deferred.resolveWith(null, []); + return deferred.promise(); + } + var params = { }; @@ -2433,6 +2453,16 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) { throw new Error("null itemId"); } + if (self.isWebSocketOpen()) { + + var deferred = $.Deferred(); + + self.sendWebSocketMessage("PlaybackStopped", itemId + "|" + (positionTicks == null ? "" : positionTicks)); + + deferred.resolveWith(null, []); + return deferred.promise(); + } + var params = { }; diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config index 8072ff77d..be1673780 100644 --- a/MediaBrowser.WebDashboard/packages.config +++ b/MediaBrowser.WebDashboard/packages.config @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <packages> - <package id="MediaBrowser.ApiClient.Javascript" version="3.0.101" targetFramework="net45" /> + <package id="MediaBrowser.ApiClient.Javascript" version="3.0.104" targetFramework="net45" /> <package id="ServiceStack.Common" version="3.9.44" targetFramework="net45" /> <package id="ServiceStack.Text" version="3.9.44" targetFramework="net45" /> </packages>
\ No newline at end of file diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 56feae805..1feb82848 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.97</version> + <version>3.0.98</version> <title>MediaBrowser.Common.Internal</title> <authors>Luke</authors> <owners>ebr,Luke,scottisafool</owners> @@ -12,9 +12,9 @@ <description>Contains common components shared by Media Browser Theatre 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.97" /> + <dependency id="MediaBrowser.Common" version="3.0.98" /> <dependency id="NLog" version="2.0.1.2" /> - <dependency id="ServiceStack.Text" version="3.9.97" /> + <dependency id="ServiceStack.Text" version="3.9.98" /> <dependency id="SimpleInjector" version="2.2.1" /> </dependencies> </metadata> diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 0860c7c9c..85d2ca3c5 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata> <id>MediaBrowser.Common</id> - <version>3.0.97</version> + <version>3.0.98</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 ed83cc8d8..5670f8a6c 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.97</version> + <version>3.0.98</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.97" /> + <dependency id="MediaBrowser.Common" version="3.0.98" /> </dependencies> </metadata> <files> |
