fix(player): reject seek during active CMAF streaming

Tightens the streaming-seek handler to the simpler contract signed off
by the user: seek works after a streaming track finishes downloading
(buffered_source.is_complete()), but is rejected cleanly with a warning
log while the download is still in progress. Avoids skip_duration
blocking the audio thread on past-watermark seeks without adding
watermark-tracking complexity.

Cache, offline-cache, and local-library seeks are unaffected — they
reach this handler with current_audio_data Some and skip the streaming
branch entirely.

Fixes part of #335.

cc
This commit is contained in:
vicrodh committed 2026-04-20 20:52:03 -06:00
1 parent 7d9a847a87
commit 2dc1ee9e9f
1 file changed
+21 -9
+21 -9
View File
@@ -2124,15 +2124,18 @@ impl Player {
thread_state.set_gapless_ready(false);
thread_state.set_gapless_next_track_id(0);
// Two source kinds reach this handler: full-file
// playback (current_audio_data holds the complete
// bytes) and CMAF streaming (bytes live inside
// Arc<BufferedMediaSource> so current_audio_data
// is None). Previously the handler early-returned
// on None, so every seek during active streaming
// silently dropped and the UI snapped back
// (issue #335). Now it branches on whichever
// source is live.
// Three cases reach this handler:
// * full-file playback (current_audio_data set)
// * CMAF streaming, download complete (buffered
// source holds the full file)
// * CMAF streaming, download IN PROGRESS — the
// decoder can only read already-buffered bytes
// and skip_duration would block the audio
// thread waiting for the rest. Reject cleanly
// here instead. Cached, offline-cached, and
// local-library playback don't reach this
// branch (current_audio_data is Some), so they
// keep seeking as before (issue #335).
if current_audio_data.is_none()
&& current_streaming_source.is_none()
{
@@ -2141,6 +2144,15 @@ impl Player {
);
return;
}
if let Some(ref stream_src) = *current_streaming_source {
if !stream_src.is_complete() {
log::warn!(
"Audio thread: seek to {}s ignored — track still streaming (not seekable until download completes)",
position_secs
);
return;
}
}
let Some(ref stream) = *stream_opt else {
log::error!(