plac

Unofficial Roon clients

macos: Implement core logic in Swift Managing long-live object and handling IO in C API was mistake. Every Zig/Swift nicities are eliminated at C API boundary. It must be stupid make/free (or retain/release) function calls and they always have to be heap allocoated using cAllocator. Everything has to be thread-safe by using manual reference counting. Good practices in each languages are no longer available due to C API barrier. Although I had to duplicated Roon API handling logic, I believe this work is worth the added code. IO and concurrent things are done in a Swift-y way, avoiding small heap allocations are now easier (I guess it's already less than the previous?), and most importantly, I have deeper understandings of Swift and Apple frameworks than before. UI layer code is way cleaner than the before. Especially watching incoming message is very ergnomic--I can just iterate on `compactMap`-ed async iterator, as you can see in "plac/DataModel/ZoneDataModel.swift". As a bonus, every async task now handles cancellation (e.g. closing window) perfectly. In terms of performance, I don't think there is any regression. Moreover, I feel this rewrite version performs better. Not profiled (I've never profiled Plac macOS app...) but playback control actions are instant without any UI stutter. Considering it now uses more high-level API provided by Apple, this rewrite should improve stability and portability. Despite of these good things, there is one I'm not satisfied with--message parsing (MOO / SOOD.) Swift does not have a good reader/writer interface unlike Zig. The closest thing is SwiftNIO's `ByteBuffer`, but I avoided it to keep dependence to third-party libraries lower (the repository is in Apple org, though.) I've considered using Zig code for that part or write a dedicated C module using Wuffs but abandoned the ideas too, because of Xcode signing gotchas (ugh.) Speaking of Xcode signing, the app now works on iOS simulator. It probably won't work on real device due to multicast entitlement, but this is huge advancement. Some entry point tweaks are necessary, like UI for entering IP/port of Roon server. Revising suspension and resume is also necessary. Not ready to use, but this is great starting point. Overall, I'm satisfied the result and enjoyed this whole learning process.

Changes

33 changed files (+3257/-1069)