# Flatpak manifest for the native punktfunk Linux client (crate punktfunk-client-linux, # binary `punktfunk-client`). Built into a single-file `.flatpak` bundle and published to # Gitea's generic package registry (see .gitea/workflows/flatpak.yml + packaging/flatpak/README.md). # # Why flatpak for the CLIENT (the host stays an RPM/deb — see packaging/README.md "Why not # Flatpak"): on SteamOS the Steam Deck's /usr is read-only and image-based, so a bare # `punktfunk-client` binary in ~/.local/bin can't bring its own libadwaita / SDL3 (both # MISSING from the SteamOS system) — but flatpak is the Deck's native, update-survivable app # path (the user already runs Moonlight + chiaki-ng as flatpaks). Unlike the host, the client # is sandbox-friendly: it only needs the GPU render node, the host PipeWire socket, the # network, Wayland, hidraw for DualSense, and its config dir — all expressible as finish-args. # # Runtime: GNOME 50 ships GTK 4.20 and libadwaita 1.8 — both far exceed the crate floors # (gtk4 0.11 "v4_16", libadwaita 0.9 "v1_5"). GNOME 50 is built on freedesktop-sdk 25.08, so # `org.freedesktop.Sdk.Extension.rust-stable` resolves to //25.08 (rustc 1.96 — the GTK4 dep # chain, e.g. pango-sys 0.22, needs >= 1.92, which the older GNOME-48/24.08 rust-stable at 1.89 # could NOT satisfy). GNOME 50 is also a *supported* runtime (GNOME 48 went EOL in March 2026). # libopus and the PipeWire client lib are in the freedesktop base; SDL3 is NOT, so it is built # from source as a bundled module. # # HEVC decode: the base runtime's libavcodec is a stripped build (no encumbered codecs). The # freedesktop runtime declares `org.freedesktop.Platform.codecs-extra` as a built-in extension # point (directory lib/x86_64-linux-gnu/codecs-extra, add-ld-path lib, auto-downloaded with the # runtime), whose full libavcodec.so.61 transparently shadows the base one at runtime. So HEVC # (software + VAAPI) works with NO app-side codec extension to declare — we just build against # the SDK's linkable libavcodec.so.61 and let the runtime swap in the capable build. app-id: io.unom.Punktfunk runtime: org.gnome.Platform runtime-version: '50' sdk: org.gnome.Sdk # Build-time SDK extensions: # - rust-stable: cargo/rustc 1.96 + the bundled mold linker (/usr/lib/sdk/rust-stable/bin). # - llvm20: provides libclang (/usr/lib/sdk/llvm20/lib), which bindgen needs — ffmpeg-sys-next # and sdl3-sys generate their FFI bindings via bindgen at build time. The base SDK ships no # clang/libclang, so without this the build panics ("Unable to find libclang"). # Both are added to PATH / LIBCLANG_PATH in build-options below. sdk-extensions: - org.freedesktop.Sdk.Extension.rust-stable - org.freedesktop.Sdk.Extension.llvm20 command: punktfunk-client cleanup: - /include - /lib/pkgconfig - /lib/cmake - /share/aclocal - /man - /share/man - '*.a' - '*.la' finish-args: # --- display --- - --socket=wayland # GTK4 native Wayland window (the client is Wayland-first) - --socket=fallback-x11 # Xwayland fallback when no Wayland socket is exposed - --share=ipc # required alongside X11 for shared-memory surfaces # --- GPU + all input devices --- # --device=all (not just --device=dri): covers the GPU render node (VAAPI HEVC decode + GL), # evdev joysticks, AND the hidraw CHAR devices SDL3's HIDAPI needs for DualSense touchpad/ # motion/adaptive-triggers/lightbar. flatpak cannot bind individual /dev/hidrawN via # --filesystem (they are char devices — "unsupported type 0o20000"), and there is no granular # --device=hidraw; --device=all is what game/emulator flatpaks (RetroArch, Dolphin) use. We # self-host via the Gitea generic registry — NOT Flathub — so its --device=all review rule # does not apply. - --device=all - --filesystem=/run/udev:ro # SDL/HIDAPI enumerates devices via udev # --- audio: PipeWire via its PulseAudio shim — covers playback AND mic uplink. SteamOS # exposes PipeWire-pulse here; --socket=pulseaudio is the portable arg Moonlight/chiaki # also use on the Deck (a bare --socket=pipewire would also need the camera/portal dance # for capture; the pulse shim gives mic + speaker in one grant). --- - --socket=pulseaudio # --- network: QUIC control + UDP data plane + mDNS discovery (_punktfunk._udp) --- - --share=network # --- persistent client identity / pairing store (shared with punktfunk-client-rs) --- - --filesystem=~/.config/punktfunk:create # client-{cert,key}.pem, known-hosts, settings build-options: append-path: /usr/lib/sdk/rust-stable/bin:/usr/lib/sdk/llvm20/bin # The rust build resolves everything via pkg-config: gtk4/libadwaita/pipewire/opus AND a # linkable libavcodec.so.61 from org.gnome.Sdk//50 (the multiarch /usr dir), plus the bundled # SDL3's .pc from /app. (At runtime the codecs-extra extension swaps in the HEVC-capable # libavcodec — see the header.) env: PKG_CONFIG_PATH: /app/lib/pkgconfig:/usr/lib/x86_64-linux-gnu/pkgconfig:/usr/lib/pkgconfig # bindgen (ffmpeg-sys-next / sdl3-sys) loads libclang from the llvm20 extension. LIBCLANG_PATH: /usr/lib/sdk/llvm20/lib # mold (shipped in rust-stable) speeds the ~450-crate link on the Deck APU. RUSTFLAGS: -C link-arg=-fuse-ld=mold modules: # --------------------------------------------------------------------------------------- # SDL3 — NOT provided as a linkable libSDL3.so.0 by org.gnome.Platform/freedesktop-sdk # 25.08, and there is no SDL3 recipe in flathub/shared-modules. Build it from source. # Pinned to 3.4.10 to match the crate exactly: sdl3-sys is `0.6.6+SDL-3.4.10`, i.e. its # bindings target SDL 3.4.10 — building an older SDL risks missing symbols at link time. # HIDAPI is enabled (DualSense touchpad/motion/triggers/lightbar over hidraw). # --------------------------------------------------------------------------------------- - name: sdl3 buildsystem: cmake-ninja config-opts: - -DCMAKE_BUILD_TYPE=Release - -DSDL_SHARED=ON - -DSDL_STATIC=OFF - -DSDL_HIDAPI=ON # DualSense full fidelity over hidraw - -DSDL_TEST_LIBRARY=OFF - -DSDL_EXAMPLES=OFF sources: - type: archive url: https://github.com/libsdl-org/SDL/releases/download/release-3.4.10/SDL3-3.4.10.tar.gz # `sha256sum SDL3-3.4.10.tar.gz` (verified 2026-06-15). Bump url + sha together. sha256: 12b34280415ec8418c864408b93d008a20a6530687ee613d60bfbd20411f2785 x-checker-data: type: anitya project-id: 4974 stable-only: true url-template: https://github.com/libsdl-org/SDL/releases/download/release-$version/SDL3-$version.tar.gz cleanup: - /bin - /include - /lib/cmake - /lib/pkgconfig # --------------------------------------------------------------------------------------- # The client. cargo-sources.json is the GENERATED offline crate cache: # python3 flatpak-cargo-generator.py Cargo.lock -o packaging/flatpak/cargo-sources.json # (run from the repo root; the CI step does exactly this). With it present the build is fully # offline (CARGO_NET_OFFLINE). For quick LOCAL iteration WITHOUT regenerating it, drop the # cargo-sources.json source and pass --build-args=--share=network to flatpak-builder # (non-reproducible; cargo fetches from crates.io during the build). # --------------------------------------------------------------------------------------- - name: punktfunk-client buildsystem: simple build-options: env: CARGO_HOME: /run/build/punktfunk-client/cargo CARGO_NET_OFFLINE: 'true' build-commands: - cargo --offline build --release --locked -p punktfunk-client-linux - install -Dm0755 target/release/punktfunk-client ${FLATPAK_DEST}/bin/punktfunk-client # Desktop entry (renamed to the app id; Exec is the in-sandbox binary). - install -Dm0644 packaging/flatpak/io.unom.Punktfunk.desktop ${FLATPAK_DEST}/share/applications/io.unom.Punktfunk.desktop # AppStream metainfo (required for a well-formed flatpak / Software listings). - install -Dm0644 packaging/flatpak/io.unom.Punktfunk.metainfo.xml ${FLATPAK_DEST}/share/metainfo/io.unom.Punktfunk.metainfo.xml # Scalable icon named for the app id (GNOME runtime renders SVG via librsvg). - install -Dm0644 packaging/flatpak/io.unom.Punktfunk.svg ${FLATPAK_DEST}/share/icons/hicolor/scalable/apps/io.unom.Punktfunk.svg sources: # The repo checkout. For a Flathub/published build, replace with a pinned git source: # - type: git # url: https://git.unom.io/unom/punktfunk # tag: vX.Y.Z # commit: # For ON-DECK / CI builds we build the checked-out working tree in place: - type: dir path: ../.. # Generated offline crate cache (see the comment block above). Remove for --share=network. - cargo-sources.json