feat: mute all microphones at once

NO
16d ago
+1018-61

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 (MicMutePolicyTests is 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.