Skip to content

fix: restore sample rate switching and add restart option - #217

Open
kush2shah wants to merge 1 commit into
vincentneo:v3from
kush2shah:fix/switching-and-restart
Open

fix: restore sample rate switching and add restart option#217
kush2shah wants to merge 1 commit into
vincentneo:v3from
kush2shah:fix/switching-and-restart

Conversation

@kush2shah

@kush2shah kush2shah commented Jul 12, 2026

Copy link
Copy Markdown

Builds on top of the v3 log-streaming rework. In testing on macOS 27, v3 detected tracks but never actually switched the device sample rate. This PR fixes that and hardens the process/app lifecycle, and adds a Restart option.

The switching fix (main one)

Music logs the format lines this branch parses — play> cm>> / asbdSampleRate / sdBitDepth — at debug level. log stream withholds debug-level messages unless you explicitly request them, so LogReader was receiving zero entries and nothing ever switched.

Verified directly with the app's exact predicate:

  • without --level debug: 0 lines
  • with --level debug: full stream, including e.g. ... play> cm>> mediaFormatinfo '<private>' , ... sdFormatID = alac, ... sdBitDepth = 16 bit, asbdSampleRate = 44.1 kHz

After adding the flag, driving track changes shows the pipeline resolving the device format end-to-end (NEAREST FORMAT [...mSampleRate: 44100.0...]).

Other fixes

  • Single detection instance. AppDelegate and MenuBarController were each creating their own OutputDevices + MediaRemoteController, so two log readers and two controllers raced to set the device sample rate (and doubled the helper processes). Consolidated to one shared instance owned by AppDelegate.
  • Subprocess lifecycle. LogReader now terminates the log stream subprocess on quit/restart (it was previously orphaned), buffers partial pipe reads so a line split across two reads still parses, and respawns the stream if it dies so switching doesn't silently go dead.
  • Bounded collection. The per-track format collection no longer grows for the entire lifetime of the app.

New feature

  • Restart LosslessSwitcher menu item, alongside Quit. Child processes are torn down in applicationWillTerminate, which both Quit and Restart go through.

Testing

  • Builds clean (xcodebuild ... build).
  • Launch spawns exactly one log stream subprocess (was two before consolidation).
  • Graceful quit leaves no orphaned log stream process.
  • Track changes produce detected stats + resolved device format in the app's output.

Note: because these are debug-level logs, this is validated against how Music logs on current macOS; if a future Music build moves the format line to a different category/level the predicate would need revisiting.

🤖 Generated with Claude Code

Builds on the v3 log-streaming rework and makes it actually switch, plus
hardens process/app lifecycle.

- LogReader: pass `--level debug` to `log stream`. The Music format lines we
  parse (`play> cm>>` / asbdSampleRate / sdBitDepth) are logged at debug
  level, which `log stream` withholds unless debug level is requested. Without
  this the reader received zero entries and nothing ever switched.
- LogReader: terminate the `log stream` subprocess on quit/restart (it was
  otherwise orphaned), buffer partial pipe reads so split lines parse
  correctly, and respawn the stream if it dies so switching doesn't silently
  stop.
- Consolidate to a single shared OutputDevices / MediaRemoteController. Both
  AppDelegate and MenuBarController were each creating their own, so two log
  readers and two controllers raced to set the device sample rate.
- OutputDevices: bound the format collection so it doesn't grow for the life
  of the app.
- Add a "Restart LosslessSwitcher" menu item; clean up child processes in
  applicationWillTerminate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RprYxphRxr3sFMoySavZzW
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant