chromecast updates

This commit is contained in:
Luke Pulverenti
2014-04-06 13:53:23 -04:00
parent 241c43e9a1
commit c60103df64
69 changed files with 1027 additions and 360 deletions

View File

@@ -1,8 +1,12 @@
using MediaBrowser.Common.Events;
using System.IO;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Session;
@@ -42,6 +46,8 @@ namespace MediaBrowser.Server.Implementations.Session
private readonly ILibraryManager _libraryManager;
private readonly IUserManager _userManager;
private readonly IMusicManager _musicManager;
private readonly IDtoService _dtoService;
private readonly IImageProcessor _imageProcessor;
/// <summary>
/// Gets or sets the configuration manager.
@@ -68,6 +74,10 @@ namespace MediaBrowser.Server.Implementations.Session
/// </summary>
public event EventHandler<PlaybackStopEventArgs> PlaybackStopped;
public event EventHandler<SessionEventArgs> SessionStarted;
public event EventHandler<SessionEventArgs> SessionEnded;
private IEnumerable<ISessionControllerFactory> _sessionFactories = new List<ISessionControllerFactory>();
private readonly SemaphoreSlim _sessionLock = new SemaphoreSlim(1, 1);
@@ -80,7 +90,7 @@ namespace MediaBrowser.Server.Implementations.Session
/// <param name="logger">The logger.</param>
/// <param name="userRepository">The user repository.</param>
/// <param name="libraryManager">The library manager.</param>
public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager)
public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager, IDtoService dtoService, IImageProcessor imageProcessor)
{
_userDataRepository = userDataRepository;
_configurationManager = configurationManager;
@@ -89,6 +99,8 @@ namespace MediaBrowser.Server.Implementations.Session
_libraryManager = libraryManager;
_userManager = userManager;
_musicManager = musicManager;
_dtoService = dtoService;
_imageProcessor = imageProcessor;
}
/// <summary>
@@ -109,6 +121,47 @@ namespace MediaBrowser.Server.Implementations.Session
get { return _activeConnections.Values.OrderByDescending(c => c.LastActivityDate).ToList(); }
}
private void OnSessionStarted(SessionInfo info)
{
EventHelper.QueueEventIfNotNull(SessionStarted, this, new SessionEventArgs
{
SessionInfo = info
}, _logger);
}
private async void OnSessionEnded(SessionInfo info)
{
try
{
await SendSessionEndedNotification(info, CancellationToken.None).ConfigureAwait(false);
}
catch (Exception ex)
{
_logger.ErrorException("Error in SendSessionEndedNotification", ex);
}
EventHelper.QueueEventIfNotNull(SessionEnded, this, new SessionEventArgs
{
SessionInfo = info
}, _logger);
var disposable = info.SessionController as IDisposable;
if (disposable != null)
{
try
{
disposable.Dispose();
}
catch (Exception ex)
{
_logger.ErrorException("Error disposing session controller", ex);
}
}
}
/// <summary>
/// Logs the user activity.
/// </summary>
@@ -194,19 +247,7 @@ namespace MediaBrowser.Server.Implementations.Session
if (_activeConnections.TryRemove(key, out removed))
{
var disposable = removed.SessionController as IDisposable;
if (disposable != null)
{
try
{
disposable.Dispose();
}
catch (Exception ex)
{
_logger.ErrorException("Error disposing session controller", ex);
}
}
OnSessionEnded(removed);
}
}
finally
@@ -222,11 +263,9 @@ namespace MediaBrowser.Server.Implementations.Session
/// <param name="item">The item.</param>
/// <param name="mediaSourceId">The media version identifier.</param>
/// <param name="isPaused">if set to <c>true</c> [is paused].</param>
/// <param name="isMuted">if set to <c>true</c> [is muted].</param>
/// <param name="currentPositionTicks">The current position ticks.</param>
private void UpdateNowPlayingItem(SessionInfo session, BaseItem item, string mediaSourceId, bool isPaused, bool isMuted, long? currentPositionTicks = null)
private void UpdateNowPlayingItem(SessionInfo session, BaseItem item, string mediaSourceId, bool isPaused, long? currentPositionTicks = null)
{
session.IsMuted = isMuted;
session.IsPaused = isPaused;
session.NowPlayingPositionTicks = currentPositionTicks;
session.NowPlayingItem = item;
@@ -291,12 +330,19 @@ namespace MediaBrowser.Server.Implementations.Session
try
{
var connection = _activeConnections.GetOrAdd(key, keyName => new SessionInfo
var connection = _activeConnections.GetOrAdd(key, keyName =>
{
Client = clientType,
DeviceId = deviceId,
ApplicationVersion = appVersion,
Id = Guid.NewGuid()
var sessionInfo = new SessionInfo
{
Client = clientType,
DeviceId = deviceId,
ApplicationVersion = appVersion,
Id = Guid.NewGuid()
};
OnSessionStarted(sessionInfo);
return sessionInfo;
});
connection.DeviceName = deviceName;
@@ -372,11 +418,14 @@ namespace MediaBrowser.Server.Implementations.Session
var mediaSourceId = GetMediaSourceId(item, info.MediaSourceId);
UpdateNowPlayingItem(session, item, mediaSourceId, false, false);
UpdateNowPlayingItem(session, item, mediaSourceId, false);
session.CanSeek = info.CanSeek;
session.QueueableMediaTypes = info.QueueableMediaTypes;
session.NowPlayingAudioStreamIndex = info.AudioStreamIndex;
session.NowPlayingSubtitleStreamIndex = info.SubtitleStreamIndex;
var key = item.GetUserDataKey();
var users = GetUsers(session);
@@ -442,7 +491,12 @@ namespace MediaBrowser.Server.Implementations.Session
var mediaSourceId = GetMediaSourceId(info.Item, info.MediaSourceId);
UpdateNowPlayingItem(session, info.Item, mediaSourceId, info.IsPaused, info.IsMuted, info.PositionTicks);
UpdateNowPlayingItem(session, info.Item, mediaSourceId, info.IsPaused, info.PositionTicks);
session.IsMuted = info.IsMuted;
session.VolumeLevel = info.VolumeLevel;
session.NowPlayingAudioStreamIndex = info.AudioStreamIndex;
session.NowPlayingSubtitleStreamIndex = info.SubtitleStreamIndex;
var key = info.Item.GetUserDataKey();
@@ -919,6 +973,27 @@ namespace MediaBrowser.Server.Implementations.Session
}
public Task SendSessionEndedNotification(SessionInfo sessionInfo, CancellationToken cancellationToken)
{
var sessions = Sessions.Where(i => i.IsActive && i.SessionController != null).ToList();
var dto = GetSessionInfoDto(sessionInfo);
var tasks = sessions.Select(session => Task.Run(async () =>
{
try
{
await session.SessionController.SendSessionEndedNotification(dto, cancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
{
_logger.ErrorException("Error in SendSessionEndedNotification.", ex);
}
}, cancellationToken));
return Task.WhenAll(tasks);
}
/// <summary>
/// Adds the additional user.
/// </summary>
@@ -1017,5 +1092,147 @@ namespace MediaBrowser.Server.Implementations.Session
session.PlayableMediaTypes = capabilities.PlayableMediaTypes;
session.SupportedCommands = capabilities.SupportedCommands;
}
public SessionInfoDto GetSessionInfoDto(SessionInfo session)
{
var dto = new SessionInfoDto
{
Client = session.Client,
DeviceId = session.DeviceId,
DeviceName = session.DeviceName,
Id = session.Id.ToString("N"),
LastActivityDate = session.LastActivityDate,
NowPlayingPositionTicks = session.NowPlayingPositionTicks,
SupportsRemoteControl = session.SupportsRemoteControl,
IsPaused = session.IsPaused,
IsMuted = session.IsMuted,
NowViewingContext = session.NowViewingContext,
NowViewingItemId = session.NowViewingItemId,
NowViewingItemName = session.NowViewingItemName,
NowViewingItemType = session.NowViewingItemType,
ApplicationVersion = session.ApplicationVersion,
CanSeek = session.CanSeek,
QueueableMediaTypes = session.QueueableMediaTypes,
PlayableMediaTypes = session.PlayableMediaTypes,
RemoteEndPoint = session.RemoteEndPoint,
AdditionalUsers = session.AdditionalUsers,
SupportedCommands = session.SupportedCommands,
NowPlayingAudioStreamIndex = session.NowPlayingAudioStreamIndex,
NowPlayingSubtitleStreamIndex = session.NowPlayingSubtitleStreamIndex,
UserName = session.UserName,
VolumeLevel = session.VolumeLevel
};
if (session.NowPlayingItem != null)
{
dto.NowPlayingItem = GetNowPlayingInfo(session.NowPlayingItem, session.NowPlayingMediaSourceId, session.NowPlayingRunTimeTicks);
}
if (session.UserId.HasValue)
{
dto.UserId = session.UserId.Value.ToString("N");
}
return dto;
}
/// <summary>
/// Converts a BaseItem to a BaseItemInfo
/// </summary>
/// <param name="item">The item.</param>
/// <param name="mediaSourceId">The media version identifier.</param>
/// <param name="nowPlayingRuntimeTicks">The now playing runtime ticks.</param>
/// <returns>BaseItemInfo.</returns>
/// <exception cref="System.ArgumentNullException">item</exception>
private BaseItemInfo GetNowPlayingInfo(BaseItem item, string mediaSourceId, long? nowPlayingRuntimeTicks)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
var info = new BaseItemInfo
{
Id = GetDtoId(item),
Name = item.Name,
MediaType = item.MediaType,
Type = item.GetClientTypeName(),
RunTimeTicks = nowPlayingRuntimeTicks,
MediaSourceId = mediaSourceId
};
info.PrimaryImageTag = GetImageCacheTag(item, ImageType.Primary);
var backropItem = item.HasImage(ImageType.Backdrop) ? item : null;
var thumbItem = item.HasImage(ImageType.Thumb) ? item : null;
if (thumbItem == null)
{
var episode = item as Episode;
if (episode != null)
{
var series = episode.Series;
if (series != null && series.HasImage(ImageType.Thumb))
{
thumbItem = series;
}
}
}
if (backropItem == null)
{
var episode = item as Episode;
if (episode != null)
{
var series = episode.Series;
if (series != null && series.HasImage(ImageType.Backdrop))
{
backropItem = series;
}
}
}
if (thumbItem == null)
{
thumbItem = item.Parents.FirstOrDefault(i => i.HasImage(ImageType.Thumb));
}
if (thumbItem != null)
{
info.ThumbImageTag = GetImageCacheTag(thumbItem, ImageType.Thumb);
info.ThumbItemId = GetDtoId(thumbItem);
}
if (thumbItem != null)
{
info.BackdropImageTag = GetImageCacheTag(backropItem, ImageType.Backdrop);
info.BackdropItemId = GetDtoId(backropItem);
}
return info;
}
private Guid? GetImageCacheTag(BaseItem item, ImageType type)
{
try
{
return _imageProcessor.GetImageCacheTag(item, type);
}
catch (Exception ex)
{
_logger.ErrorException("Error getting {0} image info", ex, type);
return null;
}
}
private string GetDtoId(BaseItem item)
{
return _dtoService.GetDtoId(item);
}
}
}

View File

@@ -1,4 +1,5 @@
using MediaBrowser.Common.Net;
using System.Globalization;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Session;
@@ -187,6 +188,8 @@ namespace MediaBrowser.Server.Implementations.Session
return result;
}
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
/// <summary>
/// Reports the playback start.
/// </summary>
@@ -228,6 +231,16 @@ namespace MediaBrowser.Server.Implementations.Session
info.MediaSourceId = vals[3];
}
if (vals.Length > 4 && !string.IsNullOrWhiteSpace(vals[4]))
{
info.AudioStreamIndex = int.Parse(vals[4], _usCulture);
}
if (vals.Length > 5 && !string.IsNullOrWhiteSpace(vals[5]))
{
info.SubtitleStreamIndex = int.Parse(vals[5], _usCulture);
}
_sessionManager.OnPlaybackStart(info);
}
}
@@ -275,6 +288,21 @@ namespace MediaBrowser.Server.Implementations.Session
info.MediaSourceId = vals[4];
}
if (vals.Length > 5 && !string.IsNullOrWhiteSpace(vals[5]))
{
info.VolumeLevel = int.Parse(vals[5], _usCulture);
}
if (vals.Length > 5 && !string.IsNullOrWhiteSpace(vals[6]))
{
info.AudioStreamIndex = int.Parse(vals[6], _usCulture);
}
if (vals.Length > 7 && !string.IsNullOrWhiteSpace(vals[7]))
{
info.SubtitleStreamIndex = int.Parse(vals[7], _usCulture);
}
_sessionManager.OnPlaybackProgress(info);
}
}

View File

@@ -198,5 +198,17 @@ namespace MediaBrowser.Server.Implementations.Session
}, cancellationToken);
}
public Task SendSessionEndedNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken)
{
var socket = GetActiveSocket();
return socket.SendAsync(new WebSocketMessage<SessionInfoDto>
{
MessageType = "SessionEnded",
Data = sessionInfo
}, cancellationToken);
}
}
}