Commit Graph

111 Commits

Author SHA1 Message Date
enricobuehler 340cbcfe22 fix(packaging): point the packaged systemd unit at /usr/bin/punktfunk-host
ci / web (push) Failing after 46s
apple / swift (push) Successful in 1m17s
ci / rust (push) Successful in 1m19s
ci / docs-site (push) Failing after 42s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 5s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
deb / build-publish (push) Successful in 2m53s
docker / deploy-docs (push) Successful in 17s
rpm / build-publish (push) Successful in 5m17s
scripts/punktfunk-host.service is dev-oriented — its ExecStart references the
source tree (%h/punktfunk/target/release/punktfunk-host). When the deb/rpm ship
it to /usr/lib/systemd/user, a fresh install with no hand-rolled unit would try
to run a binary that isn't there. Rewrite the ExecStart to the installed
/usr/bin/punktfunk-host during packaging (sed in build-deb.sh + the spec); the
source unit stays as-is for from-source dev. Hosts with a custom ~/.config unit
(which shadows the packaged one) are unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 10:25:30 +00:00
enricobuehler 4ff6f447a8 ci(packaging): punktfunk-client .deb + RPM subpackage
Hook the Linux client into the existing packaging CI:

- deb.yml builds both binaries and publishes punktfunk-host AND
  punktfunk-client to the Gitea apt registry; new
  packaging/debian/build-client-deb.sh mirrors the host script
  (shlibdeps auto-Depends — GTK4/libadwaita/SDL3/FFmpeg/PipeWire
  sonames; no NVIDIA filter, the client links no CUDA). Built and
  inspected locally on Ubuntu 26.04.
- punktfunk.spec gains a "client" subpackage (binary + desktop entry +
  udev rule); rpm.yml's publish loop picks it up unchanged.
- New shared assets: packaging/linux/io.unom.Punktfunk.desktop and
  scripts/70-punktfunk-client.rules — DualSense hidraw uaccess (USB +
  Bluetooth, steam-devices style) so SDL's HIDAPI driver gets
  touchpad/motion/lightbar/triggers instead of degrading to evdev.
- Builder images learn the client link deps (rust-ci already had
  them; fedora-rpm adds gtk4/libadwaita/SDL3-devel) with idempotent
  install steps in deb.yml/rpm.yml since jobs run against the
  previous push's image.

Workspace check CI (build/clippy/test) already covers the crate since
f09def4.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 23:18:12 +00:00
enricobuehler 0b1322d1c6 fix(packaging): ship the UDP socket-buffer sysctl in the .deb and .rpm
ci / web (push) Failing after 46s
apple / swift (push) Successful in 1m16s
ci / docs-site (push) Failing after 38s
ci / rust (push) Failing after 1m52s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 7s
deb / build-publish (push) Failing after 2m6s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 2m47s
docker / deploy-docs (push) Successful in 17s
rpm / build-publish (push) Failing after 3m4s
The host requests a 32 MB SO_SNDBUF, but the kernel clamps it to net.core.wmem_max
(~416 KB on a stock box) — so high-bitrate frames overflow the socket buffer and
the host drops a large fraction of packets on send (measured 28.5% loss / 54k
dropped at 1 Gbps to a clean LAN client on a fresh Bazzite box). scripts/99-punktfunk-net.conf
fixes it (32 MB caps) but the packages never installed it. Ship it to
/usr/lib/sysctl.d/ (auto-applied at boot by systemd-sysctl) and apply it in the
deb/rpm postinst. This is the dominant cause of the sub-Gbps ceiling on an
untuned host.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 22:41:45 +00:00
enricobuehler 06346e5037 docs(rpm): use repo_gpgcheck for the unsigned Gitea RPMs
ci / web (push) Failing after 40s
ci / rust (push) Successful in 1m8s
apple / swift (push) Successful in 1m17s
ci / docs-site (push) Failing after 48s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 6s
deb / build-publish (push) Failing after 2m21s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 2m25s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m24s
docker / deploy-docs (push) Successful in 17s
rpm / build-publish (push) Successful in 3m45s
Gitea GPG-signs the repo metadata but not the individual packages, while its
auto-served bazzite.repo sets gpgcheck=1 — so `rpm-ostree install` fails with
"could not be verified" on our unsigned RPMs. Document writing the repo
explicitly with gpgcheck=0 + repo_gpgcheck=1 (verify the signed metadata, which
carries each package checksum) instead of curling the served .repo. Note the
TLS-only fallback and that per-package signing is future hardening.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 22:07:42 +00:00
enricobuehler 58cb416abb ci(rpm): publish punktfunk-host RPM to the Gitea registry (Bazzite)
ci / web (push) Failing after 44s
ci / rust (push) Successful in 1m7s
apple / swift (push) Successful in 1m16s
ci / docs-site (push) Failing after 38s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
deb / build-publish (push) Failing after 2m20s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 2m21s
docker / deploy-docs (push) Successful in 18s
rpm / build-publish (push) Successful in 3m57s
Mirrors the apt pipeline for Fedora Atomic / Bazzite. New `rpm` workflow builds
the host RPM in a Fedora 43 builder image (ci/fedora-rpm.Dockerfile — matches
Bazzite's libavcodec.so.61, with a self-contained 16-symbol libcuda link stub so
no NVIDIA packages are needed in CI) and uploads to Gitea's public RPM registry
(group "bazzite") on every main push (rolling 0.0.1-0.ciN.<sha>) and v* tag
(clean X.Y.Z-1). Bazzite hosts then track it with `rpm-ostree upgrade`.

- packaging/rpm/build-rpm.sh: git-archive tarball + rpmbuild (--nodeps, since the
  toolchain is rustup + dnf, not RPMs); copies to dist/, asserts no cuda/nvidia leak.
- punktfunk.spec: overridable pf_version/pf_release for CI snapshots; exclude
  libcuda.so from auto-Requires (NVENC/EGL come from the driver, out of band) —
  same NVIDIA filter as the .deb; fix a bogus changelog weekday.
- docker.yml builds+pushes the new fedora-rpm image; packaging README + rpm/README
  document the rpm-ostree install/update path (recommended option).

Builder image seeded to the registry so rpm.yml's first run finds it. RPM build +
clean-Requires verified locally in the image (libavcodec.so.61 / libavutil.so.59,
no cuda).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 21:32:46 +00:00
enricobuehler dfed90bff2 ci(deb): publish punktfunk-host .deb to the Gitea apt registry
ci / web (push) Failing after 49s
ci / rust (push) Successful in 1m6s
apple / swift (push) Successful in 1m18s
ci / docs-site (push) Failing after 40s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 6s
docker / deploy-docs (push) Successful in 20s
deb / build-publish (push) Failing after 2m17s
Wires up the half-built Debian packaging: build-deb.sh existed but nothing
invoked or published it. Adds a `deb` workflow that builds the release host in
the Ubuntu 26.04 rust-ci image, packages it (dpkg-shlibdeps-resolved Depends,
NVIDIA driver filtered out), and uploads to Gitea's public Debian registry on
every main push (rolling 0.0.1~ciN.<sha>) and v* tag (clean X.Y.Z). Ubuntu hosts
then track it with `apt update && apt upgrade`.

Also: box-setup docs (packaging/debian/README.md), a pointer from the packaging
README, ignore dist/, and drop backticks from the package Description (the
unquoted control heredoc ran them as a command substitution).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 21:14:40 +00:00
enricobuehler a95984bb4f feat(client-linux): feature parity with the Swift client
Everything the macOS app does that stage 1 lacked, before any new
feature work (user directive):

- Input capture is now a deliberate, reversible STATE (Moonlight-
  style): engaged on stream start and click-into-video (the engaging
  click is suppressed), released by Ctrl+Alt+Shift+Q (toggles) or
  focus loss; held keys/buttons are flushed host-side on release;
  cursor hiding + shortcut inhibition follow the state; HUD hint when
  released. Per-session window handlers disconnect with the page.
- Gamepads: app-lifetime SDL service (GamepadManager parity) — pad
  list + "Forwarded controller" pin in Settings (auto = most recent),
  "Automatic" pad TYPE resolves from the physical pad at connect;
  DualSense touchpad contacts + ~250 Hz motion samples on the 0xCC
  plane (Swift GamepadWire scale constants); feedback grows adaptive-
  trigger replay and player LEDs via raw DS5 effects packets (the
  wire's 11-byte blocks drop into SDL_SendGamepadEffect verbatim);
  held pad state zeroed on pad switch/detach. sdl3 "hidapi" feature.
- Microphone uplink: PipeWire capture -> Opus 20 ms -> 0xCB datagrams
  (validated live: host received 711 mic packets), Settings toggle.
- Speed test per saved host (Swift's "Test Network Speed…"): 2 s
  probe burst, goodput/loss + recommended ~70 % bitrate, one-tap apply.
- Settings: host compositor preference (sent in the Hello), native-
  display resolution/refresh resolved from the window's monitor at
  connect (new default), bitrate ceiling to 3 Gbit/s.
- Hosts page: saved/trusted hosts section for direct pinned reconnect
  (mDNS not required), rebuilt on every page return.

Deliberately not ported: audio device pickers (PipeWire routing owns
this on Linux), resize-to-request_mode (not wired in Swift either),
pointer-lock relative mouse (stage-2 presenter, needs raw Wayland).
DualSense fidelity needs a physical pad to live-verify.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 21:11:52 +00:00
enricobuehler 902cc162f7 docs(bazzite): join the input group via ujust add-user-to-input-group
ci / rust (push) Has been cancelled
On Bazzite (atomic rpm-ostree) `sudo usermod -aG input $USER` doesn't stick —
/etc/group is managed declaratively, so the change is dropped or reverted on
the next update. The supported path is the `ujust add-user-to-input-group`
recipe, which edits the group the immutable-OS-correct way. Update the bazzite
README + the packaging quickstart + the troubleshooting note (which also now
points at the host's "virtual gamepad/DualSense created" vs "creation failed"
log as the unambiguous signal).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 20:32:55 +00:00
enricobuehler 136390514d build: support FFmpeg 7.x and 8.x; fix RPM spec GPU link deps
ci / rust (push) Has been cancelled
punktfunk-host builds unchanged against either FFmpeg 7.x (libavcodec 61) or 8.x
(libavcodec 62) — ffmpeg-sys-next auto-detects the system version, and the host's
ffmpeg FFI only touches long-stable APIs. Confirmed by building + running live on a
Bazzite F43 box (FFmpeg 7.1.3): full gamescope capture → zero-copy dmabuf→CUDA →
NVENC H.265 at 1280x720x60, p50 ~0.96 ms. Just doc/spec accuracy, no code change:

- encode/linux.rs + CLAUDE.md: drop the "FFmpeg 8 only" claim; note 7.x/8.x both work.
- rpm spec: add the missing zero-copy GPU build deps the link actually needs —
  pkgconfig(gl) + pkgconfig(gbm) (mesa) — and document that -lcuda needs libcuda.so at
  link time (NVIDIA host, or the CUDA toolkit stub on a headless COPR/koji builder).
  Tracked for a proper fix: make the cuda/gbm/GL FFI dlopen-based like khronos-egl so
  the RPM builds on a GPU-less host.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 09:12:59 +00:00
enricobuehler 12b047b0ae docs(packaging): add end-to-end Bazzite setup guide
ci / rust (push) Has been cancelled
A step-by-step walkthrough for running the host on Bazzite (the immutable
Fedora-Atomic gaming distro): the two install paths (rpm-ostree layering vs the
bootc image), udev + the `input` group, host.env knobs (gamescope-default), the
systemd --user service, firewall ports, verification, and troubleshooting — all
grounded in the packaging/ files. Flags the operator-run COPR, the loopback-only
mgmt port, and that the bundled unit runs the GameStream `serve` host (not m3-host).
Linked from packaging/README.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 08:40:16 +00:00
enricobuehler 23bb814bac feat(packaging): Fedora/Bazzite packaging — COPR RPM, bootc image, gamescope-default config
Roadmap #3 (install on other devices). Bazzite already ships gamescope + PipeWire + the
NVIDIA stack, so the host slots in with minimal new deps (ffmpeg-libs from RPM Fusion + opus
+ libei).

- packaging/rpm/punktfunk.spec — builds punktfunk-host from source (cargo), installs the
  binary + udev rule + systemd user unit + headless helpers; Requires/Recommends mapped from
  the Ubuntu bootstrap deps to Fedora.
- packaging/bootc/Containerfile — layer punktfunk into a bazzite-nvidia bootc image for
  atomic, image-based installs.
- packaging/bazzite/host.env — gamescope-default appliance config (spawned per session).
- packaging/copr/ + packaging/README.md — COPR build-from-SCM settings + install docs
  (rpm-ostree and bootc paths), and why not Flatpak.
- LICENSE-MIT + LICENSE-APACHE — materialize the declared `MIT OR Apache-2.0` (was unfiled);
  the RPM ships them.

Not buildable on the Ubuntu dev box (no rpm tooling) — the COPR/Fedora build is operator-run;
all spec-referenced files verified present and the cargo build is green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 22:29:01 +00:00