From 0d8862457b7699ba1170b019e927acf85e375047 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Mon, 27 Jul 2026 22:28:45 +0200 Subject: [PATCH] style(nix): run the repo's own `nix fmt` (nixfmt-rfc-style) over the flake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit flake.nix, packaging/nix/packages.nix and packaging/nix/nixos-module.nix had drifted from the formatter the flake itself declares (`formatter = nixfmt-rfc-style`). Pure reformat — no expression changes — split out so the bun2nix migration that follows is reviewable. Co-Authored-By: Claude Opus 5 (1M context) (cherry picked from commit 927b27c4fade6d646e3ef822678b6738f1e2f28a) --- flake.nix | 78 ++++++--- packaging/nix/nixos-module.nix | 92 ++++++++--- packaging/nix/packages.nix | 288 ++++++++++++++++++--------------- 3 files changed, 281 insertions(+), 177 deletions(-) diff --git a/flake.nix b/flake.nix index 39199228..4f1a0903 100644 --- a/flake.nix +++ b/flake.nix @@ -26,10 +26,12 @@ # The workspace version is the single source of truth (crates/*/Cargo.toml inherit it). version = (builtins.fromTOML (builtins.readFile ./Cargo.toml)).workspace.package.version; - pkgsFor = system: import nixpkgs { - inherit system; - overlays = [ (import rust-overlay) ]; - }; + pkgsFor = + system: + import nixpkgs { + inherit system; + overlays = [ (import rust-overlay) ]; + }; # Pin cargo/rustc EXACTLY to rust-toolchain.toml (channel 1.96.0 + rustfmt/clippy) so a Nix # build, a dev shell and CI all use the identical toolchain — the repo is deliberate about @@ -38,7 +40,8 @@ craneLibFor = pkgs: (crane.mkLib pkgs).overrideToolchain toolchainFor; - packagesFor = system: + packagesFor = + system: let pkgs = pkgsFor system; in @@ -49,17 +52,30 @@ }; in { - packages = forAllSystems (system: - let pf = packagesFor system; - in { - inherit (pf) punktfunk-host punktfunk-client punktfunk-web punktfunk-scripting punktfunk-tray; + packages = forAllSystems ( + system: + let + pf = packagesFor system; + in + { + inherit (pf) + punktfunk-host + punktfunk-client + punktfunk-web + punktfunk-scripting + punktfunk-tray + ; default = pf.punktfunk-host; - }); + } + ); # `nix run .#punktfunk-host -- serve` / `nix run .#punktfunk-client`. - apps = forAllSystems (system: - let pf = packagesFor system; - in { + apps = forAllSystems ( + system: + let + pf = packagesFor system; + in + { punktfunk-host = { type = "app"; program = "${pf.punktfunk-host}/bin/punktfunk-host"; @@ -80,19 +96,30 @@ program = "${pf.punktfunk-scripting}/bin/punktfunk-scripting"; }; default = self.apps.${system}.punktfunk-host; - }); + } + ); # `nix flake check` builds every package (web included — needs its deps hash filled in, see # packaging/nix/README.md). - checks = forAllSystems (system: - let pf = packagesFor system; - in { - inherit (pf) punktfunk-host punktfunk-client punktfunk-web punktfunk-scripting; - }); + checks = forAllSystems ( + system: + let + pf = packagesFor system; + in + { + inherit (pf) + punktfunk-host + punktfunk-client + punktfunk-web + punktfunk-scripting + ; + } + ); # `nix develop` — the pinned toolchain plus every system lib the workspace links, wired so # `cargo build` (all crates, host + client) works out of the box. - devShells = forAllSystems (system: + devShells = forAllSystems ( + system: let pkgs = pkgsFor system; toolchain = toolchainFor pkgs; @@ -134,9 +161,16 @@ PF_FFVK_VULKAN_INCLUDE = "${pkgs.vulkan-headers}/include"; # CMake ≥ 4 rejects the pre-3.5 minimums some vendored C libs (libopus) still declare. CMAKE_POLICY_VERSION_MINIMUM = "3.5"; - LD_LIBRARY_PATH = "/run/opengl-driver/lib:${pkgs.lib.makeLibraryPath [ pkgs.vulkan-loader pkgs.libGL gbm ]}"; + LD_LIBRARY_PATH = "/run/opengl-driver/lib:${ + pkgs.lib.makeLibraryPath [ + pkgs.vulkan-loader + pkgs.libGL + gbm + ] + }"; }; - }); + } + ); formatter = forAllSystems (system: (pkgsFor system).nixfmt-rfc-style); diff --git a/packaging/nix/nixos-module.nix b/packaging/nix/nixos-module.nix index 82e939b1..7a544f7f 100644 --- a/packaging/nix/nixos-module.nix +++ b/packaging/nix/nixos-module.nix @@ -21,22 +21,36 @@ # for a session with `systemctl --user enable --now punktfunk-host` (or set `autoStart = true` for a # headless appliance with `users.users..linger = true`). self: -{ config, lib, pkgs, ... }: +{ + config, + lib, + pkgs, + ... +}: let inherit (lib) - mkEnableOption mkOption mkIf mkMerge mkDefault types - optional optionals optionalString literalExpression - concatStringsSep mapAttrsToList genAttrs; + mkEnableOption + mkOption + mkIf + mkMerge + mkDefault + types + optional + optionals + optionalString + literalExpression + concatStringsSep + mapAttrsToList + genAttrs + ; cfg = config.services.punktfunk; system = pkgs.stdenv.hostPlatform.system; # host.env rendering: booleans → 1/0 (what PUNKTFUNK_* knobs expect), everything else verbatim. - renderVal = v: - if lib.isBool v then (if v then "1" else "0") - else toString v; - renderEnv = attrs: - concatStringsSep "\n" (mapAttrsToList (k: v: "${k}=${renderVal v}") attrs) + "\n"; + renderVal = v: if lib.isBool v then (if v then "1" else "0") else toString v; + renderEnv = + attrs: concatStringsSep "\n" (mapAttrsToList (k: v: "${k}=${renderVal v}") attrs) + "\n"; hostSettingsFile = pkgs.writeText "punktfunk-host.env" (renderEnv cfg.host.settings); @@ -44,10 +58,21 @@ let # ephemeral per-session UDP port the host hole-punches, so nothing fixed to open (see # packaging/linux/punktfunk.ufw). nativeTCP = [ 47990 ]; # mgmt/library REST API (HTTPS + mTLS) - nativeUDP = [ 9777 5353 ]; # QUIC control plane + mDNS + nativeUDP = [ + 9777 + 5353 + ]; # QUIC control plane + mDNS # GameStream/Moonlight-compat fixed ports (opt-in with `host.gamestream`). - gamestreamTCP = [ 47984 47989 48010 ]; - gamestreamUDP = [ 47998 47999 48000 ]; + gamestreamTCP = [ + 47984 + 47989 + 48010 + ]; + gamestreamUDP = [ + 47998 + 47999 + 48000 + ]; in { options.services.punktfunk = { @@ -93,7 +118,13 @@ in }; settings = mkOption { - type = types.attrsOf (types.oneOf [ types.str types.int types.bool ]); + type = types.attrsOf ( + types.oneOf [ + types.str + types.int + types.bool + ] + ); default = { }; example = literalExpression '' { @@ -233,10 +264,12 @@ in config = mkMerge [ # --- shared: whenever either half is enabled ----------------------------------------------- (mkIf (cfg.host.enable || cfg.client.enable) { - assertions = [{ - assertion = system == "x86_64-linux"; - message = "services.punktfunk is x86_64-linux only (desktop NVENC host; no aarch64 build)."; - }]; + assertions = [ + { + assertion = system == "x86_64-linux"; + message = "services.punktfunk is x86_64-linux only (desktop NVENC host; no aarch64 build)."; + } + ]; # The GPU driver libs the binaries dlopen at runtime (libcuda / libnvidia-encode / libEGL / # the Vulkan ICD) live under /run/opengl-driver/lib — provided by hardware.graphics. hardware.graphics.enable = mkDefault true; @@ -257,11 +290,17 @@ in services.udev.path = [ pkgs.coreutils ]; # uinput/uhid: the virtual X360 + DualSense nodes. vhci-hcd: the usbip transport that makes # the virtual Steam Deck a real USB device (Steam Input only adopts USB pads). - boot.kernelModules = [ "uinput" "uhid" "vhci-hcd" ]; + boot.kernelModules = [ + "uinput" + "uhid" + "vhci-hcd" + ]; # `input` group membership for the virtual-gamepad nodes (mirrors the RPM's usermod hint). users.groups.input = { }; - users.users = genAttrs cfg.host.users (_: { extraGroups = [ "input" ]; }); + users.users = genAttrs cfg.host.users (_: { + extraGroups = [ "input" ]; + }); # Status-tray autostart entry (self-gating: `--autostart` exits unless this user runs a host). environment.etc."xdg/autostart/io.unom.Punktfunk.Tray.desktop".source = @@ -281,10 +320,14 @@ in wantedBy = optional cfg.host.autoStart "default.target"; # The host may exec external helpers (pw-dump, sh, and — for the gamescope/kwin backends — # the compositor). Extend this in your config for a headless gamescope/KWin appliance. - path = [ pkgs.bash pkgs.coreutils pkgs.pipewire ]; + path = [ + pkgs.bash + pkgs.coreutils + pkgs.pipewire + ]; serviceConfig = { - ExecStart = "${cfg.host.package}/bin/punktfunk-host serve" - + optionalString cfg.host.gamestream " --gamestream"; + ExecStart = + "${cfg.host.package}/bin/punktfunk-host serve" + optionalString cfg.host.gamestream " --gamestream"; Restart = "on-failure"; RestartSec = 2; EnvironmentFile = @@ -339,7 +382,10 @@ in systemd.user.services.punktfunk-web = { description = "punktfunk management web console"; documentation = [ "https://git.unom.io/unom/punktfunk" ]; - after = [ "punktfunk-web-init.service" "punktfunk-host.service" ]; + after = [ + "punktfunk-web-init.service" + "punktfunk-host.service" + ]; wants = [ "punktfunk-web-init.service" ]; wantedBy = optional cfg.web.autoStart "default.target"; environment = { diff --git a/packaging/nix/packages.nix b/packaging/nix/packages.nix index deb5f061..be4ecd81 100644 --- a/packaging/nix/packages.nix +++ b/packaging/nix/packages.nix @@ -103,7 +103,10 @@ let meta = { homepage = "https://git.unom.io/unom/punktfunk"; - license = with lib.licenses; [ mit asl20 ]; + license = with lib.licenses; [ + mit + asl20 + ]; platforms = [ "x86_64-linux" ]; # NVENC desktop host; matches the RPM's ExclusiveArch: x86_64 maintainers = [ ]; }; @@ -115,156 +118,164 @@ let # runtime (see crates/punktfunk-tray/Cargo.toml), so a tokio-flavoured zbus panics at startup: # "there is no reactor running, must be called from the context of a Tokio 1.x runtime". A separate # invocation keeps the tray's zbus on async-io. (The host package copies this binary into its $out.) - punktfunk-tray = craneLib.buildPackage (commonArgs // { - pname = "punktfunk-tray"; - cargoExtraArgs = "--locked -p punktfunk-tray"; - PUNKTFUNK_BUILD_VERSION = buildVersion; - # Pure-Rust leaf: ksni/zbus talk to the dbus socket, ureq+rustls(ring) + punktfunk-core `tls` — - # nothing to link (no buildInputs) and no GPU driver runpath (it never dlopens libcuda/EGL/vulkan). - meta = meta // { - description = "punktfunk host status tray (Linux StatusNotifierItem)"; - mainProgram = "punktfunk-tray"; - }; - }); + punktfunk-tray = craneLib.buildPackage ( + commonArgs + // { + pname = "punktfunk-tray"; + cargoExtraArgs = "--locked -p punktfunk-tray"; + PUNKTFUNK_BUILD_VERSION = buildVersion; + # Pure-Rust leaf: ksni/zbus talk to the dbus socket, ureq+rustls(ring) + punktfunk-core `tls` — + # nothing to link (no buildInputs) and no GPU driver runpath (it never dlopens libcuda/EGL/vulkan). + meta = meta // { + description = "punktfunk host status tray (Linux StatusNotifierItem)"; + mainProgram = "punktfunk-tray"; + }; + } + ); in { inherit punktfunk-tray; - punktfunk-host = craneLib.buildPackage (commonArgs // { - pname = "punktfunk-host"; - # HOST ONLY — the tray is a separate derivation (see the note above; co-building crashes it). - cargoExtraArgs = - "--locked -p punktfunk-host " - + "--features punktfunk-host/nvenc,punktfunk-host/vulkan-encode"; + punktfunk-host = craneLib.buildPackage ( + commonArgs + // { + pname = "punktfunk-host"; + # HOST ONLY — the tray is a separate derivation (see the note above; co-building crashes it). + cargoExtraArgs = + "--locked -p punktfunk-host " + "--features punktfunk-host/nvenc,punktfunk-host/vulkan-encode"; - PUNKTFUNK_BUILD_VERSION = buildVersion; + PUNKTFUNK_BUILD_VERSION = buildVersion; - buildInputs = [ - ffmpeg # libavcodec/avformat/avutil (NVENC + VAAPI encode), via ffmpeg-next → ffmpeg-sys-next pkg-config - pipewire # libpipewire-0.3 + libspa-0.2 (portal capture + the `pipewire` crate) - libopus # audiopus_sys links system opus via pkg-config (else it vendors a static libopus that mis-links) - wayland # libwayland-client (wlr / KWin fake_input backends) - libxkbcommon # virtual-keyboard keymap build/validate - libGL # src/linux/zerocopy/egl.rs `#[link(name = "GL")]` - gbm # src/linux/zerocopy/egl.rs `#[link(name = "gbm")]` - vulkan-loader # ash (Vulkan-Video encode + the dmabuf→VK bridge); loaded at runtime - ]; + buildInputs = [ + ffmpeg # libavcodec/avformat/avutil (NVENC + VAAPI encode), via ffmpeg-next → ffmpeg-sys-next pkg-config + pipewire # libpipewire-0.3 + libspa-0.2 (portal capture + the `pipewire` crate) + libopus # audiopus_sys links system opus via pkg-config (else it vendors a static libopus that mis-links) + wayland # libwayland-client (wlr / KWin fake_input backends) + libxkbcommon # virtual-keyboard keymap build/validate + libGL # src/linux/zerocopy/egl.rs `#[link(name = "GL")]` + gbm # src/linux/zerocopy/egl.rs `#[link(name = "gbm")]` + vulkan-loader # ash (Vulkan-Video encode + the dmabuf→VK bridge); loaded at runtime + ]; - # KWin resolves a streaming client to a .desktop by matching /proc//exe against `Exec`, so - # the host's authorization .desktop must name the ACTUAL binary path (the store path here). The - # tray/client .desktop Exec lines are rewritten for the same reason (menu launch / autostart). - postInstall = '' - # The status tray, built in its own derivation (see the punktfunk-tray note above) so its zbus - # stays on async-io; ship it in the host's $out so the tray .desktop below resolves it. - install -Dm0755 ${punktfunk-tray}/bin/punktfunk-tray "$out/bin/punktfunk-tray" + # KWin resolves a streaming client to a .desktop by matching /proc//exe against `Exec`, so + # the host's authorization .desktop must name the ACTUAL binary path (the store path here). The + # tray/client .desktop Exec lines are rewritten for the same reason (menu launch / autostart). + postInstall = '' + # The status tray, built in its own derivation (see the punktfunk-tray note above) so its zbus + # stays on async-io; ship it in the host's $out so the tray .desktop below resolves it. + install -Dm0755 ${punktfunk-tray}/bin/punktfunk-tray "$out/bin/punktfunk-tray" - # udev: /dev/uinput + /dev/uhid (virtual gamepads) + the vhci sysfs perms for the virtual Deck. - install -Dm0644 scripts/60-punktfunk.rules "$out/lib/udev/rules.d/60-punktfunk.rules" + # udev: /dev/uinput + /dev/uhid (virtual gamepads) + the vhci sysfs perms for the virtual Deck. + install -Dm0644 scripts/60-punktfunk.rules "$out/lib/udev/rules.d/60-punktfunk.rules" - # KWin Desktop-mode authorization (zkde_screencast + fake_input). Point Exec at the store binary. - install -Dm0644 packaging/linux/io.unom.Punktfunk.Host.desktop \ - "$out/share/applications/io.unom.Punktfunk.Host.desktop" - substituteInPlace "$out/share/applications/io.unom.Punktfunk.Host.desktop" \ - --replace-fail "/usr/bin/punktfunk-host" "$out/bin/punktfunk-host" + # KWin Desktop-mode authorization (zkde_screencast + fake_input). Point Exec at the store binary. + install -Dm0644 packaging/linux/io.unom.Punktfunk.Host.desktop \ + "$out/share/applications/io.unom.Punktfunk.Host.desktop" + substituteInPlace "$out/share/applications/io.unom.Punktfunk.Host.desktop" \ + --replace-fail "/usr/bin/punktfunk-host" "$out/bin/punktfunk-host" - # Status-tray autostart entry + its hicolor status icons. - install -Dm0644 packaging/linux/io.unom.Punktfunk.Tray.desktop \ - "$out/etc/xdg/autostart/io.unom.Punktfunk.Tray.desktop" - substituteInPlace "$out/etc/xdg/autostart/io.unom.Punktfunk.Tray.desktop" \ - --replace-fail "/usr/bin/punktfunk-tray" "$out/bin/punktfunk-tray" - for sz in 22x22 48x48; do - for png in packaging/linux/icons/hicolor/$sz/apps/*.png; do - install -Dm0644 "$png" "$out/share/icons/hicolor/$sz/apps/$(basename "$png")" + # Status-tray autostart entry + its hicolor status icons. + install -Dm0644 packaging/linux/io.unom.Punktfunk.Tray.desktop \ + "$out/etc/xdg/autostart/io.unom.Punktfunk.Tray.desktop" + substituteInPlace "$out/etc/xdg/autostart/io.unom.Punktfunk.Tray.desktop" \ + --replace-fail "/usr/bin/punktfunk-tray" "$out/bin/punktfunk-tray" + for sz in 22x22 48x48; do + for png in packaging/linux/icons/hicolor/$sz/apps/*.png; do + install -Dm0644 "$png" "$out/share/icons/hicolor/$sz/apps/$(basename "$png")" + done done - done - # Reference material: headless session helpers, example env files, the OpenAPI doc. - install -Dm0755 scripts/headless/run-headless-kde.sh "$out/share/punktfunk-host/headless/run-headless-kde.sh" - install -Dm0755 scripts/headless/run-headless-sway.sh "$out/share/punktfunk-host/headless/run-headless-sway.sh" - install -Dm0644 scripts/headless/kde-authorized "$out/share/punktfunk-host/headless/kde-authorized" - install -Dm0644 scripts/headless/punktfunk-sink.conf "$out/share/punktfunk-host/headless/punktfunk-sink.conf" - install -Dm0644 scripts/host.env.example "$out/share/punktfunk-host/host.env.example" - install -Dm0644 packaging/bazzite/host.env "$out/share/punktfunk-host/host.env.bazzite" - install -Dm0644 packaging/kde/host.env "$out/share/punktfunk-host/host.env.kde" - install -Dm0644 api/openapi.json "$out/share/punktfunk-host/openapi.json" - ''; + # Reference material: headless session helpers, example env files, the OpenAPI doc. + install -Dm0755 scripts/headless/run-headless-kde.sh "$out/share/punktfunk-host/headless/run-headless-kde.sh" + install -Dm0755 scripts/headless/run-headless-sway.sh "$out/share/punktfunk-host/headless/run-headless-sway.sh" + install -Dm0644 scripts/headless/kde-authorized "$out/share/punktfunk-host/headless/kde-authorized" + install -Dm0644 scripts/headless/punktfunk-sink.conf "$out/share/punktfunk-host/headless/punktfunk-sink.conf" + install -Dm0644 scripts/host.env.example "$out/share/punktfunk-host/host.env.example" + install -Dm0644 packaging/bazzite/host.env "$out/share/punktfunk-host/host.env.bazzite" + install -Dm0644 packaging/kde/host.env "$out/share/punktfunk-host/host.env.kde" + install -Dm0644 api/openapi.json "$out/share/punktfunk-host/openapi.json" + ''; - # Run AFTER fixup (patchelf --shrink-rpath would otherwise drop /run/opengl-driver/lib, which is - # empty at build time): append the driver runpath so the runtime dlopen of libcuda.so.1 / - # libnvidia-encode.so.1 / libEGL.so.1 / the GPU's libvulkan ICD resolves from the running system. - postFixup = '' - # Only the host dlopens the GPU stack; the tray (its own derivation, copied in above) does not. - addDriverRunpath "$out/bin/punktfunk-host" - ''; + # Run AFTER fixup (patchelf --shrink-rpath would otherwise drop /run/opengl-driver/lib, which is + # empty at build time): append the driver runpath so the runtime dlopen of libcuda.so.1 / + # libnvidia-encode.so.1 / libEGL.so.1 / the GPU's libvulkan ICD resolves from the running system. + postFixup = '' + # Only the host dlopens the GPU stack; the tray (its own derivation, copied in above) does not. + addDriverRunpath "$out/bin/punktfunk-host" + ''; - meta = meta // { - description = "Low-latency desktop/game streaming host (Moonlight-compatible + native punktfunk/1)"; - mainProgram = "punktfunk-host"; - }; - }); + meta = meta // { + description = "Low-latency desktop/game streaming host (Moonlight-compatible + native punktfunk/1)"; + mainProgram = "punktfunk-host"; + }; + } + ); - punktfunk-client = craneLib.buildPackage (commonArgs // { - pname = "punktfunk-client"; - # The session's default `ui` feature pulls skia-safe, whose build DOWNLOADS a prebuilt Skia - # (rust-skia releases) — impossible in Nix's network-less build sandbox, and a from-source Skia - # build needs the full gn/ninja/python toolchain + network-fetched third-party. The `ui` feature - # is explicitly droppable (clients/session/Cargo.toml: "same streaming, stats on stdout only"), - # so build the session without it. The GTK shell (punktfunk-client-linux) is skia-free and full. - # Re-adding the Skia OSD under Nix is tracked in packaging/nix/README.md. - cargoExtraArgs = - "--locked -p punktfunk-client-linux -p punktfunk-client-session " - + "--no-default-features --features punktfunk-client-session/pyrowave"; + punktfunk-client = craneLib.buildPackage ( + commonArgs + // { + pname = "punktfunk-client"; + # The session's default `ui` feature pulls skia-safe, whose build DOWNLOADS a prebuilt Skia + # (rust-skia releases) — impossible in Nix's network-less build sandbox, and a from-source Skia + # build needs the full gn/ninja/python toolchain + network-fetched third-party. The `ui` feature + # is explicitly droppable (clients/session/Cargo.toml: "same streaming, stats on stdout only"), + # so build the session without it. The GTK shell (punktfunk-client-linux) is skia-free and full. + # Re-adding the Skia OSD under Nix is tracked in packaging/nix/README.md. + cargoExtraArgs = + "--locked -p punktfunk-client-linux -p punktfunk-client-session " + + "--no-default-features --features punktfunk-client-session/pyrowave"; - # pf-ffvk runs bindgen over libavutil/hwcontext_vulkan.h, which `#include `. - # There is no /usr/include on NixOS, so hand it the Vulkan-Headers include dir explicitly - # (build.rs turns this into a clang `-I`). libavutil's own include path comes from pkg-config. - PF_FFVK_VULKAN_INCLUDE = "${vulkan-headers}/include"; + # pf-ffvk runs bindgen over libavutil/hwcontext_vulkan.h, which `#include `. + # There is no /usr/include on NixOS, so hand it the Vulkan-Headers include dir explicitly + # (build.rs turns this into a clang `-I`). libavutil's own include path comes from pkg-config. + PF_FFVK_VULKAN_INCLUDE = "${vulkan-headers}/include"; - nativeBuildInputs = commonArgs.nativeBuildInputs ++ [ wrapGAppsHook4 ]; + nativeBuildInputs = commonArgs.nativeBuildInputs ++ [ wrapGAppsHook4 ]; - buildInputs = [ - ffmpeg # FFmpeg decode (pf-client-core) + pf-ffvk links libavutil - pipewire # PipeWire audio playback + mic capture - libopus # audiopus_sys → system opus via pkg-config (Opus decode) - sdl3 # window + gamepads (SDL3 HIDAPI: DualSense touchpad/motion/triggers) - gtk4 # the GTK4 shell (clients/linux, relm4) - libadwaita - glib - librsvg # gdk-pixbuf SVG loader for symbolic icons - gsettings-desktop-schemas - adwaita-icon-theme - libxkbcommon - libGL - vulkan-loader # ash presenter + Vulkan-Video decode (loaded at runtime) - ]; + buildInputs = [ + ffmpeg # FFmpeg decode (pf-client-core) + pf-ffvk links libavutil + pipewire # PipeWire audio playback + mic capture + libopus # audiopus_sys → system opus via pkg-config (Opus decode) + sdl3 # window + gamepads (SDL3 HIDAPI: DualSense touchpad/motion/triggers) + gtk4 # the GTK4 shell (clients/linux, relm4) + libadwaita + glib + librsvg # gdk-pixbuf SVG loader for symbolic icons + gsettings-desktop-schemas + adwaita-icon-theme + libxkbcommon + libGL + vulkan-loader # ash presenter + Vulkan-Video decode (loaded at runtime) + ]; - # wrapGApp needs to run on the real ELF, and addDriverRunpath must run post-shrink — so disable - # the hook's blanket auto-wrap and drive both by hand in postFixup (see the host note above). - dontWrapGApps = true; + # wrapGApp needs to run on the real ELF, and addDriverRunpath must run post-shrink — so disable + # the hook's blanket auto-wrap and drive both by hand in postFixup (see the host note above). + dontWrapGApps = true; - postInstall = '' - # hidraw access for the seated user's DualSense (SDL HIDAPI full-fidelity path). - install -Dm0644 scripts/70-punktfunk-client.rules "$out/lib/udev/rules.d/70-punktfunk-client.rules" + postInstall = '' + # hidraw access for the seated user's DualSense (SDL HIDAPI full-fidelity path). + install -Dm0644 scripts/70-punktfunk-client.rules "$out/lib/udev/rules.d/70-punktfunk-client.rules" - # Desktop launcher — point Exec at the store binary (wrapped below). - install -Dm0644 packaging/linux/io.unom.Punktfunk.desktop \ - "$out/share/applications/io.unom.Punktfunk.desktop" - substituteInPlace "$out/share/applications/io.unom.Punktfunk.desktop" \ - --replace-fail "Exec=punktfunk-client" "Exec=$out/bin/punktfunk-client" - ''; + # Desktop launcher — point Exec at the store binary (wrapped below). + install -Dm0644 packaging/linux/io.unom.Punktfunk.desktop \ + "$out/share/applications/io.unom.Punktfunk.desktop" + substituteInPlace "$out/share/applications/io.unom.Punktfunk.desktop" \ + --replace-fail "Exec=punktfunk-client" "Exec=$out/bin/punktfunk-client" + ''; - postFixup = '' - addDriverRunpath "$out/bin/punktfunk-client" "$out/bin/punktfunk-session" - # Only the GTK shell needs the GApps wrapper (GSETTINGS_SCHEMA_DIR, icon themes, typelibs); - # the ash session binary is not a GTK app. - wrapGApp "$out/bin/punktfunk-client" - ''; + postFixup = '' + addDriverRunpath "$out/bin/punktfunk-client" "$out/bin/punktfunk-session" + # Only the GTK shell needs the GApps wrapper (GSETTINGS_SCHEMA_DIR, icon themes, typelibs); + # the ash session binary is not a GTK app. + wrapGApp "$out/bin/punktfunk-client" + ''; - meta = meta // { - description = "Native Linux punktfunk/1 streaming client (GTK4 shell + Vulkan session)"; - mainProgram = "punktfunk-client"; - }; - }); + meta = meta // { + description = "Native Linux punktfunk/1 streaming client (GTK4 shell + Vulkan session)"; + mainProgram = "punktfunk-client"; + }; + } + ); # --- management web console (punktfunk-web) ------------------------------------------------------ # The browser console every client needs for SPAKE2 PIN pairing + host status: a TanStack Start / @@ -291,7 +302,10 @@ in pname = "punktfunk-web-deps"; inherit version; src = src + "/web"; - nativeBuildInputs = [ bun cacert ]; + nativeBuildInputs = [ + bun + cacert + ]; dontConfigure = true; buildPhase = '' runHook preBuild @@ -322,7 +336,11 @@ in # nodejs: the JS build tools' `.bin` shims are `#!/usr/bin/env node`; patchShebangs (below) # repoints them at this node so they run in the sandbox. bun is still the RUNTIME (the launcher # execs it); node is build-time only, for orval/paraglide/vite. - nativeBuildInputs = [ bun nodejs makeWrapper ]; + nativeBuildInputs = [ + bun + nodejs + makeWrapper + ]; # No cross-derivation dep cache: codegen + the vite build are fully offline (every input is in # the vendored node_modules, the checked-in api/openapi.json, and web/project.inlang). @@ -401,7 +419,10 @@ in pname = "punktfunk-scripting-deps"; inherit version; src = src + "/sdk"; - nativeBuildInputs = [ bun cacert ]; + nativeBuildInputs = [ + bun + cacert + ]; dontConfigure = true; buildPhase = '' runHook preBuild @@ -427,7 +448,10 @@ in stdenvNoCC.mkDerivation { pname = "punktfunk-scripting"; inherit src version; - nativeBuildInputs = [ bun makeWrapper ]; + nativeBuildInputs = [ + bun + makeWrapper + ]; # `bun build --target=bun` bundles the runner CLI to ONE self-contained JS: effect + the SDK # are inlined, and the runner's dynamic `import()` of the operator's plugin files is left as a