feat: banner when a Bluetooth mic pairs + fix silent BT mic level meter - #38
Merged
Conversation
Two related pieces of Bluetooth-mic UX in the streaming flow.
Banner: AudioInputProvider now diffs the Bluetooth input set on each route
change and fires onBluetoothConnected only for devices that *arrive* mid-session
(already-connected devices at launch just seed the baseline, so no false
positive). The provider is hoisted from SettingsView into ContentView so its
AVAudioSession.routeChangeNotification observer runs for the whole app lifetime,
not just while the Settings sheet is open; both screens now share one instance.
A transient glass banner slides in on the main streaming screen ("<name>
connected"), stacked under the LIVE pill, and auto-dismisses after 3s.
Fix: the Settings mic-level meter read silent for a Bluetooth mic even when the
engine was correctly routed to it (confirmed on device: route=[DJI Mic 3/
BluetoothHFP] 16kHz, yet flat). Two causes:
- A tap alone does not reliably pull a Bluetooth HFP input — the engine only
renders its input when the graph drives an output. The input node is now
routed through the main mixer (output muted) to force a full I/O cycle so the
tap receives real samples.
- There was no AVAudioEngineConfigurationChange observer, so if the HFP link
settled asynchronously after setPreferredInput the tap stayed bound to the
stale (built-in) format and went silent. Tap installation is split into a
reusable installMeterTap() that the new observer re-runs on reconfiguration;
the observer is torn down in stopLocalCapture.
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.
Summary
Two related pieces of Bluetooth-mic UX in the streaming flow.
1. Banner when a Bluetooth audio device pairs mid-session
AudioInputProviderdiffs the Bluetooth input set on eachAVAudioSessionroute change and fires a newonBluetoothConnectedcallback only for devices that arrive — already-connected devices at launch seed the baseline, so no false banner.SettingsViewintoContentViewso its route-change observer runs for the whole app lifetime (not just while the Settings sheet is open); both screens share one instance/observer."<name> connected"+ haptic) slides in on the main streaming screen, stacked under the LIVE pill, and auto-dismisses after 3s.2. Fix: Bluetooth mic level meter read silent
Confirmed on device — the meter was correctly routed (
route=[DJI Mic 3 TX-01ffca/BluetoothHFP], 16 kHz) yet flat. Two root causes:AVAudioEngineConfigurationChangeobserver. If the HFP link settled asynchronously aftersetPreferredInput, the tap stayed bound to the stale (built-in) format and went silent. Tap install is extracted into a reusableinstallMeterTap()that a new observer re-runs on reconfiguration; the observer is torn down instopLocalCapture.Testing
xcodebuild build -scheme Stream -destination 'generic/platform=iOS'→ BUILD SUCCEEDED.AVAudioEngineHFP input, but the DJI Mic 3's over-Bluetooth behavior should be verified live. If the DJI won't stream over BT HFP at all, that's a pairing limitation (use the USB-C receiver), not an app bug.🤖 Generated with Claude Code