Playback fixes from testing on a television, and a stream picker that shows what
it found. Sideload over 1.0.0 — the About screen prints 1.0.1 (3), which is
how this build is told from the one it replaces.
The remote works while the transport is down
Pressing play/pause or a direction with the controls hidden did nothing: the
buttons were faded to nothing but still held focus, so the focus engine took the
press and the player never saw it. Only Menu got through.
Rebuilt around one rule. The buttons leave the focus graph with the transport, an
invisible full-screen sink takes the remote in their place, and every press is
read at the root of the player against a single ordered policy —
PlayerRemotePolicy, the companion to PlayerExitPolicy, which decides what
Menu means. Any direction, Select or Play/Pause brings the row back; left and
right also seek and leave you holding the scrubber.
Two things had to be measured rather than reasoned about, and both are recorded
where they bite: accessibilityHidden(true) on a focus sink removes it from the
focus system as well as the accessibility tree, and a focus binding read
straight after a write reports the value just written, not what the focus engine
did with it — a retry loop asking the binding whether it succeeded always hears
yes.
The television stays awake
tvOS holds sleep off for a system video controller. The MPV surface is a Metal
layer it knows nothing about, so Sleep After applied during a film exactly as
it would to a menu left on screen. The idle timer is now held for the whole
session — not only while playing, since every buffer stall passes through a
non-playing state and re-arms it.
AVFoundation plays again
Three defects. A link the addon had not escaped left URL(string:) nil and the
controller with no player at all — a black screen with no message, on the engine
that takes the string as it stands. Artwork was fetched with Data(contentsOf:)
while the view was being built, a synchronous download holding the main thread.
And a refusal was only ever a silent hand-off to MPV, so choosing this engine
yourself looked like a button that did nothing; the failure is now named, with a
way back.
Also: the "Preparing stream" cover could outlive playback entirely and sit over a
film already running, because it was set from an event mpv had sometimes already
passed.
The stream picker
The artwork was held at 42% behind a blur and a full-frame gradient — a lot of
machinery for a background nobody can see — while the addon's own description was
clipped to three lines, which is where the codec, the running time, the seeders,
the indexer and the languages live. The picture comes forward, the description is
printed in full, the release filename appears when it adds something, and the
play disc on every row is gone: it said what the focus ring already says, forty
points at a time.
A chip now has to earn its line. Most addons write "BluRay REMUX · HDR10+ ·
TrueHD 7.1" into their text themselves, and repeating each of those underneath
was most of what made a row so tall — so a badge, a size or an indexer is drawn
only when the description has not already said it. An addon that returns a bare
name still gets the full set.
Verification
The player's remote handling is now checked by driving an actual Siri Remote
through XCUIRemote (UITests/), because whether a press reaches the transport
depends on where tvOS put focus, and that only exists at runtime: every
direction, Select, Play/Pause, Menu from an open panel, and operating a button
once the row is back. 48 tests pass.
Everything in the 1.0.0 notes still applies, including the known limits and that
the IPA is unsigned — sign it with your own certificate to sideload.