PausedGroupState.cs 7.6 KB

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