diff options
Diffstat (limited to 'Emby.Server.Implementations/SyncPlay/GroupStates/PlayingGroupState.cs')
| -rw-r--r-- | Emby.Server.Implementations/SyncPlay/GroupStates/PlayingGroupState.cs | 133 |
1 files changed, 102 insertions, 31 deletions
diff --git a/Emby.Server.Implementations/SyncPlay/GroupStates/PlayingGroupState.cs b/Emby.Server.Implementations/SyncPlay/GroupStates/PlayingGroupState.cs index 42c7779c1..e2909ff91 100644 --- a/Emby.Server.Implementations/SyncPlay/GroupStates/PlayingGroupState.cs +++ b/Emby.Server.Implementations/SyncPlay/GroupStates/PlayingGroupState.cs @@ -1,11 +1,8 @@ -using System.Linq; using System; using System.Threading; -using System.Collections.Generic; -using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Session; using MediaBrowser.Model.SyncPlay; +using Microsoft.Extensions.Logging; namespace MediaBrowser.Controller.SyncPlay { @@ -15,8 +12,21 @@ namespace MediaBrowser.Controller.SyncPlay /// <remarks> /// Class is not thread-safe, external locking is required when accessing methods. /// </remarks> - public class PlayingGroupState : SyncPlayAbstractState + public class PlayingGroupState : AbstractGroupState { + /// <summary> + /// Ignore requests for buffering. + /// </summary> + public bool IgnoreBuffering { get; set; } + + /// <summary> + /// Default constructor. + /// </summary> + public PlayingGroupState(ILogger logger) : base(logger) + { + // Do nothing + } + /// <inheritdoc /> public override GroupState GetGroupState() { @@ -24,71 +34,132 @@ namespace MediaBrowser.Controller.SyncPlay } /// <inheritdoc /> - public override bool HandleRequest(ISyncPlayStateContext context, bool newState, PlayGroupRequest request, SessionInfo session, CancellationToken cancellationToken) + public override void SessionJoined(ISyncPlayStateContext context, GroupState prevState, SessionInfo session, CancellationToken cancellationToken) { - GroupInfo group = context.GetGroup(); + // Wait for session to be ready + var waitingState = new WaitingGroupState(_logger); + context.SetState(waitingState); + waitingState.SessionJoined(context, GetGroupState(), session, cancellationToken); + } - if (newState) + /// <inheritdoc /> + public override void SessionLeaving(ISyncPlayStateContext context, GroupState prevState, SessionInfo session, CancellationToken cancellationToken) + { + // Do nothing + } + + /// <inheritdoc /> + public override void HandleRequest(ISyncPlayStateContext context, GroupState prevState, PlayGroupRequest request, SessionInfo session, CancellationToken cancellationToken) + { + // Change state + var waitingState = new WaitingGroupState(_logger); + context.SetState(waitingState); + waitingState.HandleRequest(context, GetGroupState(), request, session, cancellationToken); + } + + /// <inheritdoc /> + public override void HandleRequest(ISyncPlayStateContext context, GroupState prevState, UnpauseGroupRequest request, SessionInfo session, CancellationToken cancellationToken) + { + if (!prevState.Equals(GetGroupState())) { // Pick a suitable time that accounts for latency - var delay = Math.Max(group.GetHighestPing() * 2, group.DefaultPing); + var delayMillis = Math.Max(context.GetHighestPing() * 2, context.DefaultPing); // Unpause group and set starting point in future // Clients will start playback at LastActivity (datetime) from PositionTicks (playback position) // The added delay does not guarantee, of course, that the command will be received in time // Playback synchronization will mainly happen client side - group.LastActivity = DateTime.UtcNow.AddMilliseconds( - delay + context.LastActivity = DateTime.UtcNow.AddMilliseconds( + delayMillis ); - var command = context.NewSyncPlayCommand(SendCommandType.Play); + var command = context.NewSyncPlayCommand(SendCommandType.Unpause); context.SendCommand(session, SyncPlayBroadcastType.AllGroup, command, cancellationToken); + + // Notify relevant state change event + SendGroupStateUpdate(context, request, session, cancellationToken); } else { // Client got lost, sending current state - var command = context.NewSyncPlayCommand(SendCommandType.Play); + var command = context.NewSyncPlayCommand(SendCommandType.Unpause); context.SendCommand(session, SyncPlayBroadcastType.CurrentSession, command, cancellationToken); } - - return true; } /// <inheritdoc /> - public override bool HandleRequest(ISyncPlayStateContext context, bool newState, PauseGroupRequest request, SessionInfo session, CancellationToken cancellationToken) + public override void HandleRequest(ISyncPlayStateContext context, GroupState prevState, PauseGroupRequest request, SessionInfo session, CancellationToken cancellationToken) { // Change state - var pausedState = new PausedGroupState(); + var pausedState = new PausedGroupState(_logger); context.SetState(pausedState); - return pausedState.HandleRequest(context, true, request, session, cancellationToken); + pausedState.HandleRequest(context, GetGroupState(), request, session, cancellationToken); } /// <inheritdoc /> - public override bool HandleRequest(ISyncPlayStateContext context, bool newState, SeekGroupRequest request, SessionInfo session, CancellationToken cancellationToken) + public override void HandleRequest(ISyncPlayStateContext context, GroupState prevState, StopGroupRequest request, SessionInfo session, CancellationToken cancellationToken) { // Change state - var pausedState = new PausedGroupState(); - context.SetState(pausedState); - return pausedState.HandleRequest(context, true, request, session, cancellationToken); + var idleState = new IdleGroupState(_logger); + context.SetState(idleState); + idleState.HandleRequest(context, GetGroupState(), request, session, cancellationToken); } /// <inheritdoc /> - public override bool HandleRequest(ISyncPlayStateContext context, bool newState, BufferGroupRequest request, SessionInfo session, CancellationToken cancellationToken) + public override void HandleRequest(ISyncPlayStateContext context, GroupState prevState, SeekGroupRequest request, SessionInfo session, CancellationToken cancellationToken) { // Change state - var pausedState = new PausedGroupState(); - context.SetState(pausedState); - return pausedState.HandleRequest(context, true, request, session, cancellationToken); + var waitingState = new WaitingGroupState(_logger); + context.SetState(waitingState); + waitingState.HandleRequest(context, GetGroupState(), request, session, cancellationToken); + } + + /// <inheritdoc /> + public override void HandleRequest(ISyncPlayStateContext context, GroupState prevState, BufferGroupRequest request, SessionInfo session, CancellationToken cancellationToken) + { + if (IgnoreBuffering) + { + return; + } + + // Change state + var waitingState = new WaitingGroupState(_logger); + context.SetState(waitingState); + waitingState.HandleRequest(context, GetGroupState(), request, session, cancellationToken); } /// <inheritdoc /> - public override bool HandleRequest(ISyncPlayStateContext context, bool newState, ReadyGroupRequest request, SessionInfo session, CancellationToken cancellationToken) + public override void HandleRequest(ISyncPlayStateContext context, GroupState prevState, ReadyGroupRequest request, SessionInfo session, CancellationToken cancellationToken) { - // Group was not waiting, make sure client has latest state - var command = context.NewSyncPlayCommand(SendCommandType.Play); - context.SendCommand(session, SyncPlayBroadcastType.CurrentSession, command, cancellationToken); + if (prevState.Equals(GetGroupState())) + { + // Group was not waiting, make sure client has latest state + var command = context.NewSyncPlayCommand(SendCommandType.Unpause); + context.SendCommand(session, SyncPlayBroadcastType.CurrentSession, command, cancellationToken); + } + else if (prevState.Equals(GroupState.Waiting)) + { + // Notify relevant state change event + SendGroupStateUpdate(context, request, session, cancellationToken); + } + } + + /// <inheritdoc /> + public override void HandleRequest(ISyncPlayStateContext context, GroupState prevState, NextTrackGroupRequest request, SessionInfo session, CancellationToken cancellationToken) + { + // Change state + var waitingState = new WaitingGroupState(_logger); + context.SetState(waitingState); + waitingState.HandleRequest(context, GetGroupState(), request, session, cancellationToken); + } - return true; + /// <inheritdoc /> + public override void HandleRequest(ISyncPlayStateContext context, GroupState prevState, PreviousTrackGroupRequest request, SessionInfo session, CancellationToken cancellationToken) + { + // Change state + var waitingState = new WaitingGroupState(_logger); + context.SetState(waitingState); + waitingState.HandleRequest(context, GetGroupState(), request, session, cancellationToken); } } } |
