瀏覽代碼

integrate development from v1

herby2212 1 年之前
父節點
當前提交
db5c2f738e

+ 85 - 4
Emby.Server.Implementations/Session/SessionManager.cs

@@ -19,6 +19,7 @@ using MediaBrowser.Common.Events;
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller.Authentication;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Devices;
 using MediaBrowser.Controller.Drawing;
 using MediaBrowser.Controller.Dto;
@@ -48,6 +49,7 @@ namespace Emby.Server.Implementations.Session
     public sealed class SessionManager : ISessionManager, IAsyncDisposable
     {
         private readonly IUserDataManager _userDataManager;
+        private readonly IServerConfigurationManager _config;
         private readonly ILogger<SessionManager> _logger;
         private readonly IEventManager _eventManager;
         private readonly ILibraryManager _libraryManager;
@@ -63,6 +65,7 @@ namespace Emby.Server.Implementations.Session
             = new(StringComparer.OrdinalIgnoreCase);
 
         private Timer _idleTimer;
+        private Timer _inactiveTimer;
 
         private DtoOptions _itemInfoDtoOptions;
         private bool _disposed = false;
@@ -71,6 +74,7 @@ namespace Emby.Server.Implementations.Session
             ILogger<SessionManager> logger,
             IEventManager eventManager,
             IUserDataManager userDataManager,
+            IServerConfigurationManager config,
             ILibraryManager libraryManager,
             IUserManager userManager,
             IMusicManager musicManager,
@@ -84,6 +88,7 @@ namespace Emby.Server.Implementations.Session
             _logger = logger;
             _eventManager = eventManager;
             _userDataManager = userDataManager;
+            _config = config;
             _libraryManager = libraryManager;
             _userManager = userManager;
             _musicManager = musicManager;
@@ -369,6 +374,15 @@ namespace Emby.Server.Implementations.Session
                 session.LastPlaybackCheckIn = DateTime.UtcNow;
             }
 
+            if (info.IsPaused && session.LastPausedDate is null)
+            {
+                session.LastPausedDate = DateTime.UtcNow;
+            }
+            else if (!info.IsPaused)
+            {
+                session.LastPausedDate = null;
+            }
+
             session.PlayState.IsPaused = info.IsPaused;
             session.PlayState.PositionTicks = info.PositionTicks;
             session.PlayState.MediaSourceId = info.MediaSourceId;
@@ -536,9 +550,18 @@ namespace Emby.Server.Implementations.Session
             return users;
         }
 
-        private void StartIdleCheckTimer()
+        private void StartCheckTimers()
         {
             _idleTimer ??= new Timer(CheckForIdlePlayback, null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
+
+            if (_config.Configuration.InactiveSessionThreshold > 0)
+            {
+                _inactiveTimer ??= new Timer(CheckForInactiveSteams, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
+            }
+            else
+            {
+                StopInactiveCheckTimer();
+            }
         }
 
         private void StopIdleCheckTimer()
@@ -550,6 +573,15 @@ namespace Emby.Server.Implementations.Session
             }
         }
 
+        private void StopInactiveCheckTimer()
+        {
+            if (_inactiveTimer is not null)
+            {
+                _inactiveTimer.Dispose();
+                _inactiveTimer = null;
+            }
+        }
+
         private async void CheckForIdlePlayback(object state)
         {
             var playingSessions = Sessions.Where(i => i.NowPlayingItem is not null)
@@ -585,10 +617,53 @@ namespace Emby.Server.Implementations.Session
                 playingSessions = Sessions.Where(i => i.NowPlayingItem is not null)
                     .ToList();
             }
+            else
+            {
+                StopIdleCheckTimer();
+            }
+        }
+
+        private async void CheckForInactiveSteams(object state)
+        {
+            var pausedSessions = Sessions.Where(i =>
+                    i.NowPlayingItem is not null
+                    && i.PlayState.IsPaused
+                    && i.LastPausedDate is not null)
+                .ToList();
+
+            if (pausedSessions.Count > 0)
+            {
+                var inactiveSessions = pausedSessions.Where(i => (DateTime.UtcNow - i.LastPausedDate).Value.TotalMinutes > _config.Configuration.InactiveSessionThreshold).ToList();
+
+                foreach (var session in inactiveSessions)
+                {
+                    _logger.LogDebug("Session {Session} has been inactive for {InactiveTime} minutes. Stopping it.", session.Id, _config.Configuration.InactiveSessionThreshold);
+
+                    try
+                    {
+                        await SendPlaystateCommand(
+                            session.Id,
+                            session.Id,
+                            new PlaystateRequest()
+                            {
+                                Command = PlaystateCommand.Stop,
+                                ControllingUserId = session.UserId.ToString(),
+                                SeekPositionTicks = session.PlayState?.PositionTicks
+                            },
+                            CancellationToken.None).ConfigureAwait(true);
+                    }
+                    catch (Exception ex)
+                    {
+                        _logger.LogDebug(ex, "Error calling SendPlaystateCommand for stopping inactive session {Session}.", session.Id);
+                    }
+                }
+            }
 
+            var playingSessions = Sessions.Where(i => i.NowPlayingItem is not null)
+                .ToList();
             if (playingSessions.Count == 0)
             {
-                StopIdleCheckTimer();
+                StopInactiveCheckTimer();
             }
         }
 
@@ -668,7 +743,7 @@ namespace Emby.Server.Implementations.Session
                 eventArgs,
                 _logger);
 
-            StartIdleCheckTimer();
+            StartCheckTimers();
         }
 
         /// <summary>
@@ -762,7 +837,7 @@ namespace Emby.Server.Implementations.Session
                 session.StartAutomaticProgress(info);
             }
 
-            StartIdleCheckTimer();
+            StartCheckTimers();
         }
 
         private void OnPlaybackProgress(User user, BaseItem item, PlaybackProgressInfo info)
@@ -1798,6 +1873,12 @@ namespace Emby.Server.Implementations.Session
                 _idleTimer = null;
             }
 
+            if(_inactiveTimer is not null)
+            {
+                await _inactiveTimer.DisposeAsync().ConfigureAwait(false);
+                _inactiveTimer = null;
+            }
+
             await _shutdownCallback.DisposeAsync().ConfigureAwait(false);
 
             _deviceManager.DeviceOptionsUpdated -= OnDeviceManagerDeviceOptionsUpdated;

+ 6 - 0
MediaBrowser.Controller/Session/SessionInfo.cs

@@ -109,6 +109,12 @@ namespace MediaBrowser.Controller.Session
         /// <value>The last playback check in.</value>
         public DateTime LastPlaybackCheckIn { get; set; }
 
+        /// <summary>
+        /// Gets or sets the last paused date.
+        /// </summary>
+        /// <value>The last paused date.</value>
+        public DateTime? LastPausedDate { get; set; }
+
         /// <summary>
         /// Gets or sets the name of the device.
         /// </summary>

+ 7 - 0
MediaBrowser.Model/Configuration/ServerConfiguration.cs

@@ -157,6 +157,13 @@ namespace MediaBrowser.Model.Configuration
         /// <value>The remaining time in minutes.</value>
         public int MaxAudiobookResume { get; set; } = 5;
 
+        /// <summary>
+        /// Gets or sets the threshold in minutes after a inactive session gets closed automatically.
+        /// If set to 0 the check for inactive sessions gets disabled.
+        /// </summary>
+        /// <value>The close inactive session threshold in minutes. 0 to disable.</value>
+        public int InactiveSessionThreshold { get; set; } = 10;
+
         /// <summary>
         /// Gets or sets the delay in seconds that we will wait after a file system change to try and discover what has been added/removed
         /// Some delay is necessary with some items because their creation is not atomic.  It involves the creation of several