using MediaBrowser.Model.Dto; using MediaBrowser.Model.Session; using System; using System.Collections.Generic; using System.Linq; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Threading; namespace MediaBrowser.Controller.Session { /// /// Class SessionInfo /// public class SessionInfo : IDisposable { private ISessionManager _sessionManager; private readonly ILogger _logger; public SessionInfo(ISessionManager sessionManager, ILogger logger) { _sessionManager = sessionManager; _logger = logger; AdditionalUsers = new SessionUserInfo[] { }; PlayState = new PlayerStateInfo(); } public PlayerStateInfo PlayState { get; set; } public SessionUserInfo[] AdditionalUsers { get; set; } public ClientCapabilities Capabilities { get; set; } /// /// Gets or sets the remote end point. /// /// The remote end point. public string RemoteEndPoint { get; set; } /// /// Gets or sets the playable media types. /// /// The playable media types. public string[] PlayableMediaTypes { get { if (Capabilities == null) { return new string[] { }; } return Capabilities.PlayableMediaTypes; } } /// /// Gets or sets the id. /// /// The id. public string Id { get; set; } /// /// Gets or sets the user id. /// /// The user id. public Guid? UserId { get; set; } /// /// Gets or sets the username. /// /// The username. public string UserName { get; set; } /// /// Gets or sets the type of the client. /// /// The type of the client. public string Client { get; set; } /// /// Gets or sets the last activity date. /// /// The last activity date. public DateTime LastActivityDate { get; set; } /// /// Gets or sets the last playback check in. /// /// The last playback check in. public DateTime LastPlaybackCheckIn { get; set; } /// /// Gets or sets the name of the device. /// /// The name of the device. public string DeviceName { get; set; } /// /// Gets or sets the name of the now viewing item. /// /// The name of the now viewing item. public BaseItemDto NowViewingItem { get; set; } /// /// Gets or sets the now playing item. /// /// The now playing item. public BaseItemDto NowPlayingItem { get; set; } public BaseItem FullNowPlayingItem { get; set; } /// /// Gets or sets the device id. /// /// The device id. public string DeviceId { get; set; } /// /// Gets or sets the application version. /// /// The application version. public string ApplicationVersion { get; set; } /// /// Gets or sets the session controller. /// /// The session controller. public ISessionController SessionController { get; set; } /// /// Gets or sets the application icon URL. /// /// The application icon URL. public string AppIconUrl { get; set; } /// /// Gets or sets the supported commands. /// /// The supported commands. public string[] SupportedCommands { get { if (Capabilities == null) { return new string[] { }; } return Capabilities.SupportedCommands; } } public TranscodingInfo TranscodingInfo { get; set; } /// /// Gets a value indicating whether this instance is active. /// /// true if this instance is active; otherwise, false. public bool IsActive { get { if (SessionController != null) { return SessionController.IsSessionActive; } return (DateTime.UtcNow - LastActivityDate).TotalMinutes <= 10; } } public bool SupportsMediaControl { get { if (Capabilities == null || !Capabilities.SupportsMediaControl) { return false; } if (SessionController != null) { return SessionController.SupportsMediaControl; } return false; } } public bool ContainsUser(string userId) { return ContainsUser(new Guid(userId)); } public bool ContainsUser(Guid userId) { return (UserId ?? Guid.Empty) == userId || AdditionalUsers.Any(i => userId == new Guid(i.UserId)); } private readonly object _progressLock = new object(); private ITimer _progressTimer; private PlaybackProgressInfo _lastProgressInfo; public void StartAutomaticProgress(ITimerFactory timerFactory, PlaybackProgressInfo progressInfo) { if (_disposed) { return; } lock (_progressLock) { _lastProgressInfo = progressInfo; if (_progressTimer == null) { _progressTimer = timerFactory.Create(OnProgressTimerCallback, null, 1000, 1000); } else { _progressTimer.Change(1000, 1000); } } } // 1 second private const long ProgressIncrement = 10000000; private async void OnProgressTimerCallback(object state) { if (_disposed) { return; } var progressInfo = _lastProgressInfo; if (progressInfo == null) { return; } if (progressInfo.IsPaused) { return; } var positionTicks = progressInfo.PositionTicks ?? 0; if (positionTicks < 0) { positionTicks = 0; } var newPositionTicks = positionTicks + ProgressIncrement; var item = progressInfo.Item; long? runtimeTicks = item == null ? null : item.RunTimeTicks; // Don't report beyond the runtime if (runtimeTicks.HasValue && newPositionTicks >= runtimeTicks.Value) { return; } progressInfo.PositionTicks = newPositionTicks; try { await _sessionManager.OnPlaybackProgress(progressInfo, true).ConfigureAwait(false); } catch (Exception ex) { _logger.ErrorException("Error reporting playback progress", ex); } } public void StopAutomaticProgress() { lock (_progressLock) { if (_progressTimer != null) { _progressTimer.Dispose(); _progressTimer = null; } _lastProgressInfo = null; } } private bool _disposed = false; public void Dispose() { _disposed = true; StopAutomaticProgress(); _sessionManager = null; } } }