From 0b5019ed1b8c7624eae27aebe715132e07f8a417 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 17 Apr 2017 14:40:42 -0400 Subject: [PATCH] support automatic progress reporting --- .../Session/SessionManager.cs | 8 +- .../Session/SessionInfo.cs | 95 ++++++++++++++++++- 2 files changed, 98 insertions(+), 5 deletions(-) diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 05a240cea..ed0a47121 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -197,6 +197,8 @@ namespace Emby.Server.Implementations.Session _logger.ErrorException("Error disposing session controller", ex); } } + + info.Dispose(); } /// @@ -415,7 +417,7 @@ namespace Emby.Server.Implementations.Session if (!_activeConnections.TryGetValue(key, out sessionInfo)) { - sessionInfo = new SessionInfo + sessionInfo = new SessionInfo(this, _logger) { Client = appName, DeviceId = deviceId, @@ -609,6 +611,7 @@ namespace Emby.Server.Implementations.Session ClearTranscodingInfo(session.DeviceId); } + session.StopAutomaticProgress(); session.QueueableMediaTypes = info.QueueableMediaTypes; var users = GetUsers(session); @@ -727,6 +730,7 @@ namespace Emby.Server.Implementations.Session }, _logger); + session.StartAutomaticProgress(_timerFactory, info); StartIdleCheckTimer(); } @@ -788,6 +792,8 @@ namespace Emby.Server.Implementations.Session var session = GetSession(info.SessionId); + session.StopAutomaticProgress(); + var libraryItem = string.IsNullOrWhiteSpace(info.ItemId) ? null : GetNowPlayingItem(session, info.ItemId); diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs index 343b15a04..6cb6f4bb6 100644 --- a/MediaBrowser.Controller/Session/SessionInfo.cs +++ b/MediaBrowser.Controller/Session/SessionInfo.cs @@ -4,16 +4,23 @@ 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 + public class SessionInfo : IDisposable { - public SessionInfo() + private ISessionManager _sessionManager; + private readonly ILogger _logger; + + public SessionInfo(ISessionManager sessionManager, ILogger logger) { + _sessionManager = sessionManager; + _logger = logger; QueueableMediaTypes = new List(); AdditionalUsers = new List(); @@ -21,7 +28,7 @@ namespace MediaBrowser.Controller.Session } public PlayerStateInfo PlayState { get; set; } - + public List AdditionalUsers { get; set; } public ClientCapabilities Capabilities { get; set; } @@ -133,7 +140,7 @@ namespace MediaBrowser.Controller.Session /// /// The application icon URL. public string AppIconUrl { get; set; } - + /// /// Gets or sets the supported commands. /// @@ -196,5 +203,85 @@ namespace MediaBrowser.Controller.Session { 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) + { + lock (_progressLock) + { + _lastProgressInfo = progressInfo; + + if (_progressTimer != null) + { + return; + } + + _progressTimer = timerFactory.Create(OnProgressTimerCallback, null, 1000, 1000); + } + } + + // 1 second + private const long ProgressIncrement = 10000000; + + private async void OnProgressTimerCallback(object state) + { + var progressInfo = _lastProgressInfo; + if (progressInfo == null) + { + return; + } + if (progressInfo.IsPaused) + { + return; + } + var positionTicks = progressInfo.PositionTicks ?? 0; + if (positionTicks <= 0) + { + return; + } + + 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).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; + } + } + + public void Dispose() + { + StopAutomaticProgress(); + _sessionManager = null; + } } }