diff --git a/SentryDeck/Playback/FlyleafCameraPlayer.cs b/SentryDeck/Playback/FlyleafCameraPlayer.cs index 9409258..abdef0f 100644 --- a/SentryDeck/Playback/FlyleafCameraPlayer.cs +++ b/SentryDeck/Playback/FlyleafCameraPlayer.cs @@ -1,4 +1,5 @@ using System.ComponentModel; +using System.Diagnostics; using System.Windows.Media; using FlyleafLib; using FlyleafLib.Controls.WPF; @@ -115,17 +116,28 @@ public Task CloseAsync() return Task.Run(StopAndClose); } - public Task SeekAsync(TimeSpan position, bool accurate = true) + /// + /// How long a seek issued from the end of a clip waits for Flyleaf to leave its Ended state before returning anyway. + /// The flip normally lands within a few milliseconds; the cap only keeps a seek that never runs from stalling the caller. + /// + private static readonly TimeSpan LeaveEndedTimeout = TimeSpan.FromSeconds(1); + + public async Task SeekAsync(TimeSpan position, bool accurate = true) { ThrowIfDisposed(); if (!_isOpen) { - return Task.CompletedTask; + return; } var milliseconds = (int)Math.Clamp(position.TotalMilliseconds, 0, int.MaxValue); + // Flyleaf's Play() silently does nothing while the player is Ended, and a seek issued from the end only moves it back to Paused later, from the background task that performs the seek. + // Returning before that happens lets the very next Play() land on Ended and be dropped, leaving the video frozen while the transport reports playback. + // That is exactly what pressing play on a finished clip does, since PlayAsync seeks to the start and plays back to back. + var seekingFromEnded = _player.Status == Status.Ended; + if (accurate) { _player.SeekAccurate(milliseconds); @@ -137,7 +149,14 @@ public Task SeekAsync(TimeSpan position, bool accurate = true) _player.Seek(milliseconds, forward: false); } - return Task.CompletedTask; + if (seekingFromEnded) + { + var started = Stopwatch.GetTimestamp(); + while (!_isDisposed && _player.Status == Status.Ended && Stopwatch.GetElapsedTime(started) < LeaveEndedTimeout) + { + await Task.Delay(5); + } + } } ///