PausedGroupState.cs 7.4 KB

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