PausedGroupState.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #nullable disable
  2. using System;
  3. using System.Threading;
  4. using MediaBrowser.Controller.Session;
  5. using MediaBrowser.Controller.SyncPlay.PlaybackRequests;
  6. using MediaBrowser.Model.SyncPlay;
  7. using Microsoft.Extensions.Logging;
  8. namespace MediaBrowser.Controller.SyncPlay.GroupStates
  9. {
  10. /// <summary>
  11. /// Class PausedGroupState.
  12. /// </summary>
  13. /// <remarks>
  14. /// Class is not thread-safe, external locking is required when accessing methods.
  15. /// </remarks>
  16. public class PausedGroupState : AbstractGroupState
  17. {
  18. /// <summary>
  19. /// The logger.
  20. /// </summary>
  21. private readonly ILogger<PausedGroupState> _logger;
  22. /// <summary>
  23. /// Initializes a new instance of the <see cref="PausedGroupState"/> class.
  24. /// </summary>
  25. /// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param>
  26. public PausedGroupState(ILoggerFactory loggerFactory)
  27. : base(loggerFactory)
  28. {
  29. _logger = LoggerFactory.CreateLogger<PausedGroupState>();
  30. }
  31. /// <inheritdoc />
  32. public override GroupStateType Type { get; } = GroupStateType.Paused;
  33. /// <inheritdoc />
  34. public override void SessionJoined(IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
  35. {
  36. // Wait for session to be ready.
  37. var waitingState = new WaitingGroupState(LoggerFactory);
  38. context.SetState(waitingState);
  39. waitingState.SessionJoined(context, Type, session, cancellationToken);
  40. }
  41. /// <inheritdoc />
  42. public override void SessionLeaving(IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
  43. {
  44. // Do nothing.
  45. }
  46. /// <inheritdoc />
  47. public override void HandleRequest(PlayGroupRequest request, IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
  48. {
  49. // Change state.
  50. var waitingState = new WaitingGroupState(LoggerFactory);
  51. context.SetState(waitingState);
  52. waitingState.HandleRequest(request, context, Type, session, cancellationToken);
  53. }
  54. /// <inheritdoc />
  55. public override void HandleRequest(UnpauseGroupRequest request, IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
  56. {
  57. // Change state.
  58. var playingState = new PlayingGroupState(LoggerFactory);
  59. context.SetState(playingState);
  60. playingState.HandleRequest(request, context, Type, session, cancellationToken);
  61. }
  62. /// <inheritdoc />
  63. public override void HandleRequest(PauseGroupRequest request, IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
  64. {
  65. if (!prevState.Equals(Type))
  66. {
  67. // Pause group and compute the media playback position.
  68. var currentTime = DateTime.UtcNow;
  69. var elapsedTime = currentTime - context.LastActivity;
  70. context.LastActivity = currentTime;
  71. // Elapsed time is negative if event happens
  72. // during the delay added to account for latency.
  73. // In this phase clients haven't started the playback yet.
  74. // In other words, LastActivity is in the future,
  75. // when playback unpause is supposed to happen.
  76. // Seek only if playback actually started.
  77. context.PositionTicks += Math.Max(elapsedTime.Ticks, 0);
  78. var command = context.NewSyncPlayCommand(SendCommandType.Pause);
  79. context.SendCommand(session, SyncPlayBroadcastType.AllGroup, command, cancellationToken);
  80. // Notify relevant state change event.
  81. SendGroupStateUpdate(context, request, session, cancellationToken);
  82. }
  83. else
  84. {
  85. // Client got lost, sending current state.
  86. var command = context.NewSyncPlayCommand(SendCommandType.Pause);
  87. context.SendCommand(session, SyncPlayBroadcastType.CurrentSession, command, cancellationToken);
  88. }
  89. }
  90. /// <inheritdoc />
  91. public override void HandleRequest(StopGroupRequest request, IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
  92. {
  93. // Change state.
  94. var idleState = new IdleGroupState(LoggerFactory);
  95. context.SetState(idleState);
  96. idleState.HandleRequest(request, context, Type, session, cancellationToken);
  97. }
  98. /// <inheritdoc />
  99. public override void HandleRequest(SeekGroupRequest request, IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
  100. {
  101. // Change state.
  102. var waitingState = new WaitingGroupState(LoggerFactory);
  103. context.SetState(waitingState);
  104. waitingState.HandleRequest(request, context, Type, session, cancellationToken);
  105. }
  106. /// <inheritdoc />
  107. public override void HandleRequest(BufferGroupRequest request, IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
  108. {
  109. // Change state.
  110. var waitingState = new WaitingGroupState(LoggerFactory);
  111. context.SetState(waitingState);
  112. waitingState.HandleRequest(request, context, Type, session, cancellationToken);
  113. }
  114. /// <inheritdoc />
  115. public override void HandleRequest(ReadyGroupRequest request, IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
  116. {
  117. if (prevState.Equals(Type))
  118. {
  119. // Client got lost, sending current state.
  120. var command = context.NewSyncPlayCommand(SendCommandType.Pause);
  121. context.SendCommand(session, SyncPlayBroadcastType.CurrentSession, command, cancellationToken);
  122. }
  123. else if (prevState.Equals(GroupStateType.Waiting))
  124. {
  125. // Sending current state to all clients.
  126. var command = context.NewSyncPlayCommand(SendCommandType.Pause);
  127. context.SendCommand(session, SyncPlayBroadcastType.AllGroup, command, cancellationToken);
  128. // Notify relevant state change event.
  129. SendGroupStateUpdate(context, request, session, cancellationToken);
  130. }
  131. }
  132. /// <inheritdoc />
  133. public override void HandleRequest(NextItemGroupRequest request, IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
  134. {
  135. // Change state.
  136. var waitingState = new WaitingGroupState(LoggerFactory);
  137. context.SetState(waitingState);
  138. waitingState.HandleRequest(request, context, Type, session, cancellationToken);
  139. }
  140. /// <inheritdoc />
  141. public override void HandleRequest(PreviousItemGroupRequest request, IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
  142. {
  143. // Change state.
  144. var waitingState = new WaitingGroupState(LoggerFactory);
  145. context.SetState(waitingState);
  146. waitingState.HandleRequest(request, context, Type, session, cancellationToken);
  147. }
  148. }
  149. }