Defer initial playback-rate seek to ASYNC_DONE
An early seek right after set_state(PLAYING) raced the pipeline's preroll and GStreamer silently dropped it, so a configured custom rate only took effect after the first EOS loop-restart. Instead, flag the pending seek and fire it from the first ASYNC_DONE bus message, once the pipeline is actually ready to seek. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+30
-8
@@ -80,6 +80,7 @@ export class LiveWallpaperManager {
|
||||
this._busWatchId = 0;
|
||||
this._eosSeekTimeoutId = 0;
|
||||
this._lastEosSeekTimeMs = 0;
|
||||
this._pendingInitialRateSeek = false;
|
||||
this._monitorsChangedId = 0;
|
||||
this._fullscreenChangedId = 0;
|
||||
this._upowerProxy = null;
|
||||
@@ -279,11 +280,17 @@ export class LiveWallpaperManager {
|
||||
this._applyMute();
|
||||
const stateChangeResult = this._playbin.set_state(Gst.State.PLAYING);
|
||||
this._logger.debug(`playbin.set_state(PLAYING) returned ${stateChangeResult}`);
|
||||
// set_state(PLAYING) alone always starts at native rate 1.0 —
|
||||
// without this, a configured custom speed only ever took effect
|
||||
// once the first EOS loop-restart seek ran.
|
||||
if (this._settings.get_double(SettingsKey.LIVE_WALLPAPER_PLAYBACK_RATE) !== 1.0)
|
||||
this._seekToLoopStart();
|
||||
// Seeking here immediately would race the pipeline's preroll —
|
||||
// GStreamer can only seek once a state change has actually
|
||||
// completed, so an early seek is silently dropped and playback
|
||||
// sticks at native 1.0x. Instead, defer to the first ASYNC_DONE
|
||||
// bus message (handled in _onBusMessage), which fires once the
|
||||
// pipeline is actually ready to seek.
|
||||
const initialRate = this._settings.get_double(SettingsKey.LIVE_WALLPAPER_PLAYBACK_RATE);
|
||||
this._pendingInitialRateSeek = initialRate !== 1.0;
|
||||
this._logger.debug(
|
||||
`Live wallpaper: configured playback rate ${initialRate}, ` +
|
||||
`deferring initial seek to ASYNC_DONE: ${this._pendingInitialRateSeek}`);
|
||||
|
||||
this._frameCount = 0;
|
||||
this._pollCount = 0;
|
||||
@@ -409,6 +416,14 @@ export class LiveWallpaperManager {
|
||||
case Gst.MessageType.EOS:
|
||||
this._loopPlayback();
|
||||
break;
|
||||
case Gst.MessageType.ASYNC_DONE:
|
||||
this._logger.debug(
|
||||
`Live wallpaper: ASYNC_DONE received (pending initial rate seek: ${this._pendingInitialRateSeek})`);
|
||||
if (this._pendingInitialRateSeek) {
|
||||
this._pendingInitialRateSeek = false;
|
||||
this._seekToLoopStart();
|
||||
}
|
||||
break;
|
||||
case Gst.MessageType.ERROR: {
|
||||
const [error, debug] = message.parse_error();
|
||||
this._logger.error(error, `Live wallpaper playback error (${debug ?? 'no debug info'})`);
|
||||
@@ -466,9 +481,11 @@ export class LiveWallpaperManager {
|
||||
this._lastEosSeekTimeMs = GLib.get_monotonic_time() / 1000;
|
||||
const Gst = this._Gst;
|
||||
const rate = this._settings.get_double(SettingsKey.LIVE_WALLPAPER_PLAYBACK_RATE);
|
||||
this._playbin.seek(
|
||||
const ok = this._playbin.seek(
|
||||
rate, Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT,
|
||||
Gst.SeekType.SET, 0, Gst.SeekType.NONE, -1);
|
||||
this._logger.debug(
|
||||
`Live wallpaper: loop-restart seek to rate ${rate} ${ok ? 'succeeded' : 'FAILED (seek() returned false)'}`);
|
||||
}
|
||||
|
||||
_stateName(state) {
|
||||
@@ -488,12 +505,17 @@ export class LiveWallpaperManager {
|
||||
const Gst = this._Gst;
|
||||
const rate = this._settings.get_double(SettingsKey.LIVE_WALLPAPER_PLAYBACK_RATE);
|
||||
const [ok, position] = this._playbin.query_position(Gst.Format.TIME);
|
||||
if (!ok)
|
||||
if (!ok) {
|
||||
this._logger.debug('Live wallpaper: applyPlaybackRate aborted, query_position() failed');
|
||||
return;
|
||||
}
|
||||
|
||||
this._playbin.seek(
|
||||
const seekOk = this._playbin.seek(
|
||||
rate, Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.ACCURATE,
|
||||
Gst.SeekType.SET, position, Gst.SeekType.NONE, -1);
|
||||
this._logger.debug(
|
||||
`Live wallpaper: applyPlaybackRate to ${rate} at position ${position} ` +
|
||||
`${seekOk ? 'succeeded' : 'FAILED (seek() returned false)'}`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user