I’ve built a Volumio plugin that solves exactly the same problem you’re describing — keep the Volumio volume UI fully functional, but redirect all volume changes to an external hardware volume controller while keeping the digital path bit-perfect.
In my case the “external DAC” is a Genelec GLM adapter. I’ve reverse-engineered the USB protocol so I can set system volume directly from the Raspberry Pi, without the GLM PC software. This means the audio stream stays completely unaltered end-to-end (Volumio → digital out → Genelec DSP/room correction → finally the analog stage in the monitors applies gain). No double volume control, no digital attenuation, no clipping losses.
The key insight:
You don’t need to hack ALSA or create a fake mixer file. Volumio already supports mixer overrides cleanly.
My plugin works by:
- Registering itself as a volume override via
volumioUpdateVolumeSettings({ volumeOverride: true, ... }) - Providing its own
alsavolume()implementation, which catches every incoming volume command (e.g.+,-, absolute values) and never touches ALSA. - Emitting proper volume state objects back to Volumio, so the UI slider, REST API, WebSocket events, and plugins keep working as if nothing changed.
- Redirecting the volume value to my external device (in my case by issuing a USB command to the GLM network adapter).
Your situation with AD5234 digital pots, I2C gain elements, or multi-channel analog gain blocks fits the same pattern perfectly.
Here’s the relevant pattern from my plugin:
initVolumeSettings()sets up a dummy mixer withvolumeOverride: true- Volumio now calls my plugin for all volume actions
- My
alsavolume()method updates my hardware instead of ALSA getVolumeObject()reports the resulting state back to Volumio- No ALSA mixertype, no MPD softvol, no double attenuation
No UI elements break, no configuration files are write-protected, no system logs fill with ALSA errors, and everything survives updates.
So yes — what you’re trying to do is possible without hacks. You just need to register your own mixer override and implement the volume interface inside a plugin. Volumio is perfectly happy to delegate all volume responsibilities to an external controller as long as you provide the correct callback functions.
I used this plugin as reference for my own custom plugin: