From 66624293ac2208020d25456801664d10ddd2450a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 9 Jul 2013 12:11:16 -0400 Subject: [PATCH] Display client version in the dashboard --- MediaBrowser.Api/BaseApiService.cs | 18 ++- MediaBrowser.Api/SessionsService.cs | 76 +++++++++- .../UserLibrary/UserLibraryService.cs | 44 +++--- MediaBrowser.Controller/Dto/DtoBuilder.cs | 4 +- .../Dto/SessionInfoDtoBuilder.cs | 3 +- .../MediaBrowser.Controller.csproj | 2 +- .../IServerConfigurationManager.cs | 0 .../Session/ISessionManager.cs | 25 ++-- .../Session/SessionInfo.cs | 6 + .../MediaBrowser.Model.net35.csproj | 7 +- MediaBrowser.Model/ApiClient/IApiClient.cs | 14 ++ MediaBrowser.Model/MediaBrowser.Model.csproj | 3 +- MediaBrowser.Model/Querying/UserQuery.cs | 9 ++ ...laystateRequest.cs => PlaystateCommand.cs} | 26 +--- MediaBrowser.Model/Session/SessionInfoDto.cs | 6 + .../ScheduledTasks/ChapterImagesTask.cs | 12 +- .../Session/SessionManager.cs | 132 +++++++++--------- .../Session/SessionWebSocketListener.cs | 6 +- .../Api/DashboardService.cs | 6 + MediaBrowser.WebDashboard/ApiClient.js | 9 +- MediaBrowser.WebDashboard/packages.config | 2 +- 21 files changed, 266 insertions(+), 144 deletions(-) rename MediaBrowser.Controller/{ => Notifications}/Configuration/IServerConfigurationManager.cs (100%) create mode 100644 MediaBrowser.Model/Querying/UserQuery.cs rename MediaBrowser.Model/Session/{PlaystateRequest.cs => PlaystateCommand.cs} (66%) diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs index 193a23b3e..06e9c80e8 100644 --- a/MediaBrowser.Api/BaseApiService.cs +++ b/MediaBrowser.Api/BaseApiService.cs @@ -286,13 +286,21 @@ namespace MediaBrowser.Api } } - var deviceId = auth["DeviceId"]; - var device = auth["Device"]; - var client = auth["Client"]; + string deviceId; + string device; + string client; + string version; - if (!string.IsNullOrEmpty(client) && !string.IsNullOrEmpty(deviceId) && !string.IsNullOrEmpty(device)) + auth.TryGetValue("DeviceId", out deviceId); + auth.TryGetValue("Device", out device); + auth.TryGetValue("Client", out client); + auth.TryGetValue("Version", out version); + + version = version ?? "0.0.0.0"; + + if (!string.IsNullOrEmpty(client) && !string.IsNullOrEmpty(deviceId) && !string.IsNullOrEmpty(device) && !string.IsNullOrEmpty(version)) { - SessionManager.LogConnectionActivity(client, deviceId, device, user); + SessionManager.LogConnectionActivity(client, version, deviceId, device, user); } } } diff --git a/MediaBrowser.Api/SessionsService.cs b/MediaBrowser.Api/SessionsService.cs index a682d670d..bbd1fd985 100644 --- a/MediaBrowser.Api/SessionsService.cs +++ b/MediaBrowser.Api/SessionsService.cs @@ -1,6 +1,5 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Dto; -using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Net; using MediaBrowser.Model.Session; @@ -106,6 +105,31 @@ namespace MediaBrowser.Api public PlayCommand PlayCommand { get; set; } } + [Route("/Sessions/{Id}/Playing/{Command}", "POST")] + [Api(("Issues a playstate command to a client"))] + public class SendPlaystateCommand : IReturnVoid + { + /// + /// Gets or sets the id. + /// + /// The id. + [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public Guid Id { get; set; } + + /// + /// Gets or sets the position to seek to + /// + [ApiMember(Name = "SeekPosition", Description = "The position to seek to.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] + public long? SeekPosition { get; set; } + + /// + /// Gets or sets the play command. + /// + /// The play command. + [ApiMember(Name = "Command", Description = "The command to send - stop, pause, unpause, nexttrack, previoustrack, seek.", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public PlaystateCommand Command { get; set; } + } + /// /// Class SessionsService /// @@ -142,6 +166,56 @@ namespace MediaBrowser.Api return ToOptimizedResult(result.Select(SessionInfoDtoBuilder.GetSessionInfoDto).ToList()); } + public void Post(SendPlaystateCommand request) + { + var task = SendPlaystateCommand(request); + + Task.WaitAll(task); + } + + private async Task SendPlaystateCommand(SendPlaystateCommand 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 = "Playstate", + + Data = new PlayStateRequest + { + Command = request.Command, + SeekPosition = request.SeekPosition + } + + }, 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.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs index 6f5ed8cba..951415694 100644 --- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs +++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs @@ -586,6 +586,25 @@ namespace MediaBrowser.Api.UserLibrary Task.WaitAll(task); } + private SessionInfo GetSession() + { + var auth = RequestFilterAttribute.GetAuthorization(RequestContext); + + string deviceId; + string client; + string version; + + auth.TryGetValue("DeviceId", out deviceId); + auth.TryGetValue("Client", out client); + auth.TryGetValue("Version", out version); + + version = version ?? "0.0.0.0"; + + return _sessionManager.Sessions.First(i => string.Equals(i.DeviceId, deviceId) && + string.Equals(i.Client, client) && + string.Equals(i.ApplicationVersion, version)); + } + /// /// Posts the specified request. /// @@ -596,12 +615,7 @@ namespace MediaBrowser.Api.UserLibrary var item = DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id); - var auth = RequestFilterAttribute.GetAuthorization(RequestContext); - - if (auth != null) - { - _sessionManager.OnPlaybackStart(user, item, auth["Client"], auth["DeviceId"], auth["Device"] ?? string.Empty); - } + _sessionManager.OnPlaybackStart(item, GetSession().Id); } /// @@ -614,14 +628,9 @@ namespace MediaBrowser.Api.UserLibrary var item = DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id); - var auth = RequestFilterAttribute.GetAuthorization(RequestContext); + var task = _sessionManager.OnPlaybackProgress(item, request.PositionTicks, request.IsPaused, GetSession().Id); - if (auth != null) - { - var task = _sessionManager.OnPlaybackProgress(user, item, request.PositionTicks, request.IsPaused, auth["Client"], auth["DeviceId"], auth["Device"] ?? string.Empty); - - Task.WaitAll(task); - } + Task.WaitAll(task); } /// @@ -634,14 +643,9 @@ namespace MediaBrowser.Api.UserLibrary var item = DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id); - var auth = RequestFilterAttribute.GetAuthorization(RequestContext); + var task = _sessionManager.OnPlaybackStopped(item, request.PositionTicks, GetSession().Id); - if (auth != null) - { - var task = _sessionManager.OnPlaybackStopped(user, item, request.PositionTicks, auth["Client"], auth["DeviceId"], auth["Device"] ?? string.Empty); - - Task.WaitAll(task); - } + Task.WaitAll(task); } /// diff --git a/MediaBrowser.Controller/Dto/DtoBuilder.cs b/MediaBrowser.Controller/Dto/DtoBuilder.cs index d1a0465cd..7167447e4 100644 --- a/MediaBrowser.Controller/Dto/DtoBuilder.cs +++ b/MediaBrowser.Controller/Dto/DtoBuilder.cs @@ -381,9 +381,9 @@ namespace MediaBrowser.Controller.Dto if (parentWithImage != null) { - dto.ParentLogoItemId = GetClientItemId(parentWithImage); + dto.ParentArtItemId = GetClientItemId(parentWithImage); - dto.ParentLogoImageTag = GetImageCacheTag(parentWithImage, ImageType.Art, parentWithImage.GetImage(ImageType.Art)); + dto.ParentArtImageTag = GetImageCacheTag(parentWithImage, ImageType.Art, parentWithImage.GetImage(ImageType.Art)); } } diff --git a/MediaBrowser.Controller/Dto/SessionInfoDtoBuilder.cs b/MediaBrowser.Controller/Dto/SessionInfoDtoBuilder.cs index 27e6a8d95..b2ce4a6ba 100644 --- a/MediaBrowser.Controller/Dto/SessionInfoDtoBuilder.cs +++ b/MediaBrowser.Controller/Dto/SessionInfoDtoBuilder.cs @@ -28,7 +28,8 @@ namespace MediaBrowser.Controller.Dto NowViewingContext = session.NowViewingContext, NowViewingItemId = session.NowViewingItemId, NowViewingItemName = session.NowViewingItemName, - NowViewingItemType = session.NowViewingItemType + NowViewingItemType = session.NowViewingItemType, + ApplicationVersion = session.ApplicationVersion }; if (session.NowPlayingItem != null) diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 3d2b46712..814f6d5a1 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -70,7 +70,7 @@ Properties\SharedVersion.cs - + diff --git a/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs b/MediaBrowser.Controller/Notifications/Configuration/IServerConfigurationManager.cs similarity index 100% rename from MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs rename to MediaBrowser.Controller/Notifications/Configuration/IServerConfigurationManager.cs diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index f28721f5f..2af2bbec9 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -36,49 +36,42 @@ namespace MediaBrowser.Controller.Session /// Logs the user activity. /// /// Type of the client. + /// The app version. /// The device id. /// Name of the device. /// The user. /// Task. /// user - Task LogConnectionActivity(string clientType, string deviceId, string deviceName, User user); + Task LogConnectionActivity(string clientType, string appVersion, string deviceId, string deviceName, User user); /// /// Used to report that playback has started for an item /// - /// The user. /// The item. - /// Type of the client. - /// The device id. - /// Name of the device. + /// The session id. + /// Task. /// - Task OnPlaybackStart(User user, BaseItem item, string clientType, string deviceId, string deviceName); + Task OnPlaybackStart(BaseItem item, Guid sessionId); /// /// Used to report playback progress for an item /// - /// The user. /// The item. /// The position ticks. /// if set to true [is paused]. - /// Type of the client. - /// The device id. - /// Name of the device. + /// The session id. /// Task. /// - Task OnPlaybackProgress(User user, BaseItem item, long? positionTicks, bool isPaused, string clientType, string deviceId, string deviceName); + Task OnPlaybackProgress(BaseItem item, long? positionTicks, bool isPaused, Guid sessionId); /// /// Used to report that playback has ended for an item /// - /// The user. /// The item. /// The position ticks. - /// Type of the client. - /// The device id. - /// Name of the device. + /// The session id. /// Task. /// - Task OnPlaybackStopped(User user, BaseItem item, long? positionTicks, string clientType, string deviceId, string deviceName); + Task OnPlaybackStopped(BaseItem item, long? positionTicks, Guid sessionId); } } \ No newline at end of file diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs index e49b52624..177573de6 100644 --- a/MediaBrowser.Controller/Session/SessionInfo.cs +++ b/MediaBrowser.Controller/Session/SessionInfo.cs @@ -101,6 +101,12 @@ namespace MediaBrowser.Controller.Session /// The web socket. public List WebSockets { get; set; } + /// + /// Gets or sets the application version. + /// + /// The application version. + public string ApplicationVersion { get; set; } + /// /// Gets a value indicating whether this instance is active. /// diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index 9c534f916..95fea4071 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -268,6 +268,9 @@ Querying\ThemeSongsResult.cs + + Querying\UserQuery.cs + Search\SearchHint.cs @@ -286,8 +289,8 @@ Session\PlayRequest.cs - - Session\PlaystateRequest.cs + + Session\PlaystateCommand.cs Session\SessionInfoDto.cs diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs index 4ec7b14e1..990f63f84 100644 --- a/MediaBrowser.Model/ApiClient/IApiClient.cs +++ b/MediaBrowser.Model/ApiClient/IApiClient.cs @@ -100,6 +100,12 @@ namespace MediaBrowser.Model.ApiClient /// Task{UserDto[]}. Task GetUsersAsync(); + /// + /// Gets the public users async. + /// + /// Task{UserDto[]}. + Task GetPublicUsersAsync(); + /// /// Gets active client sessions. /// @@ -358,6 +364,14 @@ namespace MediaBrowser.Model.ApiClient /// Task. Task SendBrowseCommandAsync(string sessionId, string itemId, string itemName, string itemType, string context); + /// + /// Sends the playstate command async. + /// + /// The session id. + /// The request. + /// Task. + Task SendPlaystateCommandAsync(string sessionId, PlayStateRequest request); + /// /// Sends the play command async. /// diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index da01da475..14313d421 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -72,9 +72,10 @@ + - + diff --git a/MediaBrowser.Model/Querying/UserQuery.cs b/MediaBrowser.Model/Querying/UserQuery.cs new file mode 100644 index 000000000..48dbd30aa --- /dev/null +++ b/MediaBrowser.Model/Querying/UserQuery.cs @@ -0,0 +1,9 @@ + +namespace MediaBrowser.Model.Querying +{ + public class UserQuery + { + public bool? IsHidden { get; set; } + public bool? IsDisabled { get; set; } + } +} diff --git a/MediaBrowser.Model/Session/PlaystateRequest.cs b/MediaBrowser.Model/Session/PlaystateCommand.cs similarity index 66% rename from MediaBrowser.Model/Session/PlaystateRequest.cs rename to MediaBrowser.Model/Session/PlaystateCommand.cs index 78551060f..01f7068ac 100644 --- a/MediaBrowser.Model/Session/PlaystateRequest.cs +++ b/MediaBrowser.Model/Session/PlaystateCommand.cs @@ -1,25 +1,6 @@  namespace MediaBrowser.Model.Session { - /// - /// Class PlaystateRequest - /// - public class PlaystateRequest - { - /// - /// Gets or sets the command. - /// - /// The command. - public PlaystateCommand Command { get; set; } - - /// - /// Gets or sets the seek position. - /// Only applicable to seek commands. - /// - /// The seek position. - public long? SeekPosition { get; set; } - } - /// /// Enum PlaystateCommand /// @@ -50,4 +31,11 @@ namespace MediaBrowser.Model.Session /// Seek } + + public class PlayStateRequest + { + public PlaystateCommand Command { get; set; } + + public long? SeekPosition { get; set; } + } } diff --git a/MediaBrowser.Model/Session/SessionInfoDto.cs b/MediaBrowser.Model/Session/SessionInfoDto.cs index 294e6a264..93d531806 100644 --- a/MediaBrowser.Model/Session/SessionInfoDto.cs +++ b/MediaBrowser.Model/Session/SessionInfoDto.cs @@ -22,6 +22,12 @@ namespace MediaBrowser.Model.Session /// /// The name of the user. public string UserName { get; set; } + + /// + /// Gets or sets the application version. + /// + /// The application version. + public string ApplicationVersion { get; set; } /// /// Gets or sets the type of the client. diff --git a/MediaBrowser.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs b/MediaBrowser.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs index 79ea89ac6..0aaafec83 100644 --- a/MediaBrowser.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs +++ b/MediaBrowser.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs @@ -121,7 +121,7 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks } } } - + /// /// Creates the triggers that define when the task will run /// @@ -148,13 +148,15 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks var numComplete = 0; - var failHistoryPath = Path.Combine(_kernel.FFMpegManager.VideoImagesDataPath, "failures.json"); + var failHistoryPath = Path.Combine(_kernel.FFMpegManager.VideoImagesDataPath, "failures.txt"); List previouslyFailedImages; - + try { - previouslyFailedImages = _jsonSerializer.DeserializeFromFile>(failHistoryPath); + previouslyFailedImages = File.ReadAllText(failHistoryPath) + .Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries) + .ToList(); } catch (FileNotFoundException) { @@ -184,7 +186,7 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks Directory.CreateDirectory(parentPath); } - _jsonSerializer.SerializeToFile(previouslyFailedImages, failHistoryPath); + File.WriteAllText(failHistoryPath, string.Join("|", previouslyFailedImages.ToArray())); } numComplete++; diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index d9f28915a..fde1eba9d 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -94,13 +94,32 @@ namespace MediaBrowser.Server.Implementations.Session /// Logs the user activity. /// /// Type of the client. + /// The app version. /// The device id. /// Name of the device. /// The user. /// Task. + /// /// user - public Task LogConnectionActivity(string clientType, string deviceId, string deviceName, User user) + public async Task LogConnectionActivity(string clientType, string appVersion, string deviceId, string deviceName, User user) { + if (string.IsNullOrEmpty(clientType)) + { + throw new ArgumentNullException("clientType"); + } + if (string.IsNullOrEmpty(appVersion)) + { + throw new ArgumentNullException("appVersion"); + } + if (string.IsNullOrEmpty(deviceId)) + { + throw new ArgumentNullException("deviceId"); + } + if (string.IsNullOrEmpty(deviceName)) + { + throw new ArgumentNullException("deviceName"); + } + if (user != null && user.Configuration.IsDisabled) { throw new UnauthorizedAccessException(string.Format("The {0} account is currently disabled. Please consult with your administrator.", user.Name)); @@ -108,11 +127,13 @@ namespace MediaBrowser.Server.Implementations.Session var activityDate = DateTime.UtcNow; - GetConnection(clientType, deviceId, deviceName, user).LastActivityDate = activityDate; + var session = GetSessionInfo(clientType, appVersion, deviceId, deviceName, user); + + session.LastActivityDate = activityDate; if (user == null) { - return _trueTaskResult; + return session; } var lastActivityDate = user.LastActivityDate; @@ -122,50 +143,42 @@ namespace MediaBrowser.Server.Implementations.Session // Don't log in the db anymore frequently than 10 seconds if (lastActivityDate.HasValue && (activityDate - lastActivityDate.Value).TotalSeconds < 10) { - return _trueTaskResult; + return session; } // Save this directly. No need to fire off all the events for this. - return _userRepository.SaveUser(user, CancellationToken.None); + await _userRepository.SaveUser(user, CancellationToken.None).ConfigureAwait(false); + + return session; } /// /// Updates the now playing item id. /// - /// The user. - /// Type of the client. - /// The device id. - /// Name of the device. + /// The session. /// The item. /// if set to true [is paused]. /// The current position ticks. - private void UpdateNowPlayingItemId(User user, string clientType, string deviceId, string deviceName, BaseItem item, bool isPaused, long? currentPositionTicks = null) + private void UpdateNowPlayingItem(SessionInfo session, 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; + session.IsPaused = isPaused; + session.NowPlayingPositionTicks = currentPositionTicks; + session.NowPlayingItem = item; + session.LastActivityDate = DateTime.UtcNow; } /// /// Removes the now playing item id. /// - /// The user. - /// Type of the client. - /// The device id. - /// Name of the device. + /// The session. /// The item. - private void RemoveNowPlayingItemId(User user, string clientType, string deviceId, string deviceName, BaseItem item) + private void RemoveNowPlayingItem(SessionInfo session, BaseItem item) { - var conn = GetConnection(clientType, deviceId, deviceName, user); - - if (conn.NowPlayingItem != null && conn.NowPlayingItem.Id == item.Id) + if (session.NowPlayingItem != null && session.NowPlayingItem.Id == item.Id) { - conn.NowPlayingItem = null; - conn.NowPlayingPositionTicks = null; - conn.IsPaused = null; + session.NowPlayingItem = null; + session.NowPlayingPositionTicks = null; + session.IsPaused = null; } } @@ -173,23 +186,24 @@ namespace MediaBrowser.Server.Implementations.Session /// Gets the connection. /// /// Type of the client. + /// The app version. /// The device id. /// Name of the device. /// The user. /// SessionInfo. - private SessionInfo GetConnection(string clientType, string deviceId, string deviceName, User user) + private SessionInfo GetSessionInfo(string clientType, string appVersion, string deviceId, string deviceName, User user) { - var key = clientType + deviceId; + var key = clientType + deviceId + appVersion; var connection = _activeConnections.GetOrAdd(key, keyName => new SessionInfo { Client = clientType, DeviceId = deviceId, + ApplicationVersion = appVersion, Id = Guid.NewGuid() }); connection.DeviceName = deviceName; - connection.User = user; return connection; @@ -198,28 +212,25 @@ namespace MediaBrowser.Server.Implementations.Session /// /// Used to report that playback has started for an item /// - /// The user. /// The item. - /// Type of the client. - /// The device id. - /// Name of the device. - /// - /// - public async Task OnPlaybackStart(User user, BaseItem item, string clientType, string deviceId, string deviceName) + /// The session id. + /// Task. + /// + public async Task OnPlaybackStart(BaseItem item, Guid sessionId) { - if (user == null) - { - throw new ArgumentNullException(); - } if (item == null) { throw new ArgumentNullException(); } - UpdateNowPlayingItemId(user, clientType, deviceId, deviceName, item, false); + var session = Sessions.First(i => i.Id.Equals(sessionId)); + + UpdateNowPlayingItem(session, item, false); var key = item.GetUserDataKey(); + var user = session.User; + var data = _userDataRepository.GetUserData(user.Id, key); data.PlayCount++; @@ -248,27 +259,25 @@ namespace MediaBrowser.Server.Implementations.Session /// The item. /// The position ticks. /// if set to true [is paused]. - /// Type of the client. - /// The device id. - /// Name of the device. + /// The session id. /// Task. /// /// - public async Task OnPlaybackProgress(User user, BaseItem item, long? positionTicks, bool isPaused, string clientType, string deviceId, string deviceName) + public async Task OnPlaybackProgress(BaseItem item, long? positionTicks, bool isPaused, Guid sessionId) { - if (user == null) - { - throw new ArgumentNullException(); - } if (item == null) { throw new ArgumentNullException(); } - UpdateNowPlayingItemId(user, clientType, deviceId, deviceName, item, isPaused, positionTicks); + var session = Sessions.First(i => i.Id.Equals(sessionId)); + + UpdateNowPlayingItem(session, item, isPaused, positionTicks); var key = item.GetUserDataKey(); + var user = session.User; + if (positionTicks.HasValue) { var data = _userDataRepository.GetUserData(user.Id, key); @@ -282,36 +291,33 @@ namespace MediaBrowser.Server.Implementations.Session Item = item, User = user, PlaybackPositionTicks = positionTicks + }, _logger); } /// /// Used to report that playback has ended for an item /// - /// The user. /// The item. /// The position ticks. - /// Type of the client. - /// The device id. - /// Name of the device. + /// The session id. /// Task. - /// - /// - public async Task OnPlaybackStopped(User user, BaseItem item, long? positionTicks, string clientType, string deviceId, string deviceName) + /// + public async Task OnPlaybackStopped(BaseItem item, long? positionTicks, Guid sessionId) { - if (user == null) - { - throw new ArgumentNullException(); - } if (item == null) { throw new ArgumentNullException(); } - RemoveNowPlayingItemId(user, clientType, deviceId, deviceName, item); + var session = Sessions.First(i => i.Id.Equals(sessionId)); + + RemoveNowPlayingItem(session, item); var key = item.GetUserDataKey(); + var user = session.User; + var data = _userDataRepository.GetUserData(user.Id, key); if (positionTicks.HasValue) diff --git a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs index c649fd474..d712bbc60 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs @@ -103,7 +103,7 @@ namespace MediaBrowser.Server.Implementations.Session { var item = DtoBuilder.GetItemByClientId(message.Data, _userManager, _libraryManager); - _sessionManager.OnPlaybackStart(_userManager.GetUserById(session.User.Id), item, session.Client, session.DeviceId, session.DeviceName); + _sessionManager.OnPlaybackStart(item, session.Id); } } else if (string.Equals(message.MessageType, "PlaybackProgress", StringComparison.OrdinalIgnoreCase)) @@ -130,7 +130,7 @@ namespace MediaBrowser.Server.Implementations.Session var isPaused = vals.Length > 2 && string.Equals(vals[2], "true", StringComparison.OrdinalIgnoreCase); - _sessionManager.OnPlaybackProgress(_userManager.GetUserById(session.User.Id), item, positionTicks, isPaused, session.Client, session.DeviceId, session.DeviceName); + _sessionManager.OnPlaybackProgress(item, positionTicks, isPaused, session.Id); } } else if (string.Equals(message.MessageType, "PlaybackStopped", StringComparison.OrdinalIgnoreCase)) @@ -155,7 +155,7 @@ namespace MediaBrowser.Server.Implementations.Session } } - _sessionManager.OnPlaybackStopped(_userManager.GetUserById(session.User.Id), item, positionTicks, session.Client, session.DeviceId, session.DeviceName); + _sessionManager.OnPlaybackStopped(item, positionTicks, session.Id); } } diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index 89aaec4b2..184354a22 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -512,6 +512,12 @@ namespace MediaBrowser.WebDashboard.Api var newLineBytes = Encoding.UTF8.GetBytes(Environment.NewLine); + var versionString = string.Format("window.dashboardVersion='{0}';", GetType().Assembly.GetName().Version); + var versionBytes = Encoding.UTF8.GetBytes(versionString); + + await memoryStream.WriteAsync(versionBytes, 0, versionBytes.Length).ConfigureAwait(false); + await memoryStream.WriteAsync(newLineBytes, 0, newLineBytes.Length).ConfigureAwait(false); + await AppendResource(memoryStream, "thirdparty/autoNumeric.js", newLineBytes).ConfigureAwait(false); await AppendResource(memoryStream, "thirdparty/html5slider.js", newLineBytes).ConfigureAwait(false); diff --git a/MediaBrowser.WebDashboard/ApiClient.js b/MediaBrowser.WebDashboard/ApiClient.js index 8b602610a..3117b4b00 100644 --- a/MediaBrowser.WebDashboard/ApiClient.js +++ b/MediaBrowser.WebDashboard/ApiClient.js @@ -10,8 +10,9 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) { * @param {String} serverHostName * @param {String} serverPortNumber * @param {String} clientName + * @param {String} applicationVersion */ - return function (serverProtocol, serverHostName, serverPortNumber, clientName) { + return function (serverProtocol, serverHostName, serverPortNumber, clientName, applicationVersion) { if (!serverProtocol) { throw new Error("Must supply a serverProtocol, e.g. http:"); @@ -120,7 +121,7 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) { if (clientName) { - var auth = 'MediaBrowser Client="' + clientName + '", Device="' + deviceName + '", DeviceId="' + deviceId + '"'; + var auth = 'MediaBrowser Client="' + clientName + '", Device="' + deviceName + '", DeviceId="' + deviceId + '", Version="' + applicationVersion + '"'; if (currentUserId) { auth += ', UserId="' + currentUserId + '"'; @@ -3277,11 +3278,11 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) { /** * Provides a friendly way to create an api client instance using information from the browser's current url */ -MediaBrowser.ApiClient.create = function (clientName) { +MediaBrowser.ApiClient.create = function (clientName, applicationVersion) { var loc = window.location; - return new MediaBrowser.ApiClient(loc.protocol, loc.hostname, loc.port, clientName); + return new MediaBrowser.ApiClient(loc.protocol, loc.hostname, loc.port, clientName, applicationVersion); }; /** diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config index a1b6ec005..bb1b35f24 100644 --- a/MediaBrowser.WebDashboard/packages.config +++ b/MediaBrowser.WebDashboard/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file