Add support for choosing custom audio input - #531
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 838862350d
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if nextMode == .manual { | ||
| if self.selectedInputUID.isEmpty, | ||
| let defaultUID = currentSystemInputUID | ||
| { | ||
| self.selectedInputUID = defaultUID | ||
| SettingsStore.shared.recordInputDeviceSelection(defaultUID) | ||
| } else { | ||
| SettingsStore.shared.recordInputDeviceSelection(self.selectedInputUID) | ||
| } |
There was a problem hiding this comment.
Preserve the saved manual microphone when toggling back
When the Settings view is in system mode, selectedInputUID tracks the current macOS default, so turning off “Use macOS default microphone” here overwrites any previously saved manual microphone with that system default. This differs from the menu path, which only initializes preferredInputDeviceUID when it is empty, and it means a user who temporarily switches back to macOS default loses their custom mic preference as soon as they re-enable manual mode unless they reselect it.
Useful? React with 👍 / 👎.
8388623 to
457af51
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 457af51ff5
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| SettingsStore.shared.preferredInputDeviceUID = newUID | ||
| // Only change system default if sync is enabled | ||
| if SettingsStore.shared.syncAudioDevicesWithSystem { | ||
| SettingsStore.shared.recordInputDeviceSelection(newUID) |
There was a problem hiding this comment.
Avoid recording fallback selections as manual preferences
In manual mode this onChange fires for programmatic selection changes too, not just user picker choices. For example, SettingsView.onAppear still replaces an invalid/unavailable selectedInputUID with the current default; this line then persists that fallback as PreferredInputDeviceUID, so simply opening Settings while the saved mic is disconnected loses the custom mic that manual mode is meant to preserve. Gate this write to user-initiated picker changes or make the fallback path mode-aware.
Useful? React with 👍 / 👎.
| if let microphoneSelectionMode = payload.microphoneSelectionMode { | ||
| self.microphoneSelectionMode = microphoneSelectionMode | ||
| } |
There was a problem hiding this comment.
Reset missing microphone mode to system on restore
When restoring a backup from before this field existed while the current install is in manual mode, the if let leaves microphoneSelectionMode unchanged. Those older backups came from builds where audio selection always followed macOS defaults, so after restore future recordings can keep forcing the restored PreferredInputDeviceUID as a manual mic instead of following the legacy system-mode behavior. Treat nil as .system (or remove the key) during restore.
Useful? React with 👍 / 👎.
62a0a77 to
6dff573
Compare
|
@altic-dev Good to review, tested with the new audio optimized pipeline |
|
@greptileai review |
Greptile SummaryThis PR introduces a
|
Greptile SummaryThis PR introduces a
|
6dff573 to
97a8530
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 97a8530813
ℹ️ 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".
|
|
||
| do { | ||
| if SettingsStore.shared.microphoneSelectionMode == .manual { | ||
| AppServices.shared.microphonePreferenceCoordinator.enforcePreferredInput(reason: "recording start") |
There was a problem hiding this comment.
Do not reassert manual mics as the system default
When manual mode is enabled and the saved preferred mic differs from the current macOS default, this call routes through MicrophonePreferenceCoordinator.enforcePreferredInput(), which calls setDefaultInputDevice before capture starts. That makes a FluidVoice-only/manual selection overwrite the user's global macOS input device, and it can leave other apps on that mic even if the recording start later fails; the manual path should capture from the preferred device without changing the system default, or limit/restore any workaround to the backend path that truly needs it.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c718d8de92
ℹ️ 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".
| let restoredSystemInputUID = SettingsStore.shared.setMicrophoneSelectionMode( | ||
| nextMode, | ||
| currentSystemInputUID: currentSystemInputUID, | ||
| availableInputUIDs: availableInputUIDs | ||
| ) |
There was a problem hiding this comment.
Keep Settings state in sync with menu microphone mode
When the user toggles microphone mode from the menu bar, this updates SettingsStore and refreshes only the menu, but ContentView keeps a separate @State microphoneSelectionMode that is passed into SettingsView and is only refreshed on backup restore. In the common flow of changing the mode from the menu and then opening Preferences, the Settings toggle/info can still reflect the old mode until relaunch, so the UI can present and act on stale state. Drive Settings directly from SettingsStore or notify/synchronize the ContentView state here.
Useful? React with 👍 / 👎.
c718d8d to
07e7b6c
Compare
|
@greptileai review latest changes |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 07e7b6c986
ℹ️ 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".
| case .manual: | ||
| // The refreshed device list drives the displayed selection. | ||
| break |
There was a problem hiding this comment.
Restore the available manual mic after hardware changes
When manual mode is active and Settings is not the current detail view, this branch leaves selectedInputUID unchanged after refreshDevices(). If the saved manual microphone was previously disconnected while Settings fell back to the default, then the preferred mic reconnects while Preferences is closed, reopening Settings keeps showing the still-valid fallback instead of the saved preferred UID even though capture resolves preferredInputDeviceUID; update the manual path when the refreshed device list contains the saved preference.
Useful? React with 👍 / 👎.
…eferenceCoordinator Upstream altic-dev#531 ("Add support for choosing custom audio input") landed while this branch was open and reworked the same code paths, so the conflicting files are resolved wholly in favour of upstream and this branch's contribution is re-expressed as a small delta on their model. altic-dev#531's `.manual` mode honours the preferred microphone by moving the macOS default input to it (`enforcePreferredInput` -> `setDefaultInputDevice`, reasserted at recording start and on hardware changes). That leaves the original goal of this branch uncovered: capturing a dedicated microphone for FluidVoice alone, without taking over the system input for every other app. So `MicrophoneSelectionMode` gains a third case, `.fluidVoiceOnly`: - `inputDeviceForCapture()` resolves the preference in both preferred modes. - `enforcePreferredInput()` returns the new `.skippedFluidVoiceOnlyMode` — never touching the system default is the entire feature. - Gated on `experimentalDirectAudioCaptureEnabled`; a stored `.fluidVoiceOnly` reads back as `.manual` when direct capture is off, so the preference is still honoured rather than silently ignored. - Two guards against silently recording the wrong microphone, since device resolution falls back to the macOS default by design: `preferredInputIsMissing()` refuses to start when the pinned device is unplugged, and `startPreferredAudioCapture()` refuses the AVAudioEngine fallback, which can only ever record the system default. - Hardware-change handlers skip `stabilizePreferredInputAfterHardwareChange` (it reasserts the default) and re-resolve the capture device instead. - `setMicrophoneSelectionMode()` captures the user's own input device when *entering* `.manual` from any other mode, and hands it back when leaving. Capturing only from `.system` (as before) missed the `.fluidVoiceOnly` -> `.manual` -> `.fluidVoiceOnly` round trip and left the system input stuck on FluidVoice's choice after the user opted back out — found on-device by walking that exact sequence. - Settings and the menu bar each gain one "use for FluidVoice only" switch. Superseded by upstream and dropped: the preferred-UID-clobbered-on-disconnect fix, the derived Picker binding, and the `syncAudioDevicesWithSystem` boolean. Local: swiftlint --strict clean; 161 tests pass.
Description
Add support for choosing custom audio input separate from MacOS default. The following is the behavior
Also, add a menu bar setting to toggle micrphone
Type of Change
Related Issue or Discussion
Closes #136
Testing
swiftlint --strict --config .swiftlint.yml SourcesScreenshots / Video
fv_audio_input_compressed.mp4