plac-for-apple-platform

Unofficial Roon client for Apple devices

Commits at dd6e15349ad8037e8e8108c2bd70780f529f15a0

  1. dd6e1534 macos: Reconfigure preview for PlaybackBar view TIL "MARK:" comment support for Xcode. Shota FUJI authored at Shota FUJI comitted at
  2. d8414c2e macos: Use protocols to untie IO from UI code For testability. Shota FUJI authored at Shota FUJI comitted at
  3. ac959c70 core: Remove macOS build output It's no longer used. Shota FUJI authored at Shota FUJI comitted at
  4. 87a170f9 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. Shota FUJI authored at Shota FUJI comitted at
  5. 03091367 macos: Display now playing artwork Shota FUJI authored at Shota FUJI comitted at
  6. 92b7d54f core: C API for getting image URL SwiftUI has AsyncImage view, which takes a URL. Shota FUJI authored at Shota FUJI comitted at
  7. 4cafdb7f macos: Use Environment for passing connection down Future views such as artwork requires connection, but passing a connection down to each view via initializer is tedious. Shota FUJI authored at Shota FUJI comitted at
  8. 84d0916a macos: Disconnect on window close Shota FUJI authored at Shota FUJI comitted at
  9. 19572656 macos: Playback controls Shota FUJI authored at Shota FUJI comitted at
  10. 619caed7 macos: Start message loop earlier Shota FUJI authored at Shota FUJI comitted at
  11. a4dd6513 macos: Save IP/port for quick connection Shota FUJI authored at Shota FUJI comitted at
  12. fc8a826e macos: Save and restore authorization token Shota FUJI authored at Shota FUJI comitted at
  13. 4570e084 macos: Disconnect menu items In GTK-Adwaita, it's easy thanks to "gsettings" CLI application. In macOS, however, there seems to no way to clear an application's "@AppStorage" data. Shota FUJI authored at Shota FUJI comitted at
  14. 3b0a3dc9 core: Expose disconnect function Shota FUJI authored at Shota FUJI comitted at
  15. cf516079 macos: Accept Xcode project settings recommendation It has been showing a warning and it was annoying. Shota FUJI authored at Shota FUJI comitted at
  16. 1dd7aab4 macos: Change non-modified variable to immutable Addressed a Xcode warning. Shota FUJI authored at Shota FUJI comitted at
  17. afb2d6b4 macos: Merge server discovery and main window The former is (most of the case) shown once. The reason I changed the payload of ".found" case is, without that, the only reference will be "ConnectedView" and every updates to the View would release then re-create a connection. Shota FUJI authored at Shota FUJI comitted at
  18. d53ccec3 macos: Save connected server ID and reconnect on launch The current UX is not complete, as there is no way to disconnect. Considering the usecase of connecting to more than one Roon server is rare, the discovery window should be integrated into the main window. Then it can conditionally render server discovery or connected view without going to discovery view first. Shota FUJI authored at Shota FUJI comitted at
  19. 37c16ed0 core: Allow clients to set custom extension ID/name/version It has been pain to manage authorization tokens in Roon settings page. Shota FUJI authored at Shota FUJI comitted at
  20. dfc4cec0 macos: Display loading UI during extension authorization It has been unclear what it's doing and what a user should do. Shota FUJI authored at Shota FUJI comitted at
  21. 2bb754a9 macos: Polish PlaybackBar It was bit odd. Shota FUJI authored at Shota FUJI comitted at
  22. 8b8802c2 macos: Display now playing texts (title and artist, mostly) Shota FUJI authored at Shota FUJI comitted at
  23. 9e6bf7bf macos: Fix more than one element in array crashes application I don't know how I got to that iteration code, but the `UnsafePointer<T>.successor` is NOT a method to iterate over an array. <https://codeberg.org/pocka/plac/issues/17> Shota FUJI authored at Shota FUJI comitted at
  24. c972d09c macos: Fix app crash when server scan found nothing Shota FUJI authored at Shota FUJI comitted at
  25. 065d06d6 core: Print debug log on macOS build Ideally, integrating OSLog is the best. However, it's time-consuming and a lot of work needs to be done. This is good for now. Shota FUJI authored at Shota FUJI comitted at
  26. 790bc7fc macos: Fix crash on network error at server discovery Shota FUJI authored at Shota FUJI comitted at
  27. 8fdfb08d gtk-adwaita: Remove "develop build" style from window Even though there is some missing features (search and disconnect menu option,) it's usable for my day-to-day usage. Now all concurrency and memory bugs are fixed, this is the best timing to remove WIP label. Shota FUJI authored at Shota FUJI comitted at
  28. 5ed1b013 core: Give WS read and event handlers dedicated threads <https://codeberg.org/pocka/plac/issues/16> Parsing and handling incoming message in the same thread that reads WebSocket message from socket sometime drops WebSocket message, due to the thread being busy. This redesign solves that by separating reading and parsing/handling using dedicated threads. Although volume change operation now feels little bit sluggish, no more dropped response. Every operation is working correctly. Shota FUJI authored at Shota FUJI comitted at
  29. 12dfcdb9 core: Fix potential race condition Extremely rare, though (I saw only once.) Shota FUJI authored at Shota FUJI comitted at
  30. 03235177 core: Output request ID on control request send log "/control" endpoint suffers response loss as well as "/change_volume" endpoint. Request ID helps debugging this, because it's visible on data payload in Wireshark. Shota FUJI authored at Shota FUJI comitted at