aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller/SyncPlay/GroupStates/PausedGroupState.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Controller/SyncPlay/GroupStates/PausedGroupState.cs')
-rw-r--r--MediaBrowser.Controller/SyncPlay/GroupStates/PausedGroupState.cs165
1 files changed, 165 insertions, 0 deletions
diff --git a/MediaBrowser.Controller/SyncPlay/GroupStates/PausedGroupState.cs b/MediaBrowser.Controller/SyncPlay/GroupStates/PausedGroupState.cs
new file mode 100644
index 0000000000..fba8ba9e2e
--- /dev/null
+++ b/MediaBrowser.Controller/SyncPlay/GroupStates/PausedGroupState.cs
@@ -0,0 +1,165 @@
+using System;
+using System.Threading;
+using MediaBrowser.Controller.Session;
+using MediaBrowser.Controller.SyncPlay.PlaybackRequests;
+using MediaBrowser.Model.SyncPlay;
+using Microsoft.Extensions.Logging;
+
+namespace MediaBrowser.Controller.SyncPlay.GroupStates
+{
+ /// <summary>
+ /// Class PausedGroupState.
+ /// </summary>
+ /// <remarks>
+ /// Class is not thread-safe, external locking is required when accessing methods.
+ /// </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="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param>
+ public PausedGroupState(ILoggerFactory loggerFactory)
+ : base(loggerFactory)
+ {
+ _logger = LoggerFactory.CreateLogger<PausedGroupState>();
+ }
+
+ /// <inheritdoc />
+ public override GroupStateType Type { get; } = GroupStateType.Paused;
+
+ /// <inheritdoc />
+ public override void SessionJoined(IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
+ {
+ // Wait for session to be ready.
+ var waitingState = new WaitingGroupState(LoggerFactory);
+ context.SetState(waitingState);
+ waitingState.SessionJoined(context, Type, session, cancellationToken);
+ }
+
+ /// <inheritdoc />
+ public override void SessionLeaving(IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
+ {
+ // Do nothing.
+ }
+
+ /// <inheritdoc />
+ public override void HandleRequest(PlayGroupRequest request, IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
+ {
+ // Change state.
+ var waitingState = new WaitingGroupState(LoggerFactory);
+ context.SetState(waitingState);
+ waitingState.HandleRequest(request, context, Type, session, cancellationToken);
+ }
+
+ /// <inheritdoc />
+ public override void HandleRequest(UnpauseGroupRequest request, IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
+ {
+ // Change state.
+ var playingState = new PlayingGroupState(LoggerFactory);
+ context.SetState(playingState);
+ playingState.HandleRequest(request, context, Type, session, cancellationToken);
+ }
+
+ /// <inheritdoc />
+ public override void HandleRequest(PauseGroupRequest request, IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
+ {
+ if (!prevState.Equals(Type))
+ {
+ // Pause group and compute the media playback position.
+ var currentTime = DateTime.UtcNow;
+ var elapsedTime = currentTime - context.LastActivity;
+ context.LastActivity = currentTime;
+ // Elapsed time is negative if event happens
+ // during the delay added to account for latency.
+ // In this phase clients haven't started the playback yet.
+ // In other words, LastActivity is in the future,
+ // when playback unpause is supposed to happen.
+ // Seek only if playback actually started.
+ context.PositionTicks += Math.Max(elapsedTime.Ticks, 0);
+
+ var command = context.NewSyncPlayCommand(SendCommandType.Pause);
+ 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.Pause);
+ context.SendCommand(session, SyncPlayBroadcastType.CurrentSession, command, cancellationToken);
+ }
+ }
+
+ /// <inheritdoc />
+ public override void HandleRequest(StopGroupRequest request, IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
+ {
+ // Change state.
+ var idleState = new IdleGroupState(LoggerFactory);
+ context.SetState(idleState);
+ idleState.HandleRequest(request, context, Type, session, cancellationToken);
+ }
+
+ /// <inheritdoc />
+ public override void HandleRequest(SeekGroupRequest request, IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
+ {
+ // Change state.
+ var waitingState = new WaitingGroupState(LoggerFactory);
+ context.SetState(waitingState);
+ waitingState.HandleRequest(request, context, Type, session, cancellationToken);
+ }
+
+ /// <inheritdoc />
+ public override void HandleRequest(BufferGroupRequest request, IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
+ {
+ // Change state.
+ var waitingState = new WaitingGroupState(LoggerFactory);
+ context.SetState(waitingState);
+ waitingState.HandleRequest(request, context, Type, session, cancellationToken);
+ }
+
+ /// <inheritdoc />
+ public override void HandleRequest(ReadyGroupRequest request, IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
+ {
+ if (prevState.Equals(Type))
+ {
+ // Client got lost, sending current state.
+ var command = context.NewSyncPlayCommand(SendCommandType.Pause);
+ context.SendCommand(session, SyncPlayBroadcastType.CurrentSession, command, cancellationToken);
+ }
+ else if (prevState.Equals(GroupStateType.Waiting))
+ {
+ // Sending current state to all clients.
+ var command = context.NewSyncPlayCommand(SendCommandType.Pause);
+ context.SendCommand(session, SyncPlayBroadcastType.AllGroup, command, cancellationToken);
+
+ // Notify relevant state change event.
+ SendGroupStateUpdate(context, request, session, cancellationToken);
+ }
+ }
+
+ /// <inheritdoc />
+ public override void HandleRequest(NextItemGroupRequest request, IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
+ {
+ // Change state.
+ var waitingState = new WaitingGroupState(LoggerFactory);
+ context.SetState(waitingState);
+ waitingState.HandleRequest(request, context, Type, session, cancellationToken);
+ }
+
+ /// <inheritdoc />
+ public override void HandleRequest(PreviousItemGroupRequest request, IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
+ {
+ // Change state.
+ var waitingState = new WaitingGroupState(LoggerFactory);
+ context.SetState(waitingState);
+ waitingState.HandleRequest(request, context, Type, session, cancellationToken);
+ }
+ }
+}