Browse Source

Review logging and minor changes in SyncPlay

Ionut Andrei Oanca 4 years ago
parent
commit
a3ca36cb54

+ 45 - 38
Emby.Server.Implementations/SyncPlay/GroupController.cs

@@ -28,7 +28,12 @@ namespace Emby.Server.Implementations.SyncPlay
         /// <summary>
         /// The logger.
         /// </summary>
-        private readonly ILogger _logger;
+        private readonly ILogger<GroupController> _logger;
+
+        /// <summary>
+        /// The logger factory.
+        /// </summary>
+        private readonly ILoggerFactory _loggerFactory;
 
         /// <summary>
         /// The user manager.
@@ -45,6 +50,12 @@ namespace Emby.Server.Implementations.SyncPlay
         /// </summary>
         private readonly ILibraryManager _libraryManager;
 
+        /// <summary>
+        /// The participants, or members of the group.
+        /// </summary>
+        private readonly Dictionary<string, GroupMember> _participants =
+            new Dictionary<string, GroupMember>(StringComparer.OrdinalIgnoreCase);
+
         /// <summary>
         /// Internal group state.
         /// </summary>
@@ -54,37 +65,41 @@ namespace Emby.Server.Implementations.SyncPlay
         /// <summary>
         /// Initializes a new instance of the <see cref="GroupController" /> class.
         /// </summary>
-        /// <param name="logger">The logger.</param>
+        /// <param name="loggerFactory">The logger factory.</param>
         /// <param name="userManager">The user manager.</param>
         /// <param name="sessionManager">The session manager.</param>
         /// <param name="libraryManager">The library manager.</param>
         public GroupController(
-            ILogger logger,
+            ILoggerFactory loggerFactory,
             IUserManager userManager,
             ISessionManager sessionManager,
             ILibraryManager libraryManager)
         {
-            _logger = logger;
+            _loggerFactory = loggerFactory;
             _userManager = userManager;
             _sessionManager = sessionManager;
             _libraryManager = libraryManager;
+            _logger = loggerFactory.CreateLogger<GroupController>();
 
-            _state = new IdleGroupState(_logger);
+            _state = new IdleGroupState(loggerFactory);
         }
 
         /// <summary>
         /// Gets the default ping value used for sessions.
         /// </summary>
+        /// <value>The default ping.</value>
         public long DefaultPing { get; } = 500;
 
         /// <summary>
         /// Gets the maximum time offset error accepted for dates reported by clients, in milliseconds.
         /// </summary>
+        /// <value>The maximum time offset error.</value>
         public long TimeSyncOffset { get; } = 2000;
 
         /// <summary>
         /// Gets the maximum offset error accepted for position reported by clients, in milliseconds.
         /// </summary>
+        /// <value>The maximum offset error.</value>
         public long MaxPlaybackOffset { get; } = 500;
 
         /// <summary>
@@ -123,24 +138,16 @@ namespace Emby.Server.Implementations.SyncPlay
         /// <value>The last activity.</value>
         public DateTime LastActivity { get; set; }
 
-        /// <summary>
-        /// Gets the participants.
-        /// </summary>
-        /// <value>The participants, or members of the group.</value>
-        public Dictionary<string, GroupMember> Participants { get; } =
-            new Dictionary<string, GroupMember>(StringComparer.OrdinalIgnoreCase);
-
         /// <summary>
         /// Adds the session to the group.
         /// </summary>
         /// <param name="session">The session.</param>
         private void AddSession(SessionInfo session)
         {
-            Participants.TryAdd(
+            _participants.TryAdd(
                 session.Id,
-                new GroupMember
+                new GroupMember(session)
                 {
-                    Session = session,
                     Ping = DefaultPing,
                     IsBuffering = false
                 });
@@ -152,7 +159,7 @@ namespace Emby.Server.Implementations.SyncPlay
         /// <param name="session">The session.</param>
         private void RemoveSession(SessionInfo session)
         {
-            Participants.Remove(session.Id);
+            _participants.Remove(session.Id);
         }
 
         /// <summary>
@@ -166,14 +173,14 @@ namespace Emby.Server.Implementations.SyncPlay
             return type switch
             {
                 SyncPlayBroadcastType.CurrentSession => new SessionInfo[] { from },
-                SyncPlayBroadcastType.AllGroup => Participants
+                SyncPlayBroadcastType.AllGroup => _participants
                     .Values
                     .Select(session => session.Session),
-                SyncPlayBroadcastType.AllExceptCurrentSession => Participants
+                SyncPlayBroadcastType.AllExceptCurrentSession => _participants
                     .Values
                     .Select(session => session.Session)
                     .Where(session => !session.Id.Equals(from.Id, StringComparison.OrdinalIgnoreCase)),
-                SyncPlayBroadcastType.AllReady => Participants
+                SyncPlayBroadcastType.AllReady => _participants
                     .Values
                     .Where(session => !session.IsBuffering)
                     .Select(session => session.Session),
@@ -204,7 +211,7 @@ namespace Emby.Server.Implementations.SyncPlay
         private bool HasAccessToQueue(User user, IReadOnlyList<Guid> queue)
         {
             // Check if queue is empty.
-            if (!queue?.Any() ?? true)
+            if (queue == null || queue.Count == 0)
             {
                 return true;
             }
@@ -229,13 +236,13 @@ namespace Emby.Server.Implementations.SyncPlay
         private bool AllUsersHaveAccessToQueue(IReadOnlyList<Guid> queue)
         {
             // Check if queue is empty.
-            if (!queue?.Any() ?? true)
+            if (queue == null || queue.Count == 0)
             {
                 return true;
             }
 
             // Get list of users.
-            var users = Participants
+            var users = _participants
                 .Values
                 .Select(participant => _userManager.GetUserById(participant.Session.UserId));
 
@@ -247,7 +254,7 @@ namespace Emby.Server.Implementations.SyncPlay
         }
 
         /// <inheritdoc />
-        public bool IsGroupEmpty() => Participants.Count == 0;
+        public bool IsGroupEmpty() => _participants.Count == 0;
 
         /// <inheritdoc />
         public void CreateGroup(SessionInfo session, NewGroupRequest request, CancellationToken cancellationToken)
@@ -268,8 +275,8 @@ namespace Emby.Server.Implementations.SyncPlay
                 RunTimeTicks = session.FullNowPlayingItem.RunTimeTicks ?? 0;
                 PositionTicks = session.PlayState.PositionTicks ?? 0;
 
-                // Mantain playstate.
-                var waitingState = new WaitingGroupState(_logger)
+                // Maintain playstate.
+                var waitingState = new WaitingGroupState(_loggerFactory)
                 {
                     ResumePlaying = !session.PlayState.IsPaused
                 };
@@ -281,7 +288,7 @@ namespace Emby.Server.Implementations.SyncPlay
 
             _state.SessionJoined(this, _state.Type, session, cancellationToken);
 
-            _logger.LogInformation("InitGroup: {SessionId} created group {GroupId}.", session.Id, GroupId.ToString());
+            _logger.LogInformation("Session {SessionId} created group {GroupId}.", session.Id, GroupId.ToString());
         }
 
         /// <inheritdoc />
@@ -297,7 +304,7 @@ namespace Emby.Server.Implementations.SyncPlay
 
             _state.SessionJoined(this, _state.Type, session, cancellationToken);
 
-            _logger.LogInformation("SessionJoin: {SessionId} joined group {GroupId}.", session.Id, GroupId.ToString());
+            _logger.LogInformation("Session {SessionId} joined group {GroupId}.", session.Id, GroupId.ToString());
         }
 
         /// <inheritdoc />
@@ -311,7 +318,7 @@ namespace Emby.Server.Implementations.SyncPlay
 
             _state.SessionJoined(this, _state.Type, session, cancellationToken);
 
-            _logger.LogInformation("SessionRestore: {SessionId} re-joined group {GroupId}.", session.Id, GroupId.ToString());
+            _logger.LogInformation("Session {SessionId} re-joined group {GroupId}.", session.Id, GroupId.ToString());
         }
 
         /// <inheritdoc />
@@ -327,7 +334,7 @@ namespace Emby.Server.Implementations.SyncPlay
             var updateOthers = NewSyncPlayGroupUpdate(GroupUpdateType.UserLeft, session.UserName);
             SendGroupUpdate(session, SyncPlayBroadcastType.AllExceptCurrentSession, updateOthers, cancellationToken);
 
-            _logger.LogInformation("SessionLeave: {SessionId} left group {GroupId}.", session.Id, GroupId.ToString());
+            _logger.LogInformation("Session {SessionId} left group {GroupId}.", session.Id, GroupId.ToString());
         }
 
         /// <inheritdoc />
@@ -336,14 +343,14 @@ namespace Emby.Server.Implementations.SyncPlay
             // The server's job is to maintain a consistent state for clients to reference
             // and notify clients of state changes. The actual syncing of media playback
             // happens client side. Clients are aware of the server's time and use it to sync.
-            _logger.LogInformation("HandleRequest: {SessionId} requested {RequestType}, group {GroupId} is {StateType}.", session.Id, request.Type, GroupId.ToString(), _state.Type);
+            _logger.LogInformation("Session {SessionId} requested {RequestType} in group {GroupId} that is {StateType}.", session.Id, request.Type, GroupId.ToString(), _state.Type);
             request.Apply(this, _state, session, cancellationToken);
         }
 
         /// <inheritdoc />
         public GroupInfoDto GetInfo()
         {
-            var participants = Participants.Values.Select(session => session.Session.UserName).Distinct().ToList();
+            var participants = _participants.Values.Select(session => session.Session.UserName).Distinct().ToList();
             return new GroupInfoDto(GroupId, GroupName, _state.Type, participants, DateTime.UtcNow);
         }
 
@@ -357,7 +364,7 @@ namespace Emby.Server.Implementations.SyncPlay
         /// <inheritdoc />
         public void SetIgnoreGroupWait(SessionInfo session, bool ignoreGroupWait)
         {
-            if (Participants.TryGetValue(session.Id, out GroupMember value))
+            if (_participants.TryGetValue(session.Id, out GroupMember value))
             {
                 value.IgnoreGroupWait = ignoreGroupWait;
             }
@@ -366,7 +373,7 @@ namespace Emby.Server.Implementations.SyncPlay
         /// <inheritdoc />
         public void SetState(IGroupState state)
         {
-            _logger.LogInformation("SetState: {GroupId} switching from {FromStateType} to {ToStateType}.", GroupId.ToString(), _state.Type, state.Type);
+            _logger.LogInformation("Group {GroupId} switching from {FromStateType} to {ToStateType}.", GroupId.ToString(), _state.Type, state.Type);
             this._state = state;
         }
 
@@ -426,7 +433,7 @@ namespace Emby.Server.Implementations.SyncPlay
         /// <inheritdoc />
         public void UpdatePing(SessionInfo session, long ping)
         {
-            if (Participants.TryGetValue(session.Id, out GroupMember value))
+            if (_participants.TryGetValue(session.Id, out GroupMember value))
             {
                 value.Ping = ping;
             }
@@ -436,7 +443,7 @@ namespace Emby.Server.Implementations.SyncPlay
         public long GetHighestPing()
         {
             long max = long.MinValue;
-            foreach (var session in Participants.Values)
+            foreach (var session in _participants.Values)
             {
                 max = Math.Max(max, session.Ping);
             }
@@ -447,7 +454,7 @@ namespace Emby.Server.Implementations.SyncPlay
         /// <inheritdoc />
         public void SetBuffering(SessionInfo session, bool isBuffering)
         {
-            if (Participants.TryGetValue(session.Id, out GroupMember value))
+            if (_participants.TryGetValue(session.Id, out GroupMember value))
             {
                 value.IsBuffering = isBuffering;
             }
@@ -456,7 +463,7 @@ namespace Emby.Server.Implementations.SyncPlay
         /// <inheritdoc />
         public void SetAllBuffering(bool isBuffering)
         {
-            foreach (var session in Participants.Values)
+            foreach (var session in _participants.Values)
             {
                 session.IsBuffering = isBuffering;
             }
@@ -465,7 +472,7 @@ namespace Emby.Server.Implementations.SyncPlay
         /// <inheritdoc />
         public bool IsBuffering()
         {
-            foreach (var session in Participants.Values)
+            foreach (var session in _participants.Values)
             {
                 if (session.IsBuffering && !session.IgnoreGroupWait)
                 {

+ 17 - 11
Emby.Server.Implementations/SyncPlay/SyncPlayManager.cs

@@ -21,6 +21,11 @@ namespace Emby.Server.Implementations.SyncPlay
         /// </summary>
         private readonly ILogger<SyncPlayManager> _logger;
 
+        /// <summary>
+        /// The logger factory.
+        /// </summary>
+        private readonly ILoggerFactory _loggerFactory;
+
         /// <summary>
         /// The user manager.
         /// </summary>
@@ -58,20 +63,21 @@ namespace Emby.Server.Implementations.SyncPlay
         /// <summary>
         /// Initializes a new instance of the <see cref="SyncPlayManager" /> class.
         /// </summary>
-        /// <param name="logger">The logger.</param>
+        /// <param name="loggerFactory">The logger factory.</param>
         /// <param name="userManager">The user manager.</param>
         /// <param name="sessionManager">The session manager.</param>
         /// <param name="libraryManager">The library manager.</param>
         public SyncPlayManager(
-            ILogger<SyncPlayManager> logger,
+            ILoggerFactory loggerFactory,
             IUserManager userManager,
             ISessionManager sessionManager,
             ILibraryManager libraryManager)
         {
-            _logger = logger;
+            _loggerFactory = loggerFactory;
             _userManager = userManager;
             _sessionManager = sessionManager;
             _libraryManager = libraryManager;
+            _logger = loggerFactory.CreateLogger<SyncPlayManager>();
             _sessionManager.SessionStarted += OnSessionManagerSessionStarted;
         }
 
@@ -98,7 +104,7 @@ namespace Emby.Server.Implementations.SyncPlay
                     LeaveGroup(session, cancellationToken);
                 }
 
-                var group = new GroupController(_logger, _userManager, _sessionManager, _libraryManager);
+                var group = new GroupController(_loggerFactory, _userManager, _sessionManager, _libraryManager);
                 _groups[group.GroupId] = group;
 
                 AddSessionToGroup(session, group);
@@ -123,7 +129,7 @@ namespace Emby.Server.Implementations.SyncPlay
 
                 if (group == null)
                 {
-                    _logger.LogWarning("JoinGroup: {SessionId} tried to join group {GroupId} that does not exist.", session.Id, groupId);
+                    _logger.LogWarning("Session {SessionId} tried to join group {GroupId} that does not exist.", session.Id, groupId);
 
                     var error = new GroupUpdate<string>(Guid.Empty, GroupUpdateType.GroupDoesNotExist, string.Empty);
                     _sessionManager.SendSyncPlayGroupUpdate(session, error, CancellationToken.None);
@@ -132,7 +138,7 @@ namespace Emby.Server.Implementations.SyncPlay
 
                 if (!group.HasAccessToPlayQueue(user))
                 {
-                    _logger.LogWarning("JoinGroup: {SessionId} does not have access to some content from the playing queue of group {GroupId}.", session.Id, group.GroupId.ToString());
+                    _logger.LogWarning("Session {SessionId} tried to join group {GroupId} but does not have access to some content of the playing queue.", session.Id, group.GroupId.ToString());
 
                     var error = new GroupUpdate<string>(group.GroupId, GroupUpdateType.LibraryAccessDenied, string.Empty);
                     _sessionManager.SendSyncPlayGroupUpdate(session, error, CancellationToken.None);
@@ -171,7 +177,7 @@ namespace Emby.Server.Implementations.SyncPlay
 
                 if (group == null)
                 {
-                    _logger.LogWarning("LeaveGroup: {SessionId} does not belong to any group.", session.Id);
+                    _logger.LogWarning("Session {SessionId} does not belong to any group.", session.Id);
 
                     var error = new GroupUpdate<string>(Guid.Empty, GroupUpdateType.NotInGroup, string.Empty);
                     _sessionManager.SendSyncPlayGroupUpdate(session, error, CancellationToken.None);
@@ -183,7 +189,7 @@ namespace Emby.Server.Implementations.SyncPlay
 
                 if (group.IsGroupEmpty())
                 {
-                    _logger.LogInformation("LeaveGroup: removing empty group {GroupId}.", group.GroupId);
+                    _logger.LogInformation("Group {GroupId} is empty, removing it.", group.GroupId);
                     _groups.Remove(group.GroupId, out _);
                 }
             }
@@ -225,7 +231,7 @@ namespace Emby.Server.Implementations.SyncPlay
 
                 if (group == null)
                 {
-                    _logger.LogWarning("HandleRequest: {SessionId} does not belong to any group.", session.Id);
+                    _logger.LogWarning("Session {SessionId} does not belong to any group.", session.Id);
 
                     var error = new GroupUpdate<string>(Guid.Empty, GroupUpdateType.NotInGroup, string.Empty);
                     _sessionManager.SendSyncPlayGroupUpdate(session, error, CancellationToken.None);
@@ -370,7 +376,7 @@ namespace Emby.Server.Implementations.SyncPlay
 
             if (user.SyncPlayAccess == SyncPlayAccess.None)
             {
-                _logger.LogWarning("IsRequestValid: {SessionId} does not have access to SyncPlay. Requested {RequestType}.", session.Id, requestType);
+                _logger.LogWarning("Session {SessionId} requested {RequestType} but does not have access to SyncPlay.", session.Id, requestType);
 
                 // TODO: rename to a more generic error. Next PR will fix this.
                 var error = new GroupUpdate<string>(Guid.Empty, GroupUpdateType.JoinGroupDenied, string.Empty);
@@ -380,7 +386,7 @@ namespace Emby.Server.Implementations.SyncPlay
 
             if (requestType.Equals(GroupRequestType.NewGroup) && user.SyncPlayAccess != SyncPlayAccess.CreateAndJoinGroups)
             {
-                _logger.LogWarning("IsRequestValid: {SessionId} does not have permission to create groups.", session.Id);
+                _logger.LogWarning("Session {SessionId} does not have permission to create groups.", session.Id);
 
                 var error = new GroupUpdate<string>(Guid.Empty, GroupUpdateType.CreateGroupDenied, string.Empty);
                 _sessionManager.SendSyncPlayGroupUpdate(session, error, CancellationToken.None);

+ 11 - 2
MediaBrowser.Controller/SyncPlay/GroupMember.cs

@@ -8,10 +8,19 @@ namespace MediaBrowser.Controller.SyncPlay
     public class GroupMember
     {
         /// <summary>
-        /// Gets or sets the session.
+        /// Initializes a new instance of the <see cref="GroupMember"/> class.
+        /// </summary>
+        /// <param name="session">The session.</param>
+        public GroupMember(SessionInfo session)
+        {
+            Session = session;
+        }
+
+        /// <summary>
+        /// Gets the session.
         /// </summary>
         /// <value>The session.</value>
-        public SessionInfo Session { get; set; }
+        public SessionInfo Session { get; }
 
         /// <summary>
         /// Gets or sets the ping, in milliseconds.

+ 17 - 11
MediaBrowser.Controller/SyncPlay/GroupStates/AbstractGroupState.cs

@@ -14,22 +14,28 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
     /// </remarks>
     public abstract class AbstractGroupState : IGroupState
     {
+        /// <summary>
+        /// The logger.
+        /// </summary>
+        private readonly ILogger<AbstractGroupState> _logger;
+
         /// <summary>
         /// Initializes a new instance of the <see cref="AbstractGroupState"/> class.
         /// </summary>
-        /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
-        protected AbstractGroupState(ILogger logger)
+        /// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param>
+        protected AbstractGroupState(ILoggerFactory loggerFactory)
         {
-            Logger = logger;
+            LoggerFactory = loggerFactory;
+            _logger = loggerFactory.CreateLogger<AbstractGroupState>();
         }
 
         /// <inheritdoc />
         public abstract GroupStateType Type { get; }
 
         /// <summary>
-        /// Gets the logger.
+        /// Gets the logger factory.
         /// </summary>
-        protected ILogger Logger { get; }
+        protected ILoggerFactory LoggerFactory { get; }
 
         /// <inheritdoc />
         public abstract void SessionJoined(IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken);
@@ -52,7 +58,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
         /// <inheritdoc />
         public virtual void HandleRequest(IGroupStateContext context, GroupStateType prevState, SetPlaylistItemGroupRequest request, SessionInfo session, CancellationToken cancellationToken)
         {
-            var waitingState = new WaitingGroupState(Logger);
+            var waitingState = new WaitingGroupState(LoggerFactory);
             context.SetState(waitingState);
             waitingState.HandleRequest(context, Type, request, session, cancellationToken);
         }
@@ -68,9 +74,9 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
 
             if (playingItemRemoved && !context.PlayQueue.IsItemPlaying())
             {
-                Logger.LogDebug("HandleRequest: {RequestType} in group {GroupId}, play queue is empty.", request.Type, context.GroupId.ToString());
+                _logger.LogDebug("Play queue in group {GroupId} is now empty.", context.GroupId.ToString());
 
-                IGroupState idleState = new IdleGroupState(Logger);
+                IGroupState idleState = new IdleGroupState(LoggerFactory);
                 context.SetState(idleState);
                 var stopRequest = new StopGroupRequest();
                 idleState.HandleRequest(context, Type, stopRequest, session, cancellationToken);
@@ -84,7 +90,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
 
             if (!result)
             {
-                Logger.LogError("HandleRequest: {RequestType} in group {GroupId}, unable to move item in play queue.", request.Type, context.GroupId.ToString());
+                _logger.LogError("Unable to move item in group {GroupId}.", context.GroupId.ToString());
                 return;
             }
 
@@ -100,7 +106,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
 
             if (!result)
             {
-                Logger.LogError("HandleRequest: {RequestType} in group {GroupId}, unable to add items to play queue.", request.Type, context.GroupId.ToString());
+                _logger.LogError("Unable to add items to play queue in group {GroupId}.", context.GroupId.ToString());
                 return;
             }
 
@@ -210,7 +216,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
 
         private void UnhandledRequest(IGroupPlaybackRequest request)
         {
-            Logger.LogWarning("HandleRequest: unhandled {RequestType} request in {StateType} state.", request.Type, Type);
+            _logger.LogWarning("Unhandled request of type {RequestType} in {StateType} state.", request.Type, Type);
         }
     }
 }

+ 13 - 8
MediaBrowser.Controller/SyncPlay/GroupStates/IdleGroupState.cs

@@ -14,14 +14,19 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
     /// </remarks>
     public class IdleGroupState : AbstractGroupState
     {
+        /// <summary>
+        /// The logger.
+        /// </summary>
+        private readonly ILogger<IdleGroupState> _logger;
+
         /// <summary>
         /// Initializes a new instance of the <see cref="IdleGroupState"/> class.
         /// </summary>
-        /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
-        public IdleGroupState(ILogger logger)
-            : base(logger)
+        /// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param>
+        public IdleGroupState(ILoggerFactory loggerFactory)
+            : base(loggerFactory)
         {
-            // Do nothing.
+            _logger = LoggerFactory.CreateLogger<IdleGroupState>();
         }
 
         /// <inheritdoc />
@@ -43,7 +48,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
         public override void HandleRequest(IGroupStateContext context, GroupStateType prevState, PlayGroupRequest request, SessionInfo session, CancellationToken cancellationToken)
         {
             // Change state.
-            var waitingState = new WaitingGroupState(Logger);
+            var waitingState = new WaitingGroupState(LoggerFactory);
             context.SetState(waitingState);
             waitingState.HandleRequest(context, Type, request, session, cancellationToken);
         }
@@ -52,7 +57,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
         public override void HandleRequest(IGroupStateContext context, GroupStateType prevState, UnpauseGroupRequest request, SessionInfo session, CancellationToken cancellationToken)
         {
             // Change state.
-            var waitingState = new WaitingGroupState(Logger);
+            var waitingState = new WaitingGroupState(LoggerFactory);
             context.SetState(waitingState);
             waitingState.HandleRequest(context, Type, request, session, cancellationToken);
         }
@@ -91,7 +96,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
         public override void HandleRequest(IGroupStateContext context, GroupStateType prevState, NextTrackGroupRequest request, SessionInfo session, CancellationToken cancellationToken)
         {
             // Change state.
-            var waitingState = new WaitingGroupState(Logger);
+            var waitingState = new WaitingGroupState(LoggerFactory);
             context.SetState(waitingState);
             waitingState.HandleRequest(context, Type, request, session, cancellationToken);
         }
@@ -100,7 +105,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
         public override void HandleRequest(IGroupStateContext context, GroupStateType prevState, PreviousTrackGroupRequest request, SessionInfo session, CancellationToken cancellationToken)
         {
             // Change state.
-            var waitingState = new WaitingGroupState(Logger);
+            var waitingState = new WaitingGroupState(LoggerFactory);
             context.SetState(waitingState);
             waitingState.HandleRequest(context, Type, request, session, cancellationToken);
         }

+ 17 - 12
MediaBrowser.Controller/SyncPlay/GroupStates/PausedGroupState.cs

@@ -15,14 +15,19 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
     /// </remarks>
     public class PausedGroupState : AbstractGroupState
     {
+        /// <summary>
+        /// The logger.
+        /// </summary>
+        private readonly ILogger<PausedGroupState> _logger;
+
         /// <summary>
         /// Initializes a new instance of the <see cref="PausedGroupState"/> class.
         /// </summary>
-        /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
-        public PausedGroupState(ILogger logger)
-            : base(logger)
+        /// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param>
+        public PausedGroupState(ILoggerFactory loggerFactory)
+            : base(loggerFactory)
         {
-            // Do nothing.
+            _logger = LoggerFactory.CreateLogger<PausedGroupState>();
         }
 
         /// <inheritdoc />
@@ -32,7 +37,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
         public override void SessionJoined(IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
         {
             // Wait for session to be ready.
-            var waitingState = new WaitingGroupState(Logger);
+            var waitingState = new WaitingGroupState(LoggerFactory);
             context.SetState(waitingState);
             waitingState.SessionJoined(context, Type, session, cancellationToken);
         }
@@ -47,7 +52,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
         public override void HandleRequest(IGroupStateContext context, GroupStateType prevState, PlayGroupRequest request, SessionInfo session, CancellationToken cancellationToken)
         {
             // Change state.
-            var waitingState = new WaitingGroupState(Logger);
+            var waitingState = new WaitingGroupState(LoggerFactory);
             context.SetState(waitingState);
             waitingState.HandleRequest(context, Type, request, session, cancellationToken);
         }
@@ -56,7 +61,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
         public override void HandleRequest(IGroupStateContext context, GroupStateType prevState, UnpauseGroupRequest request, SessionInfo session, CancellationToken cancellationToken)
         {
             // Change state.
-            var playingState = new PlayingGroupState(Logger);
+            var playingState = new PlayingGroupState(LoggerFactory);
             context.SetState(playingState);
             playingState.HandleRequest(context, Type, request, session, cancellationToken);
         }
@@ -96,7 +101,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
         public override void HandleRequest(IGroupStateContext context, GroupStateType prevState, StopGroupRequest request, SessionInfo session, CancellationToken cancellationToken)
         {
             // Change state.
-            var idleState = new IdleGroupState(Logger);
+            var idleState = new IdleGroupState(LoggerFactory);
             context.SetState(idleState);
             idleState.HandleRequest(context, Type, request, session, cancellationToken);
         }
@@ -105,7 +110,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
         public override void HandleRequest(IGroupStateContext context, GroupStateType prevState, SeekGroupRequest request, SessionInfo session, CancellationToken cancellationToken)
         {
             // Change state.
-            var waitingState = new WaitingGroupState(Logger);
+            var waitingState = new WaitingGroupState(LoggerFactory);
             context.SetState(waitingState);
             waitingState.HandleRequest(context, Type, request, session, cancellationToken);
         }
@@ -114,7 +119,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
         public override void HandleRequest(IGroupStateContext context, GroupStateType prevState, BufferGroupRequest request, SessionInfo session, CancellationToken cancellationToken)
         {
             // Change state.
-            var waitingState = new WaitingGroupState(Logger);
+            var waitingState = new WaitingGroupState(LoggerFactory);
             context.SetState(waitingState);
             waitingState.HandleRequest(context, Type, request, session, cancellationToken);
         }
@@ -143,7 +148,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
         public override void HandleRequest(IGroupStateContext context, GroupStateType prevState, NextTrackGroupRequest request, SessionInfo session, CancellationToken cancellationToken)
         {
             // Change state.
-            var waitingState = new WaitingGroupState(Logger);
+            var waitingState = new WaitingGroupState(LoggerFactory);
             context.SetState(waitingState);
             waitingState.HandleRequest(context, Type, request, session, cancellationToken);
         }
@@ -152,7 +157,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
         public override void HandleRequest(IGroupStateContext context, GroupStateType prevState, PreviousTrackGroupRequest request, SessionInfo session, CancellationToken cancellationToken)
         {
             // Change state.
-            var waitingState = new WaitingGroupState(Logger);
+            var waitingState = new WaitingGroupState(LoggerFactory);
             context.SetState(waitingState);
             waitingState.HandleRequest(context, Type, request, session, cancellationToken);
         }

+ 17 - 12
MediaBrowser.Controller/SyncPlay/GroupStates/PlayingGroupState.cs

@@ -15,14 +15,19 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
     /// </remarks>
     public class PlayingGroupState : AbstractGroupState
     {
+        /// <summary>
+        /// The logger.
+        /// </summary>
+        private readonly ILogger<PlayingGroupState> _logger;
+
         /// <summary>
         /// Initializes a new instance of the <see cref="PlayingGroupState"/> class.
         /// </summary>
-        /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
-        public PlayingGroupState(ILogger logger)
-            : base(logger)
+        /// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param>
+        public PlayingGroupState(ILoggerFactory loggerFactory)
+            : base(loggerFactory)
         {
-            // Do nothing.
+            _logger = LoggerFactory.CreateLogger<PlayingGroupState>();
         }
 
         /// <inheritdoc />
@@ -37,7 +42,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
         public override void SessionJoined(IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
         {
             // Wait for session to be ready.
-            var waitingState = new WaitingGroupState(Logger);
+            var waitingState = new WaitingGroupState(LoggerFactory);
             context.SetState(waitingState);
             waitingState.SessionJoined(context, Type, session, cancellationToken);
         }
@@ -52,7 +57,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
         public override void HandleRequest(IGroupStateContext context, GroupStateType prevState, PlayGroupRequest request, SessionInfo session, CancellationToken cancellationToken)
         {
             // Change state.
-            var waitingState = new WaitingGroupState(Logger);
+            var waitingState = new WaitingGroupState(LoggerFactory);
             context.SetState(waitingState);
             waitingState.HandleRequest(context, Type, request, session, cancellationToken);
         }
@@ -89,7 +94,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
         public override void HandleRequest(IGroupStateContext context, GroupStateType prevState, PauseGroupRequest request, SessionInfo session, CancellationToken cancellationToken)
         {
             // Change state.
-            var pausedState = new PausedGroupState(Logger);
+            var pausedState = new PausedGroupState(LoggerFactory);
             context.SetState(pausedState);
             pausedState.HandleRequest(context, Type, request, session, cancellationToken);
         }
@@ -98,7 +103,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
         public override void HandleRequest(IGroupStateContext context, GroupStateType prevState, StopGroupRequest request, SessionInfo session, CancellationToken cancellationToken)
         {
             // Change state.
-            var idleState = new IdleGroupState(Logger);
+            var idleState = new IdleGroupState(LoggerFactory);
             context.SetState(idleState);
             idleState.HandleRequest(context, Type, request, session, cancellationToken);
         }
@@ -107,7 +112,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
         public override void HandleRequest(IGroupStateContext context, GroupStateType prevState, SeekGroupRequest request, SessionInfo session, CancellationToken cancellationToken)
         {
             // Change state.
-            var waitingState = new WaitingGroupState(Logger);
+            var waitingState = new WaitingGroupState(LoggerFactory);
             context.SetState(waitingState);
             waitingState.HandleRequest(context, Type, request, session, cancellationToken);
         }
@@ -121,7 +126,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
             }
 
             // Change state.
-            var waitingState = new WaitingGroupState(Logger);
+            var waitingState = new WaitingGroupState(LoggerFactory);
             context.SetState(waitingState);
             waitingState.HandleRequest(context, Type, request, session, cancellationToken);
         }
@@ -146,7 +151,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
         public override void HandleRequest(IGroupStateContext context, GroupStateType prevState, NextTrackGroupRequest request, SessionInfo session, CancellationToken cancellationToken)
         {
             // Change state.
-            var waitingState = new WaitingGroupState(Logger);
+            var waitingState = new WaitingGroupState(LoggerFactory);
             context.SetState(waitingState);
             waitingState.HandleRequest(context, Type, request, session, cancellationToken);
         }
@@ -155,7 +160,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
         public override void HandleRequest(IGroupStateContext context, GroupStateType prevState, PreviousTrackGroupRequest request, SessionInfo session, CancellationToken cancellationToken)
         {
             // Change state.
-            var waitingState = new WaitingGroupState(Logger);
+            var waitingState = new WaitingGroupState(LoggerFactory);
             context.SetState(waitingState);
             waitingState.HandleRequest(context, Type, request, session, cancellationToken);
         }

+ 54 - 49
MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs

@@ -15,14 +15,19 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
     /// </remarks>
     public class WaitingGroupState : AbstractGroupState
     {
+        /// <summary>
+        /// The logger.
+        /// </summary>
+        private readonly ILogger<WaitingGroupState> _logger;
+
         /// <summary>
         /// Initializes a new instance of the <see cref="WaitingGroupState"/> class.
         /// </summary>
-        /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
-        public WaitingGroupState(ILogger logger)
-            : base(logger)
+        /// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param>
+        public WaitingGroupState(ILoggerFactory loggerFactory)
+            : base(loggerFactory)
         {
-            // Do nothing.
+            _logger = LoggerFactory.CreateLogger<WaitingGroupState>();
         }
 
         /// <inheritdoc />
@@ -97,21 +102,21 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
             {
                 if (ResumePlaying)
                 {
+                    _logger.LogDebug("Session {SessionId} left group {GroupId}, notifying others to resume.", session.Id, context.GroupId.ToString());
+
                     // Client, that was buffering, left the group.
-                    var playingState = new PlayingGroupState(Logger);
+                    var playingState = new PlayingGroupState(LoggerFactory);
                     context.SetState(playingState);
                     var unpauseRequest = new UnpauseGroupRequest();
                     playingState.HandleRequest(context, Type, unpauseRequest, session, cancellationToken);
-
-                    Logger.LogDebug("SessionLeaving: {SessionId} left group {GroupId}, notifying others to resume.", session.Id, context.GroupId.ToString());
                 }
                 else
                 {
+                    _logger.LogDebug("Session {SessionId} left group {GroupId}, returning to previous state.", session.Id, context.GroupId.ToString());
+
                     // Group is ready, returning to previous state.
-                    var pausedState = new PausedGroupState(Logger);
+                    var pausedState = new PausedGroupState(LoggerFactory);
                     context.SetState(pausedState);
-
-                    Logger.LogDebug("SessionLeaving: {SessionId} left group {GroupId}, returning to previous state.", session.Id, context.GroupId.ToString());
                 }
             }
         }
@@ -131,13 +136,13 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
             var setQueueStatus = context.SetPlayQueue(request.PlayingQueue, request.PlayingItemPosition, request.StartPositionTicks);
             if (!setQueueStatus)
             {
-                Logger.LogError("HandleRequest: {RequestType} in group {GroupId}, unable to set playing queue.", request.Type, context.GroupId.ToString());
+                _logger.LogError("Unable to set playing queue in group {GroupId}.", context.GroupId.ToString());
 
                 // Ignore request and return to previous state.
                 IGroupState newState = prevState switch {
-                    GroupStateType.Playing => new PlayingGroupState(Logger),
-                    GroupStateType.Paused => new PausedGroupState(Logger),
-                    _ => new IdleGroupState(Logger)
+                    GroupStateType.Playing => new PlayingGroupState(LoggerFactory),
+                    GroupStateType.Paused => new PausedGroupState(LoggerFactory),
+                    _ => new IdleGroupState(LoggerFactory)
                 };
 
                 context.SetState(newState);
@@ -151,7 +156,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
             // Reset status of sessions and await for all Ready events.
             context.SetAllBuffering(true);
 
-            Logger.LogDebug("HandleRequest: {RequestType} in group {GroupId}, {SessionId} set a new play queue.", request.Type, context.GroupId.ToString(), session.Id);
+            _logger.LogDebug("Session {SessionId} set a new play queue in group {GroupId}.", session.Id, context.GroupId.ToString());
         }
 
         /// <inheritdoc />
@@ -181,14 +186,14 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
                 // Return to old state.
                 IGroupState newState = prevState switch
                 {
-                    GroupStateType.Playing => new PlayingGroupState(Logger),
-                    GroupStateType.Paused => new PausedGroupState(Logger),
-                    _ => new IdleGroupState(Logger)
+                    GroupStateType.Playing => new PlayingGroupState(LoggerFactory),
+                    GroupStateType.Paused => new PausedGroupState(LoggerFactory),
+                    _ => new IdleGroupState(LoggerFactory)
                 };
 
                 context.SetState(newState);
 
-                Logger.LogDebug("HandleRequest: {RequestType} in group {GroupId}, unable to change current playing item.", request.Type, context.GroupId.ToString());
+                _logger.LogDebug("Unable to change current playing item in group {GroupId}.", context.GroupId.ToString());
             }
         }
 
@@ -214,19 +219,19 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
                 // Reset status of sessions and await for all Ready events.
                 context.SetAllBuffering(true);
 
-                Logger.LogDebug("HandleRequest: {RequestType} in group {GroupId}, waiting for all ready events.", request.Type, context.GroupId.ToString());
+                _logger.LogDebug("Group {GroupId} is waiting for all ready events.", context.GroupId.ToString());
             }
             else
             {
                 if (ResumePlaying)
                 {
-                    Logger.LogDebug("HandleRequest: {RequestType} in group {GroupId}, ignoring sessions that are not ready and forcing the playback to start.", request.Type, context.GroupId.ToString());
+                    _logger.LogDebug("Forcing the playback to start in group {GroupId}. Group-wait is disabled until next state change.", context.GroupId.ToString());
 
                     // An Unpause request is forcing the playback to start, ignoring sessions that are not ready.
                     context.SetAllBuffering(false);
 
                     // Change state.
-                    var playingState = new PlayingGroupState(Logger)
+                    var playingState = new PlayingGroupState(LoggerFactory)
                     {
                         IgnoreBuffering = true
                     };
@@ -272,7 +277,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
             }
 
             // Change state.
-            var idleState = new IdleGroupState(Logger);
+            var idleState = new IdleGroupState(LoggerFactory);
             context.SetState(idleState);
             idleState.HandleRequest(context, Type, request, session, cancellationToken);
         }
@@ -326,7 +331,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
             // Make sure the client is playing the correct item.
             if (!request.PlaylistItemId.Equals(context.PlayQueue.GetPlayingItemPlaylistId(), StringComparison.OrdinalIgnoreCase))
             {
-                Logger.LogDebug("HandleRequest: {RequestType} in group {GroupId}, {SessionId} has wrong playlist item.", request.Type, context.GroupId.ToString(), session.Id);
+                _logger.LogDebug("Session {SessionId} reported wrong playlist item in group {GroupId}.", session.Id, context.GroupId.ToString());
 
                 var playQueueUpdate = context.GetPlayQueueUpdate(PlayQueueUpdateReason.SetCurrentItem);
                 var updateSession = context.NewSyncPlayGroupUpdate(GroupUpdateType.PlayQueue, playQueueUpdate);
@@ -400,7 +405,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
             // Make sure the client is playing the correct item.
             if (!request.PlaylistItemId.Equals(context.PlayQueue.GetPlayingItemPlaylistId(), StringComparison.OrdinalIgnoreCase))
             {
-                Logger.LogDebug("HandleRequest: {RequestType} in group {GroupId}, {SessionId} has wrong playlist item.", request.Type, context.GroupId.ToString(), session.Id);
+                _logger.LogDebug("Session {SessionId} reported wrong playlist item in group {GroupId}.", session.Id, context.GroupId.ToString());
 
                 var playQueueUpdate = context.GetPlayQueueUpdate(PlayQueueUpdateReason.SetCurrentItem);
                 var update = context.NewSyncPlayGroupUpdate(GroupUpdateType.PlayQueue, playQueueUpdate);
@@ -420,7 +425,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
             var timeSyncThresholdTicks = TimeSpan.FromMilliseconds(context.TimeSyncOffset).Ticks;
             if (Math.Abs(elapsedTime.Ticks) > timeSyncThresholdTicks)
             {
-                Logger.LogWarning("HandleRequest: {RequestType} in group {GroupId}, {SessionId} is not time syncing properly. Ignoring elapsed time.", request.Type, context.GroupId.ToString(), session.Id);
+                _logger.LogWarning("Session {SessionId} is not time syncing properly. Ignoring elapsed time.", session.Id);
 
                 elapsedTime = TimeSpan.Zero;
             }
@@ -436,7 +441,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
             var delayTicks = context.PositionTicks - clientPosition.Ticks;
             var maxPlaybackOffsetTicks = TimeSpan.FromMilliseconds(context.MaxPlaybackOffset).Ticks;
 
-            Logger.LogDebug("HandleRequest: {RequestType} in group {GroupId}, {SessionId} at {PositionTicks} (delay of {Delay} seconds).", request.Type, context.GroupId.ToString(), session.Id, clientPosition, TimeSpan.FromTicks(delayTicks).TotalSeconds);
+            _logger.LogDebug("Session {SessionId} is at {PositionTicks} (delay of {Delay} seconds) in group {GroupId}.", session.Id, clientPosition, TimeSpan.FromTicks(delayTicks).TotalSeconds, context.GroupId.ToString());
 
             if (ResumePlaying)
             {
@@ -454,7 +459,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
                     // Notify relevant state change event.
                     SendGroupStateUpdate(context, request, session, cancellationToken);
 
-                    Logger.LogWarning("HandleRequest: {RequestType} in group {GroupId}, {SessionId} got lost in time, correcting.", request.Type, context.GroupId.ToString(), session.Id);
+                    _logger.LogWarning("Session {SessionId} got lost in time, correcting.", session.Id);
                     return;
                 }
 
@@ -468,7 +473,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
                     command.When = currentTime.AddTicks(delayTicks);
                     context.SendCommand(session, SyncPlayBroadcastType.CurrentSession, command, cancellationToken);
 
-                    Logger.LogInformation("HandleRequest: {RequestType} in group {GroupId}, others still buffering, {SessionId} will pause when ready in {Delay} seconds.", request.Type, context.GroupId.ToString(), session.Id, TimeSpan.FromTicks(delayTicks).TotalSeconds);
+                    _logger.LogInformation("Session {SessionId} will pause when ready in {Delay} seconds. Group {GroupId} is waiting for all ready events.", session.Id, TimeSpan.FromTicks(delayTicks).TotalSeconds, context.GroupId.ToString());
                 }
                 else
                 {
@@ -487,7 +492,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
 
                         context.SendCommand(session, filter, command, cancellationToken);
 
-                        Logger.LogInformation("HandleRequest: {RequestType} in group {GroupId}, {SessionId} is recovering, notifying others to resume in {Delay} seconds.", request.Type, context.GroupId.ToString(), session.Id, TimeSpan.FromTicks(delayTicks).TotalSeconds);
+                        _logger.LogInformation("Session {SessionId} is recovering, group {GroupId} will resume in {Delay} seconds.", session.Id, context.GroupId.ToString(), TimeSpan.FromTicks(delayTicks).TotalSeconds);
                     }
                     else
                     {
@@ -500,11 +505,11 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
                         var command = context.NewSyncPlayCommand(SendCommandType.Unpause);
                         context.SendCommand(session, SyncPlayBroadcastType.AllGroup, command, cancellationToken);
 
-                        Logger.LogWarning("HandleRequest: {RequestType} in group {GroupId}, {SessionId} resumed playback but did not update others in time. {Delay} seconds to recover.", request.Type, context.GroupId.ToString(), session.Id, TimeSpan.FromTicks(delayTicks).TotalSeconds);
+                        _logger.LogWarning("Session {SessionId} resumed playback, group {GroupId} has {Delay} seconds to recover.", session.Id, context.GroupId.ToString(), TimeSpan.FromTicks(delayTicks).TotalSeconds);
                     }
 
                     // Change state.
-                    var playingState = new PlayingGroupState(Logger);
+                    var playingState = new PlayingGroupState(LoggerFactory);
                     context.SetState(playingState);
                     playingState.HandleRequest(context, Type, request, session, cancellationToken);
                 }
@@ -523,7 +528,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
                     // Notify relevant state change event.
                     SendGroupStateUpdate(context, request, session, cancellationToken);
 
-                    Logger.LogWarning("HandleRequest: {RequestType} in group {GroupId}, {SessionId} is seeking to wrong position, correcting.", request.Type, context.GroupId.ToString(), session.Id);
+                    _logger.LogWarning("Session {SessionId} is seeking to wrong position, correcting.", session.Id);
                     return;
                 }
                 else
@@ -534,8 +539,10 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
 
                 if (!context.IsBuffering())
                 {
+                    _logger.LogDebug("Session {SessionId} is ready, group {GroupId} is ready.", session.Id, context.GroupId.ToString());
+
                     // Group is ready, returning to previous state.
-                    var pausedState = new PausedGroupState(Logger);
+                    var pausedState = new PausedGroupState(LoggerFactory);
                     context.SetState(pausedState);
 
                     if (InitialState.Equals(GroupStateType.Playing))
@@ -548,8 +555,6 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
                     {
                         pausedState.HandleRequest(context, Type, request, session, cancellationToken);
                     }
-
-                    Logger.LogDebug("HandleRequest: {RequestType} in group {GroupId}, {SessionId} is ready, returning to previous state.", request.Type, context.GroupId.ToString(), session.Id);
                 }
             }
         }
@@ -569,7 +574,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
             // Make sure the client knows the playing item, to avoid duplicate requests.
             if (!request.PlaylistItemId.Equals(context.PlayQueue.GetPlayingItemPlaylistId(), StringComparison.OrdinalIgnoreCase))
             {
-                Logger.LogDebug("HandleRequest: {RequestType} in group {GroupId}, {SessionId} provided the wrong playlist identifier.", request.Type, context.GroupId.ToString(), session.Id);
+                _logger.LogDebug("Session {SessionId} provided the wrong playlist item for group {GroupId}.", session.Id, context.GroupId.ToString());
                 return;
             }
 
@@ -589,14 +594,14 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
                 // Return to old state.
                 IGroupState newState = prevState switch
                 {
-                    GroupStateType.Playing => new PlayingGroupState(Logger),
-                    GroupStateType.Paused => new PausedGroupState(Logger),
-                    _ => new IdleGroupState(Logger)
+                    GroupStateType.Playing => new PlayingGroupState(LoggerFactory),
+                    GroupStateType.Paused => new PausedGroupState(LoggerFactory),
+                    _ => new IdleGroupState(LoggerFactory)
                 };
 
                 context.SetState(newState);
 
-                Logger.LogDebug("HandleRequest: {RequestType} in group {GroupId}, no next track available.", request.Type, context.GroupId.ToString());
+                _logger.LogDebug("No next track available in group {GroupId}.", context.GroupId.ToString());
             }
         }
 
@@ -615,7 +620,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
             // Make sure the client knows the playing item, to avoid duplicate requests.
             if (!request.PlaylistItemId.Equals(context.PlayQueue.GetPlayingItemPlaylistId(), StringComparison.OrdinalIgnoreCase))
             {
-                Logger.LogDebug("HandleRequest: {RequestType} in group {GroupId}, {SessionId} provided the wrong playlist identifier.", request.Type, context.GroupId.ToString(), session.Id);
+                _logger.LogDebug("Session {SessionId} provided the wrong playlist item for group {GroupId}.", session.Id, context.GroupId.ToString());
                 return;
             }
 
@@ -635,14 +640,14 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
                 // Return to old state.
                 IGroupState newState = prevState switch
                 {
-                    GroupStateType.Playing => new PlayingGroupState(Logger),
-                    GroupStateType.Paused => new PausedGroupState(Logger),
-                    _ => new IdleGroupState(Logger)
+                    GroupStateType.Playing => new PlayingGroupState(LoggerFactory),
+                    GroupStateType.Paused => new PausedGroupState(LoggerFactory),
+                    _ => new IdleGroupState(LoggerFactory)
                 };
 
                 context.SetState(newState);
 
-                Logger.LogDebug("HandleRequest: {RequestType} in group {GroupId}, no previous track available.", request.Type, context.GroupId.ToString());
+                _logger.LogDebug("No previous track available in group {GroupId}.", context.GroupId.ToString());
             }
         }
 
@@ -653,12 +658,12 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
 
             if (!context.IsBuffering())
             {
-                Logger.LogDebug("HandleRequest: {RequestType} in group {GroupId}, returning to previous state.", request.Type, context.GroupId.ToString());
+                _logger.LogDebug("Ignoring session {SessionId}, group {GroupId} is ready.", session.Id, context.GroupId.ToString());
 
                 if (ResumePlaying)
                 {
                     // Client, that was buffering, stopped following playback.
-                    var playingState = new PlayingGroupState(Logger);
+                    var playingState = new PlayingGroupState(LoggerFactory);
                     context.SetState(playingState);
                     var unpauseRequest = new UnpauseGroupRequest();
                     playingState.HandleRequest(context, Type, unpauseRequest, session, cancellationToken);
@@ -666,7 +671,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
                 else
                 {
                     // Group is ready, returning to previous state.
-                    var pausedState = new PausedGroupState(Logger);
+                    var pausedState = new PausedGroupState(LoggerFactory);
                     context.SetState(pausedState);
                 }
             }

+ 9 - 23
MediaBrowser.Controller/SyncPlay/Queue/PlayQueueManager.cs

@@ -20,7 +20,7 @@ namespace MediaBrowser.Controller.SyncPlay.Queue
         /// Random number generator used to shuffle lists.
         /// </summary>
         /// <value>The random number generator.</value>
-        private readonly Random randomNumberGenerator = new Random();
+        private readonly Random _randomNumberGenerator = new Random();
 
         /// <summary>
         /// Initializes a new instance of the <see cref="PlayQueueManager" /> class.
@@ -102,7 +102,7 @@ namespace MediaBrowser.Controller.SyncPlay.Queue
             SortedPlaylist = CreateQueueItemsFromArray(items);
             if (ShuffleMode.Equals(GroupShuffleMode.Shuffle))
             {
-                ShuffledPlaylist = SortedPlaylist.ToList();
+                ShuffledPlaylist = new List<QueueItem>(SortedPlaylist);
                 Shuffle(ShuffledPlaylist);
             }
 
@@ -134,17 +134,17 @@ namespace MediaBrowser.Controller.SyncPlay.Queue
         {
             if (PlayingItemIndex == NoPlayingItemIndex)
             {
-                ShuffledPlaylist = SortedPlaylist.ToList();
+                ShuffledPlaylist = new List<QueueItem>(SortedPlaylist);
                 Shuffle(ShuffledPlaylist);
             }
             else if (ShuffleMode.Equals(GroupShuffleMode.Sorted))
             {
                 // First time shuffle.
                 var playingItem = SortedPlaylist[PlayingItemIndex];
-                ShuffledPlaylist = SortedPlaylist.ToList();
+                ShuffledPlaylist = new List<QueueItem>(SortedPlaylist);
                 ShuffledPlaylist.RemoveAt(PlayingItemIndex);
                 Shuffle(ShuffledPlaylist);
-                ShuffledPlaylist = ShuffledPlaylist.Prepend(playingItem).ToList();
+                ShuffledPlaylist.Insert(0, playingItem);
                 PlayingItemIndex = 0;
             }
             else
@@ -153,7 +153,7 @@ namespace MediaBrowser.Controller.SyncPlay.Queue
                 var playingItem = ShuffledPlaylist[PlayingItemIndex];
                 ShuffledPlaylist.RemoveAt(PlayingItemIndex);
                 Shuffle(ShuffledPlaylist);
-                ShuffledPlaylist = ShuffledPlaylist.Prepend(playingItem).ToList();
+                ShuffledPlaylist.Insert(0, playingItem);
                 PlayingItemIndex = 0;
             }
 
@@ -236,14 +236,7 @@ namespace MediaBrowser.Controller.SyncPlay.Queue
         public string GetPlayingItemPlaylistId()
         {
             var playingItem = GetPlayingItem();
-            if (playingItem != null)
-            {
-                return playingItem.PlaylistItemId;
-            }
-            else
-            {
-                return null;
-            }
+            return playingItem?.PlaylistItemId;
         }
 
         /// <summary>
@@ -253,14 +246,7 @@ namespace MediaBrowser.Controller.SyncPlay.Queue
         public Guid GetPlayingItemId()
         {
             var playingItem = GetPlayingItem();
-            if (playingItem != null)
-            {
-                return playingItem.ItemId;
-            }
-            else
-            {
-                return Guid.Empty;
-            }
+            return playingItem?.ItemId ?? Guid.Empty;
         }
 
         /// <summary>
@@ -536,7 +522,7 @@ namespace MediaBrowser.Controller.SyncPlay.Queue
             while (n > 1)
             {
                 n--;
-                int k = randomNumberGenerator.Next(n + 1);
+                int k = _randomNumberGenerator.Next(n + 1);
                 T value = list[k];
                 list[k] = list[n];
                 list[n] = value;