HEnquist / camilladsp

A flexible cross-platform IIR and FIR engine for crossovers, room correction etc.
https://henquist.github.io/
GNU General Public License v3.0
563 stars 49 forks source link

Read volume level from ALSA Loopback CTL mixer #172

Open yannpom opened 2 years ago

yannpom commented 2 years ago

Hello,

Here is my setup so you can better understand my needs:

When I press the volume buttons on my phone, the value is sent to shairport-sync which can do 3 things: apply software volume, do nothing or control an ALSA CTL mixer. Currently I'm using shairport-sync software volume, but I would like to move volume control to CamillaDSP.

I could setup shairport-sync to do noting and write a script that reads shairport-sync volume and sends it to CamillaDSP webservice. But I find the following proposal more generic and more elegant:

What do you think?

HEnquist commented 2 years ago

This seems like a quite useful addition! I'll take a look to see what kind of changes it would require. No promises for when that will happen though (or when those changes can be implemented).

Very interesting use of loopbacks and alsaloop, thanks for sharing I haven't seen anyone else syncing individual devices in this way.

Baffless commented 2 years ago

Yes, this feature is very welcome!

bitkeeper commented 10 months ago

With moOde we also uses the alsa loop back in this way. When this would directly be support by CamillaDSP we could drop the alsa/cdsp volume sync service https://github.com/bitkeeper/mpd2cdspvolume. The only benefit we have now is that we came make up our own volume curve.

HEnquist commented 6 months ago

This is included here: https://github.com/HEnquist/camilladsp/pull/341

HEnquist commented 6 months ago

This is working well, using the "PCM Playback Volume" mixer control on the loopback. But there is a problem that I don't get. On Fedora, the loopback has this control. Listing the controls with amixer -c 2 controls (the Loopback is card 2 on that system) includes the line numid=113,iface=MIXER,name='PCM Playback Volume'. But doing the same in Manjaro and Raspberry Pi OS, this control isn't there (but all the others are present). How can this control be enabled? @pavhofman do you know?

pavhofman commented 6 months ago

There is no volume ctl created in the aloop source.

IMO it's added by the softvol configuration in /usr/share/alsa/cards/Loopback.conf . Looking at the softvol code - the volume ctl is added to the slaved card, i.e. to the actual hw device, via IOCTL call to the kernel. So the ctl becomes available for all uses of the hw device - therefore listed by amixer -c CARD.

BUT the softvol operation is applied to the stream going through the softvol plugin, i.e. only when client opens a PCM (not HW) device and the softvol plugin is in its chain. Therefore the softvol ctl does nothing when the hw card is accessed directly. But since it's defined for the hw card, it contains the set value and behaves basically identically as the PCM Volume ctl created by the gadget driver. IMO it's just a coincidence, not intended for this purpose. The softvol is defined for many other cards in default alsa configs in /usr/share/alsa/cards.

However, note that only one Volume ctl is added for the card, no separate Volume ctls for each loopback device, like in case of PCM Slave Format/Channels/xxx controls added explicitly by the driver. While one loopback card can be used for two "wires" and its controls are defined for each device ("wire"), here only one Volume ctl is available, common for both directions.

There is one more caveat. The softvol ctl is created the first time the chain containing the softvol plugin is opened. I tried to list loopback card mixer on a freshly-booted bare debian distribution without pulseaudio and could not find out why the loopback device always had the Volume ctl defined. Alsa has many systemd units storing and restoring state, caches the state, etc. But it may happen that a different linux system, freshly installed, will not initialize the softvol ctl upon boot as the softvol plugin was never opened for the given card.

IMO using that Volume ctl for this purpose in CDSP is a hack which may work OK.

pavhofman commented 6 months ago

Just a note - if the loopback device configured for CDSP is a PCM which contains the softvol plugin in the chain (e.g. front:CARD=Loopback), the volume would be applied twice - by the softvol plugin and by the CDSP (or its playback device, if CDSP controls its Volume ctl instead).

HEnquist commented 6 months ago

Thanks @pavhofman for the excellent explanation! This makes it all make sense. A simple aplay -D front:CARD=Loopback,DEV=0 makes the mysterious volume control appear.

This also means that the way I implemented it now is fragile. I think the functionality is very useful, but there needs to be more active input from the user to enable it. I will change the use_virtual_volume boolean to an optional string, to let the user provide a name of a volume control to follow. This makes it explicit which control will be used.