Skip to content

feat(audio): follow system default devices on macOS - #173

Merged
bilalyazicioglu merged 2 commits into
developfrom
feat/follow-default-device
Oct 10, 2026
Merged

bilalyazicioglu merged 2 commits into
developfrom
feat/follow-default-device

Conversation

@bilalyazicioglu

@bilalyazicioglu bilalyazicioglu commented Oct 9, 2026 •

Copy link
Copy Markdown
Owner

Description

On macOS, connecting a headset could leave tincan on the still-working built-in devices. Streams opened with the default choice now follow system default changes on the existing one-second recovery tick.

Named CLI devices, remembered devices, and successful manual selections remain pinned, including when recovery falls back to the default. Each picker now offers System default (follow changes) to resume following and clear that side's saved preference.

Automatic changes synchronize the active device and microphone gate, preserve pending gate edits under the correct microphone, and cancel stale calibration. A same-device recovery retains the live gate. On macOS, open settings poll device lists even when a pinned stream emits no recovery event. Reconnected devices appear automatically, browsing keeps the highlighted device by name across reordering, and a disappeared selection falls back to the actual active device. Long device lists keep the highlighted choice visible; repeated outage notices are suppressed independently for input and output.

Default polling is limited to macOS. Linux sound-server routing and Windows stream recovery retain their existing platform scope. Recovery of an unavailable pinned device still permits a default fallback, without enabling following or automatically returning when the original device reconnects.

Fixes #160

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change
  • Documentation update

Validation

  • cargo test --locked --offline -- --quiet: 377 passed; 6 deliberately ignored (asset generators, internet discovery, and hardware-dependent test).
  • cargo clippy --all-targets --locked --offline -- -D warnings, cargo fmt --all --check, and git diff --check passed.
  • Routing lifecycle tests cover all 7,776 five-event sequences against expected outcomes, plus profile changes, failed opens, total device loss, per-side preferences, fallback, and recovery.
  • UI/config tests verify actual persistence across restart, device-specific gate edits, failure rollback, calibration cancellation, and visible selection in crowded pickers. A combined disconnect/reconnect scenario renders the full UI to verify that rail names, actual destinations, highlighted replacements, and reappearing headset choices agree.
  • Explicitly ran live_macos_streams_recover_and_keep_transferring_samples with BlackHole and built-in devices: a transmitted 440 Hz signal returned through real CPAL/resampler/ring-buffer callbacks; failed selections preserved working audio; default transitions and simulated driver-loss recovery kept the original capture consumer alive.
  • Compared initial loopback amplitude against unchanged develop code before making the hardware assertion independent of device gain.

Real AirPods connect/disconnect and Bluetooth profile changes during a call remain a manual release check. The hardware test does not change global system defaults. This draft is prepared for the macOS/Linux/Windows CI matrix; no release tag is created.

Checklist

  • This PR is for an issue assigned to me.
  • I have run cargo test and all non-ignored tests pass.
  • I have run cargo clippy --all-targets and resolved all warnings.
  • I have formatted my code with cargo fmt.
  • I have updated relevant documentation.

@bilalyazicioglu
bilalyazicioglu marked this pull request as ready for review October 10, 2026 08:34
@bilalyazicioglu
bilalyazicioglu merged commit 3b7664e into develop Oct 10, 2026
5 checks passed
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