Skip to content

Fix microphone recovery after audio device changes - #966

Open
altic-dev wants to merge 6 commits into
B/1.6.10-more-enhancementsfrom
B/audio-disconnect-recovery-testing
Open

altic-dev wants to merge 6 commits into
B/1.6.10-more-enhancementsfrom
B/audio-disconnect-recovery-testing

Conversation

@altic-dev

@altic-dev altic-dev commented Sep 11, 2026

Copy link
Copy Markdown
Owner

Description

Rebuild microphone setup after audio-device changes and fix cancellation and playback restoration when recording recovery fails.

Type of Change

  • 🐞 Bug fix
  • ✨ New feature
  • 💥 Breaking change
  • 🧹 Chore
  • 📝 Documentation update

Related Issue or Discussion

Stacked on #955.

Testing

  • Tested on Intel Mac
  • Tested on Apple Silicon Mac (automated tests)
  • Tested on macOS version: 27.0
  • Ran linter locally: swiftlint --strict --config .swiftlint.yml Sources Tests Package.swift
  • Ran formatter locally: swiftformat --config .swiftformat Sources
  • Ran tests locally: 188 signed tests and 37 controller ThreadSanitizer tests passed.

Screenshots / Video

  • No UI/visual changes; screenshots/video are not applicable.

Notes

altic-dev and others added 4 commits September 10, 2026 07:36
Serialize native hardware cleanup, preserve cancellation while a pending audio call retires, and retry route discovery within bounded recovery waits. Keep ordinary startup and stop free of recovery deadlines.

Add hosted ASR and controller regression coverage for fallback, stale completions, cancellation, and normal capture compatibility.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 11, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-11T21:25:54.567714Z c7b15e8 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions github-actions Bot added the needs screenshots Pull request needs screenshot or video evidence. label Sep 11, 2026
@github-actions

Copy link
Copy Markdown

The PR Policy check is blocking this PR because required template information is missing.

Please update the PR description with:

  • Screenshots / Video

Visual files detected:

  • Sources/Fluid/Services/MenuBarManager.swift

Screenshots or video are required for UI, UX, settings, onboarding, overlay, menu bar, or visual behavior changes. If this PR has no visual changes, check the no-visual-change box in the template.

If this remains incomplete for 48 hours after opening, the PR may be closed.

@github-actions github-actions Bot removed the needs screenshots Pull request needs screenshot or video evidence. label Sep 11, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 99ccb0fbe5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/Fluid/Services/DirectCoreAudioInput.swift
@greptile-apps

greptile-apps Bot commented Sep 11, 2026

Copy link
Copy Markdown

Greptile Summary

This PR rebuilds microphone capture after Core Audio topology changes and strengthens cancellation, recovery serialization, fallback selection, failure presentation, and media-playback restoration.

  • Adds bounded, cancellation-aware queues for hardware operations and device discovery.
  • Tracks topology revisions so stopped capture is rebuilt rather than reusing stale native setup.
  • Uses fresh device snapshots to determine startup and active-recovery fallback budgets.
  • Adds integration and lifecycle tests covering device changes, blocked native operations, cancellation, fallback microphones, teardown failures, and playback restoration.
  • Updates the application version to 1.6.10-beta.2 build 23.

Confidence Score: 5/5

The PR appears safe to merge, with no outstanding correctness or repository-rule issues identified.

The previously reported topology-revision issue was manually resolved, and the current lifecycle code preserves a pending topology revision when reusing a running preview so the next stopped start rebuilds the capture input. The latest fresh-snapshot retry-budget change covers the intended candidates and same-device retry without introducing a concrete regression.

Reviews (3): Last reviewed commit: "size microphone retries from the fresh s..." | Re-trigger Greptile

Comment thread Sources/Fluid/Services/DirectCoreAudioInput.swift Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0c11cb11e6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/Fluid/Services/ASRService.swift Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c7b15e8578

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

self.publishSnapshot(phase: .shutDown, input: nil, fingerprint: nil)
}
Self.log("Direct capture interrupted operation drained status=\(status)", level: .info)
return status == noErr && self.isPoisoned == false

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Treat quarantined stopped hardware as recovered

When a known-stopped notification interrupts a blocked prepare/start and the subsequent input.invalidate() returns an error, invalidateLocked consumes that stopped marker and deliberately leaves isPoisoned false because replacement is safe, but this expression still reports recovery failure solely because status != noErr. BoundedAudioHardwareQueue then latches cleanupFailed; the queued notification no longer has its marker, and the topology fallback requires isPoisoned, so every later recording attempt is rejected until restart. Recovery should succeed when the failed teardown was safely quarantined rather than requiring noErr unconditionally.

Useful? React with 👍 / 👎.

name: NSNotification.Name("ASRServiceStartFailed"),
object: nil,
userInfo: ["errorMessage": errorMessage]
self.presentAudioCaptureFailure(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you post a system notification maybe instead of directly focusing the main app window ? Clicking on it could take users to the main app

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, technically this shouldn't even be popping up at all. But the recovery doesn't happen for the same user I mentioned below and this seems to help. If they have notification suppressed - this will go unnoticed and since it's fatal, it made sense to make the app pop up in front so the user is aware of issue - if it happens - seems to be very rare occurrence.

Comment on lines +987 to +989
let topologyRevision = self.snapshotLock.withLock { self.hardwareTopologyRevision }
if let input = self.input, input.isRunning == false,
topologyRevision != self.lastStartedTopologyRevision

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to rebuild the pipeline even if the preferred is mic available (and topology changed due to some device coming/going) ? What would be the latency impact of rebuild this ?

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is some weird issue with one user that doesn't work if I don't do the whole build and gets stuck. the current build I have works for now. If this problem happens, I am not sure about the extra delay as I don't have that info or can reproduce this on my side. So still tinkering with this.

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.

2 participants