Files
lhns--steam-frame-nix/modules/jellyfin.nix
T
Pierre Kisters 69909f5b4c jellyfin: hardware decoding through a desktop entry, not an override
The shim's permissions (devices=all, its store path, LD_PRELOAD,
SFN_MPV_HWDEC) were a Flatpak override: through nix-flatpak's
services.flatpak.overrides, whose override file outlives the
configuration (it left an empty file behind), or a Home Manager link that
`flatpak override --user` would replace (hence `force`). Now a desktop
entry shadowing the Flatpak's (same ID, same fields and actions; also what
the "+" menu sees) passes them as `flatpak run` options
(--device=all --filesystem=<shim>:ro --env=...), so nothing is written to
Flatpak's overrides and they disappear with the entry.
jellyfin.hardwareDecoding.command is that command line for a terminal.

The entries earlier versions put into the override file are removed by
steam-frame-nix-cleanup. Checked with `flatpak run ... --command=sh`: the
shim's store path is visible read-only, the environment is set and
/dev/video* is there.
2026-09-29 00:08:10 +02:00

101 lines
3.6 KiB
Nix

# Hardware video decoding for the Jellyfin Desktop Flatpak
# (org.jellyfin.JellyfinDesktop; installing it is up to the user).
# The Frame's decoder is a V4L2 M2M device (qcom-iris, /dev/video*): the
# Flatpak's devices=dri doesn't expose it (nothing finer than devices=all
# exists), and Jellyfin hard-sets mpv's hwdec=auto-copy, whose probe list
# leaves out V4L2 M2M, without a way to pass mpv options. So:
# - an LD_PRELOAD shim (jellyfin/mpv-hwdec-shim.c) rewrites an "auto*" hwdec
# to $SFN_MPV_HWDEC. Preloaded from the store: only its store path is
# exposed (read-only) to the sandbox.
# - a desktop entry shadowing the Flatpak's (same ID, also seen by the "+"
# menu) starts it with those permissions as `flatpak run` options
# (--device=all, --filesystem, --env): nothing is written to Flatpak's
# override files, so they apply only to launches from this entry and
# disappear with it.
# Earlier versions used an override file (nix-flatpak or Home Manager);
# steam-frame-nix-cleanup removes their entries.
{ config, lib, pkgs, ... }:
let
cfg = config.steamFrame.jellyfin.hardwareDecoding;
app = "org.jellyfin.JellyfinDesktop";
shim = pkgs.callPackage ./jellyfin/shim.nix { };
run = lib.concatStringsSep " " [
"flatpak run --branch=stable --arch=aarch64 --command=jellyfin-desktop"
"--device=all"
"--filesystem=${shim}:ro"
"--env=LD_PRELOAD=${shim}/lib/mpv-hwdec-shim.so"
"--env=SFN_MPV_HWDEC=${cfg.hwdec}"
app
];
in {
imports = [ ./cleanup.nix ];
options.steamFrame.jellyfin.hardwareDecoding = {
enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Hardware video decoding (the Frame's V4L2 decoder) in the Jellyfin
Desktop Flatpak: a desktop entry (shadowing the Flatpak's) that
starts it with device access (devices=all) and an LD_PRELOAD shim
that makes mpv try hwdec's value below. Only launches from that
entry (menus, the "+" menu) get it; nothing is written to Flatpak's
overrides. Takes effect at the next start of Jellyfin.
'';
};
hwdec = lib.mkOption {
type = lib.types.strMatching "[^[:space:]]+";
default = "v4l2m2m-copy,auto-copy";
example = "v4l2m2m-copy";
description = ''
mpv hwdec value used instead of Jellyfin's automatic one ("auto*");
tried in order, software decoding if none handles the stream.
Set as SFN_MPV_HWDEC in the Flatpak's environment.
'';
};
command = lib.mkOption {
type = lib.types.str;
readOnly = true;
default = run;
defaultText = lib.literalMD "`flatpak run … org.jellyfin.JellyfinDesktop` with the options";
description = "The command line the desktop entry runs (for a terminal).";
};
};
# Fields as in the Flatpak's own entry (1.x), which has no MimeType.
config = lib.mkIf cfg.enable {
xdg.dataFile."applications/${app}.desktop".text = ''
[Desktop Entry]
Version=1.0
Name=Jellyfin
Comment=Desktop client for Jellyfin
Exec=${run}
Icon=${app}
Terminal=false
Type=Application
StartupWMClass=${app}
Categories=AudioVideo;Video;Player;TV;
Actions=DesktopF;DesktopW;TVF;TVW
X-Flatpak=${app}
[Desktop Action DesktopF]
Name=Desktop [Fullscreen]
Exec=${run} --fullscreen --desktop
[Desktop Action DesktopW]
Name=Desktop [Windowed]
Exec=${run} --windowed --desktop
[Desktop Action TVF]
Name=TV [Fullscreen]
Exec=${run} --fullscreen --tv
[Desktop Action TVW]
Name=TV [Windowed]
Exec=${run} --windowed --tv
'';
};
}