feat: mute all microphones at once
What
A global "Mute All Mics" switch, in the spirit of MacMute:
- Right-click menu: "Mute All Mics" / "Unmute All Mics", with mic icons.
- Microphone tab: a full-width mute tile. While muted, the tab icon, the input gain slider icon and recording app rows turn red, and the gain slider is frozen.
- Menu bar: a second, red slashed-mic icon is shown while muted. A click opens a menu (status, any devices that can't be muted, and "Unmute All Mics"), so a stray click never opens the mics.
How it mutes
- Every input device is muted at the CoreAudio HAL level, so apps that pick a non-default input are covered too. Sliders' own aggregate devices are skipped, because their input side carries tapped app audio, not a microphone.
- Listeners on the device list, the default input, and each device's mute and volume react in the same main-queue turn. Newly plugged devices are muted as they appear.
- If something else undoes a mute, it is put back and backed by input gain at zero from then on. A device that refuses the mute gets the gain lock at once. A 2 s watchdog covers drivers that change state without a notification.
- Devices with no working control (for example, an iPhone Continuity mic) are named in the UI as "can't be muted", and stop being the default input while the mute lasts.
- Fails closed: the engaged state and each device's original values are saved before any HAL write, so a crash or update relaunch stays muted. A normal quit restores every device exactly as it was, then re-mutes on the next launch.
Testing
- 114 tests pass (
MicMutePolicyTestsis new). Lint passes. - On real hardware (MacBook Pro mic and an external mic), an earlier build re-muted a tampered mute within 2–10 ms, escalated to zero gain, and restored the original state on quit.
- Not yet tested by hand: the latest build's menu and icon changes, hot-plugging, sleep and wake, a Core Audio restart, and Sparkle update relaunch.
[!NOTE]
High Risk
Writes Core Audio mute/gain and default input device system-wide with persisted fail-closed behavior—privacy-critical microphone surface with complex edge cases (unmutable devices, Core Audio restarts, quit vs update).
Overview
Adds Mute All Microphones: one action from the microphone tab tile, the Sliders right‑click menu, and a dedicated red menu-bar icon (menu-only unmute so stray clicks don’t open mics).
Enforcement is new HAL-level logic (MicrophoneMute + policy/store): every real input device is held muted (Sliders plumbing aggregates skipped), hot-plug and tamper re-mute in the same main-queue turn with optional zero-gain backup, a watchdog, and naming devices that can’t be silenced while temporarily moving default input off them. State fails closed—engaged mute and restore snapshots persist across crash/update; normal quit restores prior levels via releaseForQuit() while update relaunch keeps mics muted.
UI follows mute state (frozen input slider, red tab/recording rows when fully protected). ControlSlider gains optional icon color and respects .disabled for scroll-wheel adjustment. README and render-shot scene 08-microphone-muted document the feature; MicMutePolicyTests covers policy/persistence.
Reviewed by Cursor Bugbot for commit bb0e5fb3df6bccdd77c90afb59a8d7827c497309. Bugbot is set up for automated code reviews on this repo. Configure here.