aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller/SyncPlay
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Controller/SyncPlay')
-rw-r--r--MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs21
-rw-r--r--MediaBrowser.Controller/SyncPlay/IGroupStateContext.cs6
-rw-r--r--MediaBrowser.Controller/SyncPlay/Queue/PlayQueueManager.cs5
3 files changed, 29 insertions, 3 deletions
diff --git a/MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs b/MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs
index eb38eeb503..8f17039ae1 100644
--- a/MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs
+++ b/MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs
@@ -50,6 +50,11 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
/// </summary>
private GroupStateType InitialState { get; set; }
+ /// <summary>
+ /// Gets or sets a value indicating whether the group position moved during this wait.
+ /// </summary>
+ private bool PositionJumped { get; set; }
+
/// <inheritdoc />
public override void SessionJoined(IGroupStateContext context, GroupStateType prevState, SessionInfo session, CancellationToken cancellationToken)
{
@@ -136,6 +141,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
ResumePlaying = true;
var setQueueStatus = context.SetPlayQueue(request.PlayingQueue, request.PlayingItemPosition, request.StartPositionTicks);
+ PositionJumped = setQueueStatus;
if (!setQueueStatus)
{
_logger.LogError("Unable to set playing queue in group {GroupId}.", context.GroupId.ToString());
@@ -175,6 +181,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
ResumePlaying = true;
var result = context.SetPlayingItem(request.PlaylistItemId);
+ PositionJumped = result;
if (result)
{
var playQueueUpdate = context.GetPlayQueueUpdate(PlayQueueUpdateReason.SetCurrentItem);
@@ -214,6 +221,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
{
ResumePlaying = true;
context.RestartCurrentItem();
+ PositionJumped = true;
var playQueueUpdate = context.GetPlayQueueUpdate(PlayQueueUpdateReason.NewPlaylist);
var update = new SyncPlayPlayQueueUpdate(context.GroupId, playQueueUpdate);
@@ -310,6 +318,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
// Seek.
context.PositionTicks = ticks;
context.LastActivity = DateTime.UtcNow;
+ PositionJumped = true;
var command = context.NewSyncPlayCommand(SendCommandType.Seek);
context.SendCommand(session, SyncPlayBroadcastType.AllGroup, command, cancellationToken);
@@ -450,7 +459,13 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
{
// Handle case where session reported as ready but in reality
// it has no clue of the real position nor the playback state.
- if (!request.IsPlaying && Math.Abs(delayTicks) > maxPlaybackOffsetTicks)
+ // A jump means the session has not applied the new position; without one it is
+ // catching up after buffering and is allowed to lag.
+ var maxOffsetTicks = request.IsPlaying && !PositionJumped
+ ? TimeSpan.FromMilliseconds(context.MaxCatchUpOffset).Ticks
+ : maxPlaybackOffsetTicks;
+
+ if (Math.Abs(delayTicks) > maxOffsetTicks)
{
// Session not ready at all.
context.SetBuffering(session, true);
@@ -501,7 +516,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
{
// Client, that was buffering, resumed playback but did not update others in time.
delayTicks = context.GetHighestPing() * 2 * TimeSpan.TicksPerMillisecond;
- delayTicks = Math.Max(delayTicks, context.DefaultPing);
+ delayTicks = Math.Max(delayTicks, TimeSpan.FromMilliseconds(context.DefaultPing).Ticks);
context.LastActivity = currentTime.AddTicks(delayTicks);
@@ -580,6 +595,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
}
var newItem = context.NextItemInQueue();
+ PositionJumped = newItem;
if (newItem)
{
// Send playing-queue update.
@@ -626,6 +642,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
}
var newItem = context.PreviousItemInQueue();
+ PositionJumped = newItem;
if (newItem)
{
// Send playing-queue update.
diff --git a/MediaBrowser.Controller/SyncPlay/IGroupStateContext.cs b/MediaBrowser.Controller/SyncPlay/IGroupStateContext.cs
index ddf86be71f..e02d1bde45 100644
--- a/MediaBrowser.Controller/SyncPlay/IGroupStateContext.cs
+++ b/MediaBrowser.Controller/SyncPlay/IGroupStateContext.cs
@@ -34,6 +34,12 @@ namespace MediaBrowser.Controller.SyncPlay
long MaxPlaybackOffset { get; }
/// <summary>
+ /// Gets the maximum offset accepted for a session catching up after buffering, in milliseconds.
+ /// </summary>
+ /// <value>The maximum catch-up offset, in milliseconds.</value>
+ long MaxCatchUpOffset => 60000;
+
+ /// <summary>
/// Gets the group identifier.
/// </summary>
/// <value>The group identifier.</value>
diff --git a/MediaBrowser.Controller/SyncPlay/Queue/PlayQueueManager.cs b/MediaBrowser.Controller/SyncPlay/Queue/PlayQueueManager.cs
index 9326864d78..258b92e4d9 100644
--- a/MediaBrowser.Controller/SyncPlay/Queue/PlayQueueManager.cs
+++ b/MediaBrowser.Controller/SyncPlay/Queue/PlayQueueManager.cs
@@ -157,7 +157,10 @@ namespace MediaBrowser.Controller.SyncPlay.Queue
/// </summary>
public void RestoreSortedPlaylist()
{
- if (PlayingItemIndex != NoPlayingItemIndex)
+ // The shuffled playlist is only populated while the shuffle mode is active, so there is
+ // nothing to map back when the playlist is already sorted. Guarding on its contents keeps
+ // a redundant request for the sorted mode from indexing an empty list.
+ if (PlayingItemIndex != NoPlayingItemIndex && _shuffledPlaylist.Count > 0)
{
var playingItem = _shuffledPlaylist[PlayingItemIndex];
PlayingItemIndex = _sortedPlaylist.IndexOf(playingItem);