fix: detect Bluetooth/DJI mics connected mid-session (no app restart) - #35
Merged
Conversation
Input enumeration was pull-only — it ran on the Settings view's onAppear and the manual "Refresh Inputs" button, and nowhere else. Nothing observed AVAudioSession.routeChangeNotification, so a Bluetooth headset connected while the app was already running never re-enumerated; the only way to pick it up was relaunching (which re-runs onAppear). AudioInputProvider now registers a single routeChangeNotification observer (idempotently, from refresh()) and re-enumerates on .newDeviceAvailable / .oldDeviceUnavailable. It deliberately ignores .categoryChange and .override, which we provoke ourselves by setting the category and preferred input — reacting to those would loop. The observer is torn down in a nonisolated deinit. SettingsView wires the new onInputsChanged callback to re-apply the persisted preferred input to the session and restart the mic-level meter on the new route, so a headset plugged in now goes live within a second. Skipped while broadcasting, where the ScreenCaptureKit extension owns the route. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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
Audio input enumeration was pull-only — it ran on the Settings view's
onAppearand the manual "Refresh Inputs" button, and nowhere else. Nothing observedAVAudioSession.routeChangeNotification, so a Bluetooth headset (or DJI mic) connected while the app was already running never re-enumerated. The only way to pick it up was quitting and relaunching (which re-runsonAppear).Fix
AudioInputProvidernow registers a singleAVAudioSession.routeChangeNotificationobserver (idempotently, fromrefresh()) and re-enumerates on.newDeviceAvailable/.oldDeviceUnavailable. It deliberately ignores.categoryChange/.override, which we provoke ourselves by setting the category and preferred input — reacting to those would loop. Torn down in anonisolateddeinit.SettingsViewwires the newonInputsChangedcallback to re-apply the persisted preferred input to the session and restart the mic-level meter on the new route, so a headset plugged in now goes live within a second. Skipped while broadcasting (the ScreenCaptureKit extension owns the route).Scope
2 files, +64 lines —
Stream/AudioInputProvider.swift,Stream/SettingsView.swift. App-target only; noStreamCorechanges.🤖 Generated with Claude Code