Skip to content

AetherEngine 5.17.1

Choose a tag to compare

@superuser404notfound superuser404notfound released this 21 Jul 08:20

Patch release: the wireless-AirPlay LAN-swap reload no longer destroys host subtitle session state (#170).

Fixed

AirPlay LAN-swap reload destroyed host subtitle session state (#170)

Symptom (reported by @dlev02, surfaced by a Prism beta report streaming iOS to tvOS via AirPlay): when wireless AirPlay engages or ends, the engine reloads itself to move the loopback playlist onto the device's LAN IP and back (#86). That reload was a from-scratch load() driven by LoadOptions alone, and it wiped three pieces of session state the host had set up, none of which were restored:

  1. Mid-session addExternalSubtitleTrack registrations (#88) were gone. The host's menu kept listing them, but selecting one targeted a synthetic id that no longer existed ("the subtitle selection dropdown is tripping out").
  2. The active audio/subtitle selection was re-derived by preferred-language auto-selection, silently overriding the user's explicit picks, including subtitles they had turned off.
  3. nativeSubtitleReapplyOrdinal was nil'd. The host reacts to the AirPlay flip by calling setNativeSubtitleRendering(true) (the documented contract), and the engine's own reload, triggered by the same KVO change, then destroyed that request: the receiver rendered no subtitles at all and the Sodalite#38 force-deselect loop kept running.

Root cause: reloadAtCurrentPosition()'s URL branch rebuilt the session from LoadOptions with no knowledge of state accumulated since load. The #65/#93 stall recovery already replays the native-rendition pick after an in-place item swap, and the custom-source reload branch already preserves the audio pick and re-arms the subtitle source; the URL branch (AirPlay swap, background-return reopen) restored nothing.

Fix: reloadAtCurrentPosition captures a subtitle session carryover before the reload and restores it around the fresh load():

  • The external-track registry is seeded id-exactly (removal gaps preserved, so future adds cannot collide with the session's id history). Seeding happens before the native rendition table is built, so mid-session external tracks become WebVTT-rendition-eligible on the reloaded item, which is exactly the AirPlay/PiP window where the host overlay cannot draw. This covers the issue's second ask for the reload case; a standalone mid-session rendition promote without an item swap is not possible (AVPlayer reads the master playlist once per item).
  • The explicit audio pick rides load()'s existing audioSourceStreamIndex override, matching the custom-source branch.
  • The previous subtitle selection is re-selected instead of re-running auto-selection; explicit subtitles-off stays off (the host's authority flag carries over, so the load-end preferred-language pass does not run against it).
  • The native-rendition pick is replayed like the #65 recovery, recomputed against the rebuilt table (which the seeded externals can grow), with positional replay for host-driven ordinals.
  • A host setNativeSubtitleRendering call landing mid-reload is latched and applied after the restore instead of being misread as a deselect (the active track is transiently nil during the reload).

The audio-switch reload (selectAudioTrack) gets the same native-ordinal replay, so switching audio during PiP/AirPlay no longer strands the receiver without subtitles, and an active external track now re-arms through its synthetic id there instead of collapsing to a one-shot sidecar URL.

Hosts shipping workarounds for this (freezing track mirrors across the reload, re-adding dropped tracks, re-asserting the rendering call) can remove them on 5.17.1.

Not covered: the nativeRemoteHLS bypass never takes the AirPlay reload (the source is already receiver-reachable), and its background-return reload keeps prior behavior for mid-session external tracks.

Tests

  • 19 new tests in Issue170SessionCarryoverTests (carryover capture, id-exact seeding, selection-restore decision matrix, table-aware ordinal replay, mid-reload latch).
  • Full suite: 891 Swift Testing + 344 XCTest passing, strict-concurrency complete clean, macOS + iOS Simulator + tvOS Simulator CI green.