chore(release): bump workspace version to 0.27.0
ci / web (pull_request) Successful in 1m9s
apple / swift (pull_request) Successful in 1m42s
apple / screenshots (pull_request) Skipped
ci / docs-site (pull_request) Successful in 1m21s
ci / bun-nix (pull_request) Successful in 23s
windows / build (x86_64-pc-windows-msvc) (pull_request) Successful in 2m56s
android / android (pull_request) Successful in 8m13s
windows / build (aarch64-pc-windows-msvc) (pull_request) Successful in 1m33s
ci / rust-arm64 (pull_request) Successful in 8m39s
ci / rust (pull_request) Successful in 18m11s
nix / flake (pull_request) Successful in 17m53s

87 commits since v0.26.0. The number is forced rather than chosen: the C ABI moves
17 -> 18, and `scripts/ci/pf-version.sh` already reports PF_BASE=0.27.0.

Fills in what `docs/releases/v0.27.0.md` and the `## v0.27.0 — in development`
CHANGELOG section deferred to the bump -- the lead-in, the TL;DR, "Before you update",
the version table and the commit count -- and merges in the work that landed without
notes: the Windows Xbox HID pad, the Apple console-UI batch, and the v0.26.0 field
repairs. Everything already accumulated on main is kept as written.

Version table, all re-derived at HEAD rather than read off the diff:
  * wire 2 (unchanged), C ABI 17 -> 18 (ADDED symbol, not widened)
  * crate dirs 26 -> 27 (`punktfunk-encode-worker`), 39 members
  * gamescope `+pfhdr4` -> `+pfhdr5` (6 patches -> 7, the PipeWire UAF), pkgrel resets to 1
  * driver proto 6, gamepad channel 3, plugin index 1, SDK 0.1.4, plugin-kit 0.4.0 -- all unchanged
  * `api/openapi.json` stays 0.25.0: it moves only on an API EDIT, and the last one
    (`6cffe29b`) predates the v0.26.0 tag. It is not a mechanical per-release bump.

⚠ `crates/pf-driver-proto` is NO LONGER byte-identical to the previous release -- it was
through both v0.25.0 and v0.26.0, and the last two CHANGELOGs told packagers so. Three
additive `device_type`s. Called out explicitly so a packager who has been skipping it stops.

The Play whatsnew names the one real Android change (the OLED palette is Eclipse now;
display name only, the stored `oled` id is unchanged so saved choices carry over) and is
otherwise explicit that the release is host-side.

`docs-site/.../running-as-a-service.md` claimed "0.26.0-2 revoked it everywhere". No such
version exists -- the Arch registry goes 0.26.0-1 straight to 0.27.0 canaries -- and the
corrected 0.26.0 packages shipped under the SAME version string, which is exactly why a
machine that installed an early one was never offered the fix. Reworded to say that, since
it is the reason this release matters to those users.

Gates, all green on this commit:
  * `cargo fmt --all --check` clean
  * `cargo metadata --locked` resolves
  * `Cargo.lock` diff versions-only -- 72/72 changed lines, 36 crates
  * Play gate's own python3 arithmetic: 400/500 CHARACTERS, not byte-identical to any other
    release (`wc -c` misleads -- `•` is 3 bytes)
  * notes voice check: 1 hit, reviewed and kept -- `getcap /usr/bin/punktfunk-host` is a
    command the reader runs, the same class as the `usermod` line v0.26.0's notes carried
  * `docs-site` builds

NOT DONE: no tag yet.
This commit is contained in:
2026-08-10 20:51:45 +02:00
parent 30c47eb691
commit 147bc82130
6 changed files with 291 additions and 57 deletions
+60 -14
View File
@@ -1,28 +1,74 @@
<!--
Accumulating ahead of the version bump, per docs/releases/README.md: entries are added as work
lands, and the lead-in, the TL;DR and any "Before you update" section are written at the bump,
when the shape of the whole release is known. The angle-bracket lines below are the TEMPLATE.md
placeholders and must be replaced before the tag is pushed. docs/releases/whatsnew/v0.27.0.txt is
still owed and is a hard gate on the android job.
-->
Wire-compatible with 0.26.x — everything you have already paired keeps working, and you can update one side at a time. Nothing here changes how a host and a client agree on what to send each other, so an old client on a new host, or the other way round, streams exactly as it does today.
Wire-compatible with 0.26.x — everything you have already paired keeps working, and you can update one side at a time. <one sentence on how older/newer clients negotiate or fall back, so nobody fears updating.>
<Lead-in: one or two sentences naming the headline change of this release — everything above the first `##` is what the Discord #releases embed shows, so make it read as a standalone summary.>
This release does three things. Streaming performance on Linux finally gets the graphics-card priority it has been asking for since 0.25, without the privilege that broke KDE. An Xbox controller on a Windows host becomes a real controller that games can actually see, with rumble for the first time. And the controller interface on iPad, Apple TV and Mac becomes something you can drive end to end with a controller in your hands — including pairing, which used to be a dead end. Alongside all of it, everything 0.26.0 got wrong in the field is repaired.
## TL;DR
- **<The one thing you would tell someone in a sentence.>**
- **<Second. Anything that needs the reader to ACT goes here too, and in `## Before you update`.>**
- **<Third. Three to six bullets, one line each. This is what a reader sees instead of giving up.>**
- **The wavelet codec can ask your graphics card for priority again**, on every Linux desktop, with the privilege moved to a small separate program so the host never holds one. Worth about a third off the worst frames under a demanding game. Nothing to switch on.
- **An Xbox controller on a Windows host was invisible to games** — not Steam, not the Windows controller panel, not most modern titles. It is a real controller now, and it rumbles. Update the host.
- **HDR streams from an NVIDIA host had red and blue swapped.** Every one of them, on every client. Update the host.
- **A gamescope session crashed on essentially every connect**, black screen, until the machine gave up and came back on the unpatched compositor. Update the host.
- **On NixOS the host could not detect a running desktop at all**, so streaming a desktop never worked. Update the host.
- **You can now pair, trust a host and answer every prompt with a controller** on iPad, Apple TV and Mac — and drive the whole interface from a keyboard. Update the client.
## Before you update
Most people need to do nothing. Check this list if any of it applies to you.
- **Any Linux host you installed on 9 August:** the very first 0.26.0 packages gave the host a system privilege that stops KDE recognising it, and desktop streaming failed outright as a result. Corrected packages went out the same day under the *same* version number, so a machine that installed an early one was never offered the fix. This release carries a new version number and therefore actually reaches it. If you are unsure, `getcap /usr/bin/punktfunk-host` should print nothing at all.
- **Never grant that privilege to the host yourself.** Not by hand, not through a service file, not through a NixOS wrapper. The small helper program beside it is the thing that needs one, and your packages already gave it one.
- **Fedora or Nobara, if the patched compositor refused to install:** `punktfunk-gamescope` was never signed, so installing it failed on every Fedora and Nobara machine even though the package was sitting right there in the repository. It is signed now. Install it again.
- **Fedora or Nobara, if every connect gives you a black screen:** Game Mode needs your user to be in the `punktfunk` group, and nothing said so — the host blamed a missing permission rule instead, and neither remedy it suggested added anyone to a group. Run `sudo usermod -aG punktfunk "$USER"` and log back in. The host now checks this at startup and tells you plainly.
- **Bazzite, if 0.26.0 seemed to change nothing:** the system-extension upgrade is driven by the *old* release's script, so a step added in 0.26.0 was executed by nobody, and every check afterwards reported there was nothing to do. Among the casualties was that same `punktfunk` group. Run `sudo punktfunk-sysext update`, or `sudo punktfunk-sysext reapply` to re-run those steps without reinstalling the image.
- **NixOS:** the plugin runner now starts by default, matching every other packaging. If you do not want it, set `scripting.autoStart = false`.
- **Windows, if you stream with an Xbox controller:** the new controller is the default now. Nothing to do, but if a title behaves oddly with it, `PUNKTFUNK_XBOX_BACKEND=xusb` restores the old one without reinstalling anything.
## New
- **An Xbox controller on a Windows host is a real controller.** Until now it existed only as a companion device, visible to the oldest of Windows' controller interfaces and to nothing else — so Steam, the Windows game controller panel and everything a modern title actually uses could not see it at all. One report spent two weeks on a controller that was, from every angle that mattered, simply absent. It is now built as genuine hardware and promoted by Windows exactly as a real Xbox pad is, so everything that can see a controller sees this one.
- **That controller rumbles.** It never had rumble of any kind — nothing was listening for it. Games now drive it through the ordinary Windows path.
- **Three Xbox models to choose from:** Xbox Wireless Controller, Xbox Wireless Controller (One S), and Xbox Elite Wireless Controller Series 2, so glyphs and the name a game shows match what you picked. The Elite is reachable by setting it explicitly; no client offers it in a menu yet, and its four paddles are not wired up.
- **Pairing you can do with a controller.** On iPhone, iPad and Mac the pairing sheet is a form with text fields, which a controller cannot reach, type into, or submit — so for anyone using the controller interface, the one thing standing between a fresh install and a first stream was a dead end. It is fully pad-driven now. The trust prompt that appears mid-connect takes controller input too, and so do the alerts and confirmations along the way, which were all dead ends for the same reason.
- **Drive the interface from a keyboard.** Asked for by an iPad user on a Magic Keyboard: arrow keys move, Return launches. A couch Mac gets the same.
- **A Shortcut or a home-screen widget can jump straight into a host's library** on Apple devices, landing in whichever view the current mode uses.
- **The controls legend is clickable.** Every hint that names an action is a real button on iPhone, iPad and Mac, so an iPad on a stand or a Mac driven by trackpad can use the interface it was reading.
## Improved
- **The wavelet codec can ask your graphics card for priority again — on every desktop this time.** Under a demanding game it encodes on the same graphics cores the game is using and gets crowded out, and asking the driver to put that work first is worth about a third off the worst frames. It needs a system privilege, and 0.26 could not use it: an interim build gave that privilege to the host, KDE stopped recognising the host as a result, and desktop streaming failed outright — so the privilege was taken away everywhere and the switch sat dormant. The encoding now happens in a small separate program installed alongside the host, and the privilege is granted to **that** program rather than to the host. The host still holds nothing at all, so KDE keeps recognising it, and the priority request works on KDE, GNOME, gamescope and everything else alike. Nothing to switch on. There is also nothing to grant by hand — in particular, do not give the host that privilege yourself, which is still the one thing that takes KDE desktop streaming away. Linux hosts, wavelet-codec sessions only.
- **A host that cannot start that helper simply carries on.** If the program is missing, refuses to start, is a mismatched version, or stops mid-session, the host does the encoding itself exactly as it did before, notes one line in the log, and the stream keeps running. The same is true if the privilege was never granted: the request is refused, the encoding runs at normal priority, and the only cost is frame pacing under a game that is already saturating the graphics card.
- **The controller interface is sized for an iPad.** It had two sizes — Apple TV, and everything else — so a 13" iPad Pro drew its rows, tabs and legend at phone scale across a very large display. There is a size between them now, and the controls pill sits in the display's corner instead of floating well above it.
- **The interface remembers which controller is yours.** The button hints read the live controller, so the moment a DualSense slept or ran flat every ✕/◯ turned into A/B under its owner's hands. They now stay as the pad you actually own.
- **The OLED palette is called Eclipse.** Every other background is named for a place or a material, and "OLED" was a spec sheet sitting among them.
- **When Game Mode cannot take over the screen, the host says exactly why.** It used to discard the one message that explained it and guess instead, naming a permission rule that was installed and working, and offering two remedies that could not have helped. The real reason now comes through word for word, and a startup check raises it before you are mid-stream rather than during one.
- **The console is on the current design system**, and card spacing is fixed at the root rather than worked around in seven places. Dropdowns were the visible casualty of the old one: a near-white border and focus ring, with a chevron and placeholder text so dark they all but disappeared.
- **The Virtual displays page has tabs** — Configuration and Live displays. The configuration card alone is taller than most screens, so the list of live displays was in practice off the bottom of the page.
## Fixed
- **A gamescope session crashed on essentially every connect.** Eleven crashes in three minutes on the machine that surfaced it, until the session supervisor ran out of retries and brought the box up on the unpatched compositor instead — so the visible symptom was a black screen, and then a machine quietly running something other than what you installed.
- **Streaming a desktop never worked on NixOS.** The host works out whether a desktop is running by asking the system what each program is called, and on NixOS essentially every graphical program is wrapped, so the name it gets back is the wrapper's — which matched nothing. Every check answered "no desktop here" on a perfectly ordinary running desktop, and nothing downstream could recover: naming your compositor explicitly turned the miss into a hard error instead. Sway and river escaped by accident.
- **Every HDR stream from an NVIDIA host had red and blue swapped.** The compositor writes those pixels in its own order on NVIDIA hardware while labelling them with the ordinary one, so the host believed a label that was correct at every step while the contents underneath it were reversed — which is why this survived a full trace of both ends. Confirmed against two unrelated clients, so it was never a client fault. Ordinary streams were never affected.
- **Game Mode could never start on Fedora and Nobara.** Nobara's session script names the system compositor outright and ignores every way we have of pointing it somewhere else, so it ran the unpatched one and the host refused it. Once that was solved a second fault appeared behind it: the graphics layer shipped with the distribution speaks a different dialect to the compositor we ship, and it was killing every graphical program before anything could draw, so Steam never appeared. Black screen, no error. Both are handled, and the machine can no longer end up dumped on the plain desktop with a leftover setting that also breaks the next boot.
- **Taking over the screen barred the way back into Game Mode.** The takeover switches off the machine's own session supervisor so it cannot restart underneath the stream, and only switched it back on when the client disconnected — so for the whole stream the button the user was most likely to press did nothing.
- **Connecting to a host paused your music, and resuming it silenced the stream.** The audio session was claiming exclusive use, so it evicted whatever was playing on connect, and handing it back later left the stream mute for good. Both halves were the same defect.
- **Changing your audio device mid-stream killed the sound on a Mac.** Starting a stream with AirPods in and taking them out gave you nothing on the speakers; putting them back in gave you nothing in the AirPods either, and only restarting the whole stream brought it back. The audio engine stops itself when the hardware underneath it changes and nothing was starting it again. It now rebuilds on whatever device is there, including when the microphone and echo cancellation are on, which is the default on a Mac.
- **The library's hide button was invisible and clickable at the same time.** Hiding a title shipped in 0.26.0 and was in practice unusable: the operator reported there was no button, then found it by clicking the empty corner of a poster — which meant anyone could drop a game from their library by accident and never know how.
- **One failure to start the video encoder could take down every session on the machine**, not just the one that failed. Separately, the check that asks whether your card can encode 10-bit was itself enough to wedge every later attempt on an NVIDIA host using the direct path.
- **`punktfunk-gamescope` could not be installed on Fedora or Nobara.** Every copy ever published was unsigned, and the repository we tell you to add requires signatures — so it failed on every machine while both the release notes and the documentation said it was available.
- **Uninstalling on Windows left its audio devices behind forever.** "Punktfunk Speakers", "Punktfunk Microphone" and a per-controller entry stayed in your sound settings after the host was gone, because they are created while it runs rather than installed. Uninstalling now takes them with it, restores whatever playback device you had before if a stream left it switched, and matches only its own — Steam's identically named devices are untouched.
- **A Bazzite system-extension update could report success and change nothing.** Because the old release's script drives the upgrade, a step added in a new release is run by nobody, and every check afterwards said there was nothing to do. That is why 0.26.0 quietly failed to create the group Game Mode needs. Those steps are re-run now, and a `reapply` command re-applies them on demand.
- **The console reported the resolution the client asked for, not the one it got.** When the two differ — and they do, whenever a mode is adjusted on the way up — the number on screen was the request rather than the result.
- **The controller interface's cards flashed once as they settled**, sat at the wrong fill for the whole entrance, and the selected settings tab was white on light grey in one palette.
- **A controller that could not be created blamed the drivers.** When a live stream already held that controller slot — which is entirely legitimate — the host told you to reinstall or repair the drivers, which was never the problem and never helped. It now names what is actually holding the slot.
- **On NixOS three service settings had quietly diverged** from the ones every other packaging ships, including one that could leave the web console permanently stopped if it was enabled before the host's first run.
## For developers
Protocol, ABI, driver and add-on detail — including the version table and any breaking changes — is in [CHANGELOG.md](https://git.unom.io/unom/punktfunk/src/tag/v0.27.0/CHANGELOG.md).
Protocol, ABI, driver and add-on detail — the version table, the new environment variables and what did *not* move — is in [CHANGELOG.md](https://git.unom.io/unom/punktfunk/src/tag/v0.27.0/CHANGELOG.md).
The short version: **nothing breaks.** The wire protocol stays at 2. The C ABI moves 17 → 18, and it moves by *addition* — one new entry point for four-motor rumble, alongside the existing one, which keeps its signature and the values it reports. An embedder that ignores the new symbol behaves exactly as it does today.
If you package Punktfunk, one thing changes shape: there is a second installed binary, `punktfunk-encode-worker`, and it is the **only** file that may carry `cap_sys_nice=ep`. It must stay a separate file — never a hardlink to `punktfunk-host`, never a subcommand of it — because a shared inode shares the file capability and re-creates the KDE breakage. `punktfunk-host` carries no capability, on any channel, ever.
The shared virtual-display and gamepad definitions have also changed for the first time in three releases: three new Xbox controller identities, all additive.
+2
View File
@@ -0,0 +1,2 @@
• The OLED colour scheme is called Eclipse now — the same black-with-a-violet-ember palette, under a name that belongs beside Nebula and Abyss. Your saved choice carries over.
• The rest of this release is on the computer you stream from. Once it updates: HDR streams from an NVIDIA machine no longer have red and blue swapped, and Linux hosts hold their frame rate far better under a demanding game.