Add gSlapper video wallpaper plugin (#152)
* feat: add gSlapper wallpaper plugin * docs: clarify gSlapper installation and testing * docs: state Noctalia v5 requirement * docs: use generated plugin thumbnail * fix: keep gSlapper videos playing by default
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
# gSlapper Wallpaper
|
||||
|
||||
Choose images and video wallpapers from one picker. Apply one file to every
|
||||
detected output or select a different file for each connector.
|
||||
|
||||
> Requires Noctalia v5 and plugin API 19. Noctalia v4 uses a different QML
|
||||
> plugin format and will not list or load this source.
|
||||
|
||||
Video playback uses [gSlapper](https://github.com/Nomadcxx/gSlapper) instead of
|
||||
mpvpaper. gSlapper uses GStreamer rather than libmpv; its README documents lower
|
||||
CPU, memory, and GPU use than mpvpaper. Tests cover Niri, Hyprland, and Sway.
|
||||
|
||||
## Plugin
|
||||
|
||||
| Field | Value |
|
||||
| --- | --- |
|
||||
| ID | `nomadcxx/gslapper` |
|
||||
| Entries | Bar widget: `wallpaper`; panel: `picker`; service: `service` |
|
||||
|
||||
## Requirements
|
||||
|
||||
- `find` indexes the wallpaper roots
|
||||
- [gSlapper](https://github.com/Nomadcxx/gSlapper) 1.5.2 or newer provides the
|
||||
`gslapper` command and renders video wallpapers
|
||||
- `gst-launch-1.0` creates image and video previews
|
||||
- `pkill` cleans up a plugin-owned process if its socket stops responding
|
||||
- `socat` sends gSlapper IPC commands
|
||||
|
||||
Arch Linux provides `gst-launch-1.0` in `gstreamer`. Debian and Ubuntu provide
|
||||
it in `gstreamer1.0-tools`. Preview generation can fail without blocking image
|
||||
selection or video playback.
|
||||
|
||||
## Install
|
||||
|
||||
Add the canonical repository as a custom plugin source:
|
||||
|
||||
1. Open **Settings → Plugins → Sources**.
|
||||
2. Choose **Add custom repository**.
|
||||
3. Enter `https://github.com/Nomadcxx/noctalia-gslapper`.
|
||||
4. Open **Settings → Plugins → Install** and select **gSlapper Wallpaper**.
|
||||
|
||||
Or install it from a shell:
|
||||
|
||||
```sh
|
||||
noctalia msg plugins source add gslapper git https://github.com/Nomadcxx/noctalia-gslapper
|
||||
noctalia msg plugins enable nomadcxx/gslapper
|
||||
```
|
||||
|
||||
Choose this source or the Noctalia community source. If you add both, Noctalia
|
||||
uses the copy from the last user source. Remove the other source with:
|
||||
|
||||
```sh
|
||||
noctalia msg plugins source remove <source-name>
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
In Noctalia Settings, open your existing bar, choose a widget section, select
|
||||
Add Widget, then add **gSlapper Wallpaper**. You can remove Noctalia's
|
||||
Wallpaper widget if you want one wallpaper button.
|
||||
|
||||
Left-click the gSlapper widget to open the picker. Select **All outputs** or a
|
||||
connector such as `eDP-1` or `DP-1`, then choose an image or video. The All
|
||||
view can pause assigned videos or restore every output.
|
||||
|
||||
Toggle the picker from a shell:
|
||||
|
||||
```sh
|
||||
noctalia msg panel-toggle nomadcxx/gslapper:picker
|
||||
```
|
||||
|
||||
The service indexes your image and video roots when Noctalia starts. It creates
|
||||
224 by 126 JPEG previews in the plugin data directory. The picker shows 24
|
||||
media files per page in a four-column grid and lists child folders in a
|
||||
separate selector.
|
||||
|
||||
## Settings
|
||||
|
||||
| Setting | Default | Description |
|
||||
| --- | --- | --- |
|
||||
| Video directory | `~/Videos/Wallpapers` | Root for video wallpapers. Noctalia's wallpaper directory supplies images. |
|
||||
| Video scale | `fill` | Uses gSlapper's fill, stretch, original, or panscan scaling mode. |
|
||||
| When hidden | `none` | Keeps playing unless you select Auto Pause or Auto Stop. |
|
||||
| Loop videos | On | Restarts video playback at the end. |
|
||||
| FPS cap | `30` | Caps video wallpaper playback at 30, 60, or 100 FPS. |
|
||||
| Fade between videos | Off | Enables gSlapper's fade transition. |
|
||||
| Fade duration | `0.5` seconds | Sets the transition duration when you enable fading. |
|
||||
| Additional GStreamer options | Empty | Appends options to gSlapper's GStreamer option list. |
|
||||
| Widget glyph | `wallpaper-selector` | Changes the icon shown in the bar. |
|
||||
|
||||
The service restarts active video wallpapers after you change a playback
|
||||
setting.
|
||||
|
||||
## Self-check
|
||||
|
||||
Run the built-in model and trust-boundary checks with:
|
||||
|
||||
```sh
|
||||
noctalia msg plugin nomadcxx/gslapper:service all self-test
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- The plugin starts one `gslapper` process and one Unix socket under
|
||||
`$XDG_RUNTIME_DIR/noctalia-gslapper/` for each output with a video.
|
||||
- The plugin stores assignments, its self-check report, its media index, and
|
||||
cached preview JPEGs in Noctalia's plugin data directory. It makes no network
|
||||
requests.
|
||||
- The picker skips filenames that do not use UTF-8.
|
||||
- Static images use Noctalia's wallpaper renderer. For video assignments, the
|
||||
plugin disables Noctalia's wallpaper surface on that output while gSlapper
|
||||
owns it, then restores the native surface when you select **Restore**.
|
||||
- Use **Restore all** before disabling or reloading the plugin. This stops its
|
||||
processes, removes its sockets, and re-enables Noctalia's wallpaper surfaces.
|
||||
- The current plugin API does not report static wallpaper changes made outside
|
||||
this plugin, so its saved image assignment can become stale.
|
||||
- Assignments follow connector names, not monitor serial numbers. Review them
|
||||
after GPU, dock, or cabling changes that rename outputs.
|
||||
+1002
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,111 @@
|
||||
id = "nomadcxx/gslapper"
|
||||
name = "gSlapper Wallpaper"
|
||||
version = "0.1.1"
|
||||
plugin_api = 19
|
||||
author = "Nomadcxx"
|
||||
license = "MIT"
|
||||
dependencies = ["find", "gslapper", "gst-launch-1.0", "pkill", "socat"]
|
||||
tags = ["bar", "panel", "service", "video", "wallpaper"]
|
||||
icon = "wallpaper-selector"
|
||||
description = "Choose an image or video wallpaper for each output."
|
||||
|
||||
[[setting]]
|
||||
key = "video_directory"
|
||||
type = "folder"
|
||||
label_key = "settings.video_directory.label"
|
||||
description_key = "settings.video_directory.description"
|
||||
default = "~/Videos/Wallpapers"
|
||||
|
||||
[[setting]]
|
||||
key = "scale"
|
||||
type = "select"
|
||||
label_key = "settings.scale.label"
|
||||
description_key = "settings.scale.description"
|
||||
default = "fill"
|
||||
options = [
|
||||
{ value = "fill", label_key = "settings.scale.options.fill" },
|
||||
{ value = "stretch", label_key = "settings.scale.options.stretch" },
|
||||
{ value = "original", label_key = "settings.scale.options.original" },
|
||||
{ value = "panscan", label_key = "settings.scale.options.panscan" },
|
||||
]
|
||||
|
||||
[[setting]]
|
||||
key = "hidden_behavior"
|
||||
type = "select"
|
||||
label_key = "settings.hidden_behavior.label"
|
||||
description_key = "settings.hidden_behavior.description"
|
||||
default = "none"
|
||||
options = [
|
||||
{ value = "none", label_key = "settings.hidden_behavior.options.none" },
|
||||
{ value = "auto-pause", label_key = "settings.hidden_behavior.options.auto_pause" },
|
||||
{ value = "auto-stop", label_key = "settings.hidden_behavior.options.auto_stop" },
|
||||
]
|
||||
|
||||
[[setting]]
|
||||
key = "loop"
|
||||
type = "bool"
|
||||
label_key = "settings.loop.label"
|
||||
description_key = "settings.loop.description"
|
||||
default = true
|
||||
|
||||
[[setting]]
|
||||
key = "fps_cap"
|
||||
type = "select"
|
||||
label_key = "settings.fps_cap.label"
|
||||
description_key = "settings.fps_cap.description"
|
||||
default = "30"
|
||||
options = [
|
||||
{ value = "30", label_key = "settings.fps_cap.options.fps_30" },
|
||||
{ value = "60", label_key = "settings.fps_cap.options.fps_60" },
|
||||
{ value = "100", label_key = "settings.fps_cap.options.fps_100" },
|
||||
]
|
||||
|
||||
[[setting]]
|
||||
key = "fade"
|
||||
type = "bool"
|
||||
label_key = "settings.fade.label"
|
||||
description_key = "settings.fade.description"
|
||||
default = false
|
||||
|
||||
[[setting]]
|
||||
key = "fade_duration"
|
||||
type = "double"
|
||||
label_key = "settings.fade_duration.label"
|
||||
description_key = "settings.fade_duration.description"
|
||||
default = 0.5
|
||||
min = 0.1
|
||||
max = 5.0
|
||||
step = 0.1
|
||||
visible_when = { key = "fade", values = ["true"] }
|
||||
|
||||
[[setting]]
|
||||
key = "gst_options"
|
||||
type = "string"
|
||||
label_key = "settings.gst_options.label"
|
||||
description_key = "settings.gst_options.description"
|
||||
default = ""
|
||||
advanced = true
|
||||
|
||||
[[setting]]
|
||||
key = "glyph"
|
||||
type = "glyph"
|
||||
label_key = "settings.glyph.label"
|
||||
description_key = "settings.glyph.description"
|
||||
default = "wallpaper-selector"
|
||||
|
||||
[[service]]
|
||||
id = "service"
|
||||
entry = "service.luau"
|
||||
|
||||
[[panel]]
|
||||
id = "picker"
|
||||
entry = "panel.luau"
|
||||
width = 980
|
||||
height = 1100
|
||||
placement = "attached"
|
||||
position = "auto"
|
||||
keyboard_focus = "exclusive"
|
||||
|
||||
[[widget]]
|
||||
id = "wallpaper"
|
||||
entry = "widget.luau"
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
@@ -0,0 +1,102 @@
|
||||
{
|
||||
"panel": {
|
||||
"title": "Wallpaper",
|
||||
"media_count": "{count} items",
|
||||
"thumbnail_unavailable": "Video preview unavailable",
|
||||
"settings": "Settings",
|
||||
"close": "Close",
|
||||
"search": "Search wallpapers",
|
||||
"all_outputs": "All outputs",
|
||||
"filter_all": "All",
|
||||
"filter_images": "Images",
|
||||
"filter_videos": "Videos",
|
||||
"folders": "Folders",
|
||||
"up": "Up",
|
||||
"checking_dependencies": "Checking video support…",
|
||||
"scanning": "Indexing wallpaper library…",
|
||||
"preparing_library": "Preparing wallpaper library…",
|
||||
"generating_previews": "Generating previews · {count} / {total}",
|
||||
"video_unavailable": "Video wallpapers are unavailable",
|
||||
"video_badge": "VIDEO",
|
||||
"partial_badge": "{count} / {total}",
|
||||
"mixed_summary": "{outputs} outputs · {videos} video · {images} image",
|
||||
"pause_videos": "Pause videos",
|
||||
"resume_videos": "Resume videos",
|
||||
"restore_all": "Restore all",
|
||||
"pause": "Pause",
|
||||
"resume": "Resume",
|
||||
"restore": "Restore",
|
||||
"status_static": "Static",
|
||||
"status_starting": "Starting",
|
||||
"status_playing": "Playing",
|
||||
"status_paused": "Paused",
|
||||
"status_error": "Error",
|
||||
"applying": "Applying wallpaper…",
|
||||
"navigation_blocked": "The selected directory is outside its wallpaper root.",
|
||||
"directory_unreadable": "Directory unavailable",
|
||||
"directory_empty": "No supported wallpapers in this directory",
|
||||
"no_search_results": "No wallpapers match your search",
|
||||
"page": "{page} / {pages}"
|
||||
},
|
||||
"widget": {
|
||||
"tooltip": "Choose wallpaper"
|
||||
},
|
||||
"service": {
|
||||
"self_test_passed": "Self-test passed.",
|
||||
"self_test_failed": "Self-test failed."
|
||||
},
|
||||
"settings": {
|
||||
"video_directory": {
|
||||
"label": "Video directory",
|
||||
"description": "Directory containing video wallpapers."
|
||||
},
|
||||
"scale": {
|
||||
"label": "Video scale",
|
||||
"description": "How videos fit the output.",
|
||||
"options": {
|
||||
"fill": "Fill",
|
||||
"stretch": "Stretch",
|
||||
"original": "Original",
|
||||
"panscan": "Panscan"
|
||||
}
|
||||
},
|
||||
"hidden_behavior": {
|
||||
"label": "When hidden",
|
||||
"description": "Playback control when the wallpaper is hidden.",
|
||||
"options": {
|
||||
"none": "None",
|
||||
"auto_pause": "Auto Pause",
|
||||
"auto_stop": "Auto Stop"
|
||||
}
|
||||
},
|
||||
"loop": {
|
||||
"label": "Loop videos",
|
||||
"description": "Restart a video when it reaches the end."
|
||||
},
|
||||
"fps_cap": {
|
||||
"label": "FPS cap",
|
||||
"description": "Maximum video wallpaper frame rate.",
|
||||
"options": {
|
||||
"fps_30": "30",
|
||||
"fps_60": "60",
|
||||
"fps_100": "100"
|
||||
}
|
||||
},
|
||||
"fade": {
|
||||
"label": "Fade between videos",
|
||||
"description": "Use a fade when changing media."
|
||||
},
|
||||
"fade_duration": {
|
||||
"label": "Fade duration",
|
||||
"description": "Fade duration in seconds."
|
||||
},
|
||||
"gst_options": {
|
||||
"label": "Additional GStreamer options",
|
||||
"description": "Extra options passed to gSlapper's GStreamer pipeline."
|
||||
},
|
||||
"glyph": {
|
||||
"label": "Widget glyph",
|
||||
"description": "Glyph shown in the bar."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
--!nonstrict
|
||||
|
||||
local PANEL_ID = "nomadcxx/gslapper:picker"
|
||||
|
||||
local function render()
|
||||
barWidget.setGlyph(noctalia.getConfig("glyph") or "wallpaper-selector")
|
||||
barWidget.setTooltip(noctalia.tr("widget.tooltip"))
|
||||
end
|
||||
|
||||
function onClick()
|
||||
noctalia.togglePanel(PANEL_ID)
|
||||
end
|
||||
|
||||
function onConfigChanged()
|
||||
render()
|
||||
end
|
||||
|
||||
render()
|
||||
Reference in New Issue
Block a user