iD4 #
A macOS menu bar app that makes the keyboard volume keys control an Audient iD4 MkII.
macOS shows no volume control for the iD4 because its USB descriptor declares none. The firmware still accepts USB Audio Class 2 volume and mute requests on its playback feature unit. While the iD4 is the default output, this app intercepts volume up, volume down and mute, and sends those requests instead.
Behaviour #
- Volume up and down move the level by 3 dB, between -60 dB and 0 dB.
- Volume down at -60 dB mutes. Volume up or down while muted unmutes.
- Mute toggles the device's mute control.
- Each key press shows a volume indicator below the menu bar, at the top right of the screen.
- The iD4 resets its level to 0 dB when it loses power. The app stores the last level it set and writes it back whenever the iD4 becomes the default output, including at launch.
- With any other output selected, the keys reach macOS unchanged.
- The level is a digital attenuation ahead of the hardware knob. The knob sets the maximum.
The menu has two items: Hide Menu Bar Icon and Quit. The icon stays hidden across launches, including at login and after a restart. Opening the app while it is running shows the icon again.
Build #
Requires Xcode 26 or later. The app runs on macOS 26 or later.
./build.sh
This produces iD4.app, signed with the first identity matching Apple Development. Set CODESIGN_IDENTITY to use another one, or - for an ad-hoc signature.
On first launch, grant the app Accessibility access in System Settings. It needs it to intercept the volume keys.
Protocol #
Tested on an iD4 MkII (USB 2708:0009, firmware 1.04).
Requests are USB Audio Class 2 CUR requests (bRequest 0x01), addressed to feature unit 0x0a through interface 4, the DFU interface. macOS denies requests addressed to interface 0, which the audio driver owns.
| Control | wValue |
wIndex |
Data |
|---|---|---|---|
| Mute | 0x01 selector, channel in the low byte |
0x0a04 |
1 byte, 0 or 1 |
| Volume | 0x02 selector, channel in the low byte |
0x0a04 |
signed 16-bit little-endian, 1/256 dB |
Volume ranges from -127 dB to 0 dB in 1 dB steps. The app writes channels 0, 1 and 2.
The position of the hardware knob is not readable over USB.
The entity layout of the larger iD interfaces is documented by MixiD and BiD, which is where the request format comes from.
- Swift 97%
- Shell 3%