Display client version in the dashboard

This commit is contained in:
Luke Pulverenti 2013-07-09 12:11:16 -04:00
parent 48265fefa4
commit 66624293ac
21 changed files with 266 additions and 144 deletions

View File

@ -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);
}
}
}

View File

@ -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
{
/// <summary>
/// Gets or sets the id.
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
public Guid Id { get; set; }
/// <summary>
/// Gets or sets the position to seek to
/// </summary>
[ApiMember(Name = "SeekPosition", Description = "The position to seek to.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
public long? SeekPosition { get; set; }
/// <summary>
/// Gets or sets the play command.
/// </summary>
/// <value>The play command.</value>
[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; }
}
/// <summary>
/// Class SessionsService
/// </summary>
@ -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<PlayStateRequest>
{
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.");
}
}
/// <summary>
/// Posts the specified request.
/// </summary>

View File

@ -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));
}
/// <summary>
/// Posts the specified request.
/// </summary>
@ -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);
}
/// <summary>
@ -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);
}
/// <summary>
@ -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);
}
/// <summary>

View File

@ -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));
}
}

View File

@ -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)

View File

@ -70,7 +70,7 @@
<Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link>
</Compile>
<Compile Include="Configuration\IServerConfigurationManager.cs" />
<Compile Include="Notifications\Configuration\IServerConfigurationManager.cs" />
<Compile Include="Dto\SessionInfoDtoBuilder.cs" />
<Compile Include="Entities\Audio\MusicAlbumDisc.cs" />
<Compile Include="Entities\Audio\MusicGenre.cs" />

View File

@ -36,49 +36,42 @@ namespace MediaBrowser.Controller.Session
/// Logs the user activity.
/// </summary>
/// <param name="clientType">Type of the client.</param>
/// <param name="appVersion">The app version.</param>
/// <param name="deviceId">The device id.</param>
/// <param name="deviceName">Name of the device.</param>
/// <param name="user">The user.</param>
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException">user</exception>
Task LogConnectionActivity(string clientType, string deviceId, string deviceName, User user);
Task<SessionInfo> LogConnectionActivity(string clientType, string appVersion, string deviceId, string deviceName, User user);
/// <summary>
/// Used to report that playback has started for an item
/// </summary>
/// <param name="user">The user.</param>
/// <param name="item">The item.</param>
/// <param name="clientType">Type of the client.</param>
/// <param name="deviceId">The device id.</param>
/// <param name="deviceName">Name of the device.</param>
/// <param name="sessionId">The session id.</param>
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException"></exception>
Task OnPlaybackStart(User user, BaseItem item, string clientType, string deviceId, string deviceName);
Task OnPlaybackStart(BaseItem item, Guid sessionId);
/// <summary>
/// Used to report playback progress for an item
/// </summary>
/// <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>
/// <param name="sessionId">The session id.</param>
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException"></exception>
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);
/// <summary>
/// Used to report that playback has ended for an item
/// </summary>
/// <param name="user">The user.</param>
/// <param name="item">The item.</param>
/// <param name="positionTicks">The position ticks.</param>
/// <param name="clientType">Type of the client.</param>
/// <param name="deviceId">The device id.</param>
/// <param name="deviceName">Name of the device.</param>
/// <param name="sessionId">The session id.</param>
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException"></exception>
Task OnPlaybackStopped(User user, BaseItem item, long? positionTicks, string clientType, string deviceId, string deviceName);
Task OnPlaybackStopped(BaseItem item, long? positionTicks, Guid sessionId);
}
}

View File

@ -101,6 +101,12 @@ namespace MediaBrowser.Controller.Session
/// <value>The web socket.</value>
public List<IWebSocketConnection> WebSockets { get; set; }
/// <summary>
/// Gets or sets the application version.
/// </summary>
/// <value>The application version.</value>
public string ApplicationVersion { get; set; }
/// <summary>
/// Gets a value indicating whether this instance is active.
/// </summary>

View File

@ -268,6 +268,9 @@
<Compile Include="..\MediaBrowser.Model\Querying\ThemeSongsResult.cs">
<Link>Querying\ThemeSongsResult.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Querying\UserQuery.cs">
<Link>Querying\UserQuery.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Search\SearchHint.cs">
<Link>Search\SearchHint.cs</Link>
</Compile>
@ -286,8 +289,8 @@
<Compile Include="..\MediaBrowser.Model\Session\PlayRequest.cs">
<Link>Session\PlayRequest.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Session\PlaystateRequest.cs">
<Link>Session\PlaystateRequest.cs</Link>
<Compile Include="..\MediaBrowser.Model\Session\PlaystateCommand.cs">
<Link>Session\PlaystateCommand.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Session\SessionInfoDto.cs">
<Link>Session\SessionInfoDto.cs</Link>

View File

@ -100,6 +100,12 @@ namespace MediaBrowser.Model.ApiClient
/// <returns>Task{UserDto[]}.</returns>
Task<UserDto[]> GetUsersAsync();
/// <summary>
/// Gets the public users async.
/// </summary>
/// <returns>Task{UserDto[]}.</returns>
Task<UserDto[]> GetPublicUsersAsync();
/// <summary>
/// Gets active client sessions.
/// </summary>
@ -358,6 +364,14 @@ namespace MediaBrowser.Model.ApiClient
/// <returns>Task.</returns>
Task SendBrowseCommandAsync(string sessionId, string itemId, string itemName, string itemType, string context);
/// <summary>
/// Sends the playstate command async.
/// </summary>
/// <param name="sessionId">The session id.</param>
/// <param name="request">The request.</param>
/// <returns>Task.</returns>
Task SendPlaystateCommandAsync(string sessionId, PlayStateRequest request);
/// <summary>
/// Sends the play command async.
/// </summary>

View File

@ -72,9 +72,10 @@
<Compile Include="Entities\BaseItemInfo.cs" />
<Compile Include="Querying\NextUpQuery.cs" />
<Compile Include="Querying\SimilarItemsQuery.cs" />
<Compile Include="Querying\UserQuery.cs" />
<Compile Include="Session\BrowseRequest.cs" />
<Compile Include="Session\PlayRequest.cs" />
<Compile Include="Session\PlaystateRequest.cs" />
<Compile Include="Session\PlaystateCommand.cs" />
<Compile Include="Entities\ImageDownloadOptions.cs" />
<Compile Include="Logging\ILogManager.cs" />
<Compile Include="MediaInfo\BlurayDiscInfo.cs" />

View File

@ -0,0 +1,9 @@

namespace MediaBrowser.Model.Querying
{
public class UserQuery
{
public bool? IsHidden { get; set; }
public bool? IsDisabled { get; set; }
}
}

View File

@ -1,25 +1,6 @@

namespace MediaBrowser.Model.Session
{
/// <summary>
/// Class PlaystateRequest
/// </summary>
public class PlaystateRequest
{
/// <summary>
/// Gets or sets the command.
/// </summary>
/// <value>The command.</value>
public PlaystateCommand Command { get; set; }
/// <summary>
/// Gets or sets the seek position.
/// Only applicable to seek commands.
/// </summary>
/// <value>The seek position.</value>
public long? SeekPosition { get; set; }
}
/// <summary>
/// Enum PlaystateCommand
/// </summary>
@ -50,4 +31,11 @@ namespace MediaBrowser.Model.Session
/// </summary>
Seek
}
public class PlayStateRequest
{
public PlaystateCommand Command { get; set; }
public long? SeekPosition { get; set; }
}
}

View File

@ -22,6 +22,12 @@ namespace MediaBrowser.Model.Session
/// </summary>
/// <value>The name of the user.</value>
public string UserName { get; set; }
/// <summary>
/// Gets or sets the application version.
/// </summary>
/// <value>The application version.</value>
public string ApplicationVersion { get; set; }
/// <summary>
/// Gets or sets the type of the client.

View File

@ -121,7 +121,7 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks
}
}
}
/// <summary>
/// Creates the triggers that define when the task will run
/// </summary>
@ -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<string> previouslyFailedImages;
try
{
previouslyFailedImages = _jsonSerializer.DeserializeFromFile<List<string>>(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++;

View File

@ -94,13 +94,32 @@ namespace MediaBrowser.Server.Implementations.Session
/// Logs the user activity.
/// </summary>
/// <param name="clientType">Type of the client.</param>
/// <param name="appVersion">The app version.</param>
/// <param name="deviceId">The device id.</param>
/// <param name="deviceName">Name of the device.</param>
/// <param name="user">The user.</param>
/// <returns>Task.</returns>
/// <exception cref="System.UnauthorizedAccessException"></exception>
/// <exception cref="System.ArgumentNullException">user</exception>
public Task LogConnectionActivity(string clientType, string deviceId, string deviceName, User user)
public async Task<SessionInfo> 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;
}
/// <summary>
/// Updates the now playing item id.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="clientType">Type of the client.</param>
/// <param name="deviceId">The device id.</param>
/// <param name="deviceName">Name of the device.</param>
/// <param name="session">The session.</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, 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;
}
/// <summary>
/// Removes the now playing item id.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="clientType">Type of the client.</param>
/// <param name="deviceId">The device id.</param>
/// <param name="deviceName">Name of the device.</param>
/// <param name="session">The session.</param>
/// <param name="item">The item.</param>
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.
/// </summary>
/// <param name="clientType">Type of the client.</param>
/// <param name="appVersion">The app version.</param>
/// <param name="deviceId">The device id.</param>
/// <param name="deviceName">Name of the device.</param>
/// <param name="user">The user.</param>
/// <returns>SessionInfo.</returns>
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
/// <summary>
/// Used to report that playback has started for an item
/// </summary>
/// <param name="user">The user.</param>
/// <param name="item">The item.</param>
/// <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>
public async Task OnPlaybackStart(User user, BaseItem item, string clientType, string deviceId, string deviceName)
/// <param name="sessionId">The session id.</param>
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException"></exception>
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
/// <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>
/// <param name="sessionId">The session id.</param>
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException">
/// </exception>
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);
}
/// <summary>
/// Used to report that playback has ended for an item
/// </summary>
/// <param name="user">The user.</param>
/// <param name="item">The item.</param>
/// <param name="positionTicks">The position ticks.</param>
/// <param name="clientType">Type of the client.</param>
/// <param name="deviceId">The device id.</param>
/// <param name="deviceName">Name of the device.</param>
/// <param name="sessionId">The session id.</param>
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException">
/// </exception>
public async Task OnPlaybackStopped(User user, BaseItem item, long? positionTicks, string clientType, string deviceId, string deviceName)
/// <exception cref="System.ArgumentNullException"></exception>
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)

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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);
};
/**

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MediaBrowser.ApiClient.Javascript" version="3.0.139" targetFramework="net45" />
<package id="MediaBrowser.ApiClient.Javascript" version="3.0.141" targetFramework="net45" />
<package id="ServiceStack.Common" version="3.9.54" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.9.54" targetFramework="net45" />
</packages>