Callback-based sound sources are kept alive in a static registry while the
C side may still invoke their trampoline, but nothing ever removed them:
every callback source leaked its wrapper and closure permanently, and a
source retained only by a transient Channel.default wrapper relied on that
leak for safety. The registry is now the single source of truth and is
purged on Sound.removeSource, Channel.removeSource, and when an owned
channel is freed (its sources can no longer be pulled).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Wraps all ten subsystems of the Playdate SDK 3.1.1 C API (system, display,
graphics, sprites, sound, file, JSON, Lua, scoreboards, network) in
idiomatic Swift: namespaced APIs, wrapper types with ownership semantics,
closures for callbacks, and typed throws. Written within the Embedded Swift
subset so the same code can target the device.
The SDK headers are resolved through a "playdate" pkg-config module
(Scripts/install-pkgconfig.sh), so the package works as a normal SwiftPM
dependency without unsafe build flags.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>