fix(audio): route follows-default apps when highest-priority output reconnects#314
Open
clem-git wants to merge 1 commit into
Open
fix(audio): route follows-default apps when highest-priority output reconnects#314clem-git wants to merge 1 commit into
clem-git wants to merge 1 commit into
Conversation
…econnects When a Bluetooth output device reconnects, macOS auto-switches the system default to it within milliseconds. By the time handleDeviceConnected runs, the connected device already equals the current default, so the previous branching matched neither case — it neither re-evaluated the default nor restored the prior one. lastConfirmedDefaultUID stayed stale on the old device and the follows-default app taps were never re-pointed; a subsequent handleDefaultDeviceChanged then reverted routing to the stale device, leaving the system default on the newly connected device while app audio kept playing on the previous one (e.g. built-in speakers). Resolve the connect decision through a pure connectedOutputDefaultAction(...): when the connected device is the highest-priority *connected* device, ensure it is the default and re-route follows-default apps via reEvaluateOutputDefault (which sets the default only when it differs and always re-points the taps). Lower-priority-hijack protection (.restorePrevious) is unchanged. Add OutputDeviceReconnectRoutingTests covering the reconnect desync, the disconnected-ronitsingh10#1 priority resolution (WH-1000XM5 off / Buds4 on), and the preserved protection behaviour. Full FineTuneTests target passes. Addresses ronitsingh10#255 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
e4a60b1 to
18204ce
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Addresses #255. On a Bluetooth output reconnect, the system default and the UI correctly move to the reconnected device, but per-app audio (follows-default apps, e.g. Spotify) keeps playing on the previous device (typically the built-in speakers). The user has to manually toggle the output in FineTune to make audio actually follow.
Reproduced on macOS 26.4.1 with FineTune 1.7.0:
Root cause
In
handleDeviceConnected, macOS natively auto-switches the system default to a newly connected BT device within milliseconds. By the time the handler runs,deviceUID == currentDefault, so the existing branching matched neither case:Result:
lastConfirmedDefaultUIDstays stale on the old device androuteFollowsDefaultAppsis never called, so the app taps are never re-pointed. A subsequenthandleDefaultDeviceChanged(Case 1) then treats macOS's switch as something to undo and routes follows-default apps back to the stale device — stranding audio on the old output while the system default sits on the new one.Fix
Extract the decision into a pure, testable
connectedOutputDefaultAction(...)and add the missing.confirmConnectedcase: when the connected device is the highest-priority connected device and macOS already made it the default, confirm it (lastConfirmedDefaultUID) and route follows-default apps so their taps follow.The existing
.switchToConnected(higher-priority reconnect, not yet default) and.restorePrevious(lower-priority device macOS hijacked to) behaviours are preserved exactly — lower-priority-hijack protection is unchanged.Testing
OutputDeviceReconnectRoutingTestscovers the reconnect desync (the previously-unhandled case) and the preserved protection behaviour, including the "disconnected top-priority device → highest connected device still wins" scenario.FineTuneTeststarget passes.🤖 Generated with Claude Code