Claude/gnome wallpaper auto rotation r1ailq #1
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Loads the GObject-Introspection bindings the live wallpaper feature needs
|
||||
* (Gst, GstApp for the appsink signals, Cogl for uploading decoded frames)
|
||||
* and initializes GStreamer. Shared by extension.js (to actually run the
|
||||
* pipeline) and prefs.js (to tell the user up front why the feature is
|
||||
* greyed out), since either process may be missing the system packages
|
||||
* that provide these typelibs.
|
||||
*
|
||||
* Throws with a descriptive message on failure; never caches a *failure*,
|
||||
* since the user may install the missing packages and reopen preferences
|
||||
* without restarting the shell.
|
||||
*/
|
||||
export async function loadGstreamerModules() {
|
||||
const [{default: Gst}, , {default: Cogl}] = await Promise.all([
|
||||
import('gi://Gst?version=1.0'),
|
||||
import('gi://GstApp?version=1.0'),
|
||||
import('gi://Cogl'),
|
||||
]);
|
||||
|
||||
if (!Gst.is_initialized())
|
||||
Gst.init(null);
|
||||
|
||||
return {Gst, Cogl};
|
||||
}
|
||||
|
||||
export const GSTREAMER_INSTALL_HINT =
|
||||
'Install GStreamer’s "base" and "good" plugin sets (with their GObject-Introspection data), ' +
|
||||
'which provide playback and GIF decoding:\n' +
|
||||
'• Arch: sudo pacman -S gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav\n' +
|
||||
'• Debian/Ubuntu: sudo apt install gstreamer1.0-plugins-base gstreamer1.0-plugins-good ' +
|
||||
'gir1.2-gst-plugins-base-1.0\n' +
|
||||
'• Fedora: sudo dnf install gstreamer1-plugins-base gstreamer1-plugins-good gobject-introspection\n' +
|
||||
'Then restart GNOME Shell (log out and back in on Wayland).';
|
||||
+3
-16
@@ -4,6 +4,7 @@ import Clutter from 'gi://Clutter';
|
||||
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
|
||||
|
||||
import {SettingsKey} from './settingsKeys.js';
|
||||
import {loadGstreamerModules, GSTREAMER_INSTALL_HINT} from './gstreamerAvailability.js';
|
||||
|
||||
/**
|
||||
* Plays a video or animated GIF file as a looping animated background.
|
||||
@@ -88,28 +89,14 @@ export class LiveWallpaperManager {
|
||||
|
||||
async _loadGstreamer() {
|
||||
try {
|
||||
// GstApp's binding itself is unused, but importing it registers
|
||||
// GstApp.AppSink with GJS so appsink elements expose 'new-sample'
|
||||
// and the 'pull-sample' action signal instead of being wrapped
|
||||
// as a generic, capability-less Gst.Element.
|
||||
const [{default: Gst}, , {default: Cogl}] = await Promise.all([
|
||||
import('gi://Gst?version=1.0'),
|
||||
import('gi://GstApp?version=1.0'),
|
||||
import('gi://Cogl'),
|
||||
]);
|
||||
|
||||
const {Gst, Cogl} = await loadGstreamerModules();
|
||||
this._Gst = Gst;
|
||||
this._Cogl = Cogl;
|
||||
|
||||
if (!Gst.is_initialized())
|
||||
Gst.init(null);
|
||||
|
||||
this._available = true;
|
||||
} catch (e) {
|
||||
this._available = false;
|
||||
this._logger.warn(
|
||||
'Live wallpaper unavailable: GStreamer/Cogl introspection bindings could not be loaded ' +
|
||||
`(${e.message ?? e}). Install GStreamer with its "good"/"base" plugin sets to enable this feature.`);
|
||||
`Live wallpaper unavailable: GStreamer/Cogl introspection bindings could not be loaded (${e.message ?? e}).\n${GSTREAMER_INSTALL_HINT}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,15 +6,17 @@ import Gdk from 'gi://Gdk';
|
||||
import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
|
||||
|
||||
import {SettingsKey} from './lib/settingsKeys.js';
|
||||
import {loadGstreamerModules, GSTREAMER_INSTALL_HINT} from './lib/gstreamerAvailability.js';
|
||||
|
||||
export default class BenthicBloomPreferences extends ExtensionPreferences {
|
||||
fillPreferencesWindow(window) {
|
||||
async fillPreferencesWindow(window) {
|
||||
const settings = this.getSettings();
|
||||
const gstreamerError = await loadGstreamerModules().then(() => null, e => e.message ?? String(e));
|
||||
|
||||
window.set_default_size(640, 720);
|
||||
window.add(this._buildGeneralPage(settings));
|
||||
window.add(this._buildRotationPage(settings));
|
||||
window.add(this._buildLiveWallpaperPage(settings));
|
||||
window.add(this._buildLiveWallpaperPage(settings, gstreamerError));
|
||||
window.add(this._buildOledPage(settings));
|
||||
window.add(this._buildAboutPage());
|
||||
}
|
||||
@@ -170,9 +172,21 @@ export default class BenthicBloomPreferences extends ExtensionPreferences {
|
||||
|
||||
// --- Live wallpaper page --------------------------------------------
|
||||
|
||||
_buildLiveWallpaperPage(settings) {
|
||||
_buildLiveWallpaperPage(settings, gstreamerError) {
|
||||
const page = new Adw.PreferencesPage({title: _('Live Wallpaper'), icon_name: 'video-x-generic-symbolic'});
|
||||
|
||||
if (gstreamerError) {
|
||||
const warningGroup = new Adw.PreferencesGroup();
|
||||
const warningRow = new Adw.ActionRow({
|
||||
title: _('GStreamer Not Found'),
|
||||
subtitle: `${_('Live wallpapers will stay disabled until this is fixed:')} ${gstreamerError}\n\n${GSTREAMER_INSTALL_HINT}`,
|
||||
css_classes: ['warning'],
|
||||
});
|
||||
warningRow.subtitle_lines = 0;
|
||||
warningGroup.add(warningRow);
|
||||
page.add(warningGroup);
|
||||
}
|
||||
|
||||
const group = new Adw.PreferencesGroup({
|
||||
title: _('Video Wallpaper'),
|
||||
description: _(
|
||||
@@ -221,17 +235,19 @@ export default class BenthicBloomPreferences extends ExtensionPreferences {
|
||||
fileRow.add_suffix(chooseButton);
|
||||
group.add(fileRow);
|
||||
|
||||
group.add(this._switchRow(
|
||||
const muteRow = this._switchRow(
|
||||
settings, SettingsKey.LIVE_WALLPAPER_MUTED,
|
||||
_('Mute Audio'), _('Play video wallpapers without sound')));
|
||||
group.add(this._spinRow(
|
||||
_('Mute Audio'), _('Play video wallpapers without sound'));
|
||||
group.add(muteRow);
|
||||
const rateRow = this._spinRow(
|
||||
{
|
||||
title: _('Playback Speed'),
|
||||
subtitle: _('Multiplier, e.g. 0.5 for half speed, 2.0 for double speed'),
|
||||
lower: 0.1, upper: 4.0, step: 0.1, page: 0.5, digits: 1,
|
||||
},
|
||||
() => settings.get_double(SettingsKey.LIVE_WALLPAPER_PLAYBACK_RATE),
|
||||
value => settings.set_double(SettingsKey.LIVE_WALLPAPER_PLAYBACK_RATE, value)));
|
||||
value => settings.set_double(SettingsKey.LIVE_WALLPAPER_PLAYBACK_RATE, value));
|
||||
group.add(rateRow);
|
||||
|
||||
const powerGroup = new Adw.PreferencesGroup({title: _('Power Saving')});
|
||||
page.add(powerGroup);
|
||||
@@ -242,6 +258,16 @@ export default class BenthicBloomPreferences extends ExtensionPreferences {
|
||||
settings, SettingsKey.LIVE_WALLPAPER_PAUSE_WHEN_FULLSCREEN,
|
||||
_('Pause When Fullscreen'), _('Stop video playback while a window is fullscreen')));
|
||||
|
||||
// The enable switch itself stays usable so the setting can be
|
||||
// prepared ahead of time, but everything that only matters once
|
||||
// GStreamer is actually driving playback is greyed out.
|
||||
if (gstreamerError) {
|
||||
fileRow.sensitive = false;
|
||||
muteRow.sensitive = false;
|
||||
rateRow.sensitive = false;
|
||||
powerGroup.sensitive = false;
|
||||
}
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user