Add live wallpaper pipeline diagnostics
A user's live wallpaper reached "started" with zero errors (Cogl and GStreamer both loading fine, actor added to _backgroundGroup) but never actually appeared on screen, and no code path here could tell us why: the bus handler only looked at EOS/ERROR, silently discarding WARNING and STATE_CHANGED messages where a stalled negotiation or preroll would actually show up. Adds: WARNING message logging, PLAYING/PAUSED/etc. state-changed logging for the playbin itself, a frame counter with first-frame and periodic debug logs, and a one-shot watchdog that logs an explicit warning if zero frames arrive within 4s of set_state(PLAYING). Also switched appsink's pull-sample from an emitted action signal to the plain pull_sample() method, which is the more directly supported GstApp.AppSink API and one less variable while debugging. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019RDqbdjsiisSU7CbQke4g8
This commit is contained in:
+46
-4
@@ -48,6 +48,9 @@ export class LiveWallpaperManager {
|
||||
this._fullscreenChangedId = 0;
|
||||
this._upowerProxy = null;
|
||||
this._upowerSignalId = 0;
|
||||
|
||||
this._frameCount = 0;
|
||||
this._noFrameWatchdogId = 0;
|
||||
}
|
||||
|
||||
get isAvailable() {
|
||||
@@ -155,7 +158,20 @@ export class LiveWallpaperManager {
|
||||
this._busWatchId = bus.connect('message', (_bus, message) => this._onBusMessage(message));
|
||||
|
||||
this._applyMute();
|
||||
this._playbin.set_state(Gst.State.PLAYING);
|
||||
const stateChangeResult = this._playbin.set_state(Gst.State.PLAYING);
|
||||
this._logger.debug(`playbin.set_state(PLAYING) returned ${stateChangeResult}`);
|
||||
|
||||
this._frameCount = 0;
|
||||
this._noFrameWatchdogId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 4, () => {
|
||||
this._noFrameWatchdogId = 0;
|
||||
if (this._active && this._frameCount === 0) {
|
||||
this._logger.warn(
|
||||
'Live wallpaper: no frames received 4s after starting playback. ' +
|
||||
'The pipeline likely stalled during caps negotiation or preroll without ' +
|
||||
'raising an error — check for GStreamer WARNING messages logged above.');
|
||||
}
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
|
||||
this._setActive(true);
|
||||
this._paused = false;
|
||||
@@ -169,7 +185,7 @@ export class LiveWallpaperManager {
|
||||
|
||||
_onNewSample(sink) {
|
||||
const Gst = this._Gst;
|
||||
const sample = sink.emit('pull-sample');
|
||||
const sample = sink.pull_sample();
|
||||
if (!sample)
|
||||
return Gst.FlowReturn.OK;
|
||||
|
||||
@@ -185,6 +201,11 @@ export class LiveWallpaperManager {
|
||||
|
||||
try {
|
||||
this._updateFrame(mapInfo.data, width, height);
|
||||
this._frameCount++;
|
||||
if (this._frameCount === 1)
|
||||
this._logger.debug(`Live wallpaper: first frame received (${width}x${height})`);
|
||||
else if (this._frameCount % 120 === 0)
|
||||
this._logger.debug(`Live wallpaper: ${this._frameCount} frames rendered so far`);
|
||||
} finally {
|
||||
buffer.unmap(mapInfo);
|
||||
}
|
||||
@@ -221,12 +242,28 @@ export class LiveWallpaperManager {
|
||||
Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT, 0);
|
||||
break;
|
||||
case Gst.MessageType.ERROR: {
|
||||
const [error] = message.parse_error();
|
||||
this._logger.error(error, 'Live wallpaper playback error');
|
||||
const [error, debug] = message.parse_error();
|
||||
this._logger.error(error, `Live wallpaper playback error (${debug ?? 'no debug info'})`);
|
||||
this._stop();
|
||||
break;
|
||||
}
|
||||
case Gst.MessageType.WARNING: {
|
||||
const [warning, debug] = message.parse_warning();
|
||||
this._logger.warn(`Live wallpaper GStreamer warning: ${warning.message} (${debug ?? 'no debug info'})`);
|
||||
break;
|
||||
}
|
||||
case Gst.MessageType.STATE_CHANGED:
|
||||
if (message.src === this._playbin) {
|
||||
const [, newState] = message.parse_state_changed();
|
||||
this._logger.debug(`Live wallpaper pipeline state changed to ${this._stateName(newState)}`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_stateName(state) {
|
||||
const Gst = this._Gst;
|
||||
return Object.keys(Gst.State).find(name => Gst.State[name] === state) ?? String(state);
|
||||
}
|
||||
|
||||
_applyMute() {
|
||||
@@ -326,6 +363,11 @@ export class LiveWallpaperManager {
|
||||
_stop() {
|
||||
this._disconnectPowerWatches();
|
||||
|
||||
if (this._noFrameWatchdogId) {
|
||||
GLib.source_remove(this._noFrameWatchdogId);
|
||||
this._noFrameWatchdogId = 0;
|
||||
}
|
||||
|
||||
if (this._playbin) {
|
||||
const bus = this._playbin.get_bus();
|
||||
if (this._busWatchId) {
|
||||
|
||||
Reference in New Issue
Block a user