Skip to content

feat: banner when a Bluetooth mic pairs + fix silent BT mic level meter - #38

Merged
joeblau merged 1 commit into
mainfrom
feat/bluetooth-mic-connectivity
Jul 9, 2026
Merged

feat: banner when a Bluetooth mic pairs + fix silent BT mic level meter#38
joeblau merged 1 commit into
mainfrom
feat/bluetooth-mic-connectivity

Conversation

@joeblau

@joeblau joeblau commented Jul 9, 2026

Copy link
Copy Markdown
Owner

Summary

Two related pieces of Bluetooth-mic UX in the streaming flow.

1. Banner when a Bluetooth audio device pairs mid-session

  • AudioInputProvider diffs the Bluetooth input set on each AVAudioSession route change and fires a new onBluetoothConnected callback only for devices that arrive — already-connected devices at launch seed the baseline, so no false banner.
  • The provider is hoisted from SettingsView into ContentView so its route-change observer runs for the whole app lifetime (not just while the Settings sheet is open); both screens share one instance/observer.
  • A transient glass banner ("<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:

  • A tap alone doesn't pull a Bluetooth HFP input. The engine only renders its input when the graph drives an output, so an unconnected input node hands the tap silent buffers. Input is now routed through the main mixer with output volume 0 (no monitoring/feedback) to force a full I/O cycle.
  • No AVAudioEngineConfigurationChange observer. If the HFP link settled asynchronously after setPreferredInput, the tap stayed bound to the stale (built-in) format and went silent. Tap install is extracted into a reusable installMeterTap() that a new observer re-runs on reconfiguration; the observer is torn down in stopLocalCapture.

Testing

  • xcodebuild build -scheme Stream -destination 'generic/platform=iOS'BUILD SUCCEEDED.
  • StreamCore test suite unaffected (changes are app-target only).
  • ⚠️ The mic-meter fix is not yet confirmed on-device — the muted-mixer pull is the standard remedy for silent AVAudioEngine HFP 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

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>
@joeblau
joeblau merged commit 539eca4 into main Jul 9, 2026
1 check passed
@joeblau
joeblau deleted the feat/bluetooth-mic-connectivity branch July 9, 2026 13:06
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