MPD icon indicating copy to clipboard operation
MPD copied to clipboard

ALSA device aliases in "device" and "mixer_device"

Open tremby opened this issue 6 years ago • 18 comments

TLDR: final paragraph.

I'm using MPD 0.20.16 on Raspberry Pi 3, with a Hifiberry Amp2.

I had some weirdness with my ALSA hardware devices today. One of my devices (Raspberry Pi's built-in audio device) temporarily disappeared from /proc/asound/cards for reasons beyond me. (I was tinkering with my Raspberry Pi and Kodi settings, so it's almost certainly my fault, but I didn't figure out exactly what was happening.) I didn't have time to debug since I had some people over and wanted to play music, so I just did whatever worked, and that was setting the device to hw:0 while it was usually hw:1.

I still haven't figured out exactly what happened, but both devices are back now. I wondered if there was a way to specify devices by name rather than hardware address, and found online that there's such a thing as ALSA device aliases. I tried using one in the device setting in my configuration as I saw in that Q&A, and found that it worked. Great!

But what about the volume control? The mixer_device had also been hw:1, and I tried setting it to the same thing I had set device to, but that was not accepted.

I later found that just commenting out that option did work. The docs say the default is default, but I'm not clear on what this means -- I don't know if now this particular device is the system default (now that it's device 1 again I don't know why it would be the default) or if the default is to use the same device as in device.

So the main question I have is: is it possible to make mixer_device accept ALSA device aliases, as device does?

tremby avatar Oct 17 '18 08:10 tremby

All MPD does is call snd_mixer_attach() and pass the configured value to that function. The documentation of libasound is very sparse, and it doesn't tell what kind of values are valid here.

MaxKellermann avatar Oct 17 '18 08:10 MaxKellermann

OK, that's a shame that upstream things are inconsistent.

Can you tell me if the default setting for mixer_device is either of the things I suggested above? To reiterate, does leaving that configuration option absent set it to the system default mixer, or does it use whatever device device is set to, or is it something else? (Or is this totally up to ALSA too, i.e. MPD in this case just lets ALSA do whatever it wants?)

tremby avatar Oct 17 '18 08:10 tremby

The default setting is default (yes, really), which appears to be a magic string accepted by snd_mixer_attach(). The ALSA API is a mystery to me. It's very powerful, but heavily under-documented.

MaxKellermann avatar Oct 17 '18 08:10 MaxKellermann

I see, so it's just ALSA magic, and if default seems to work for me, I guess it's OK!

It seems like what ALSA does with these config values is totally out of MPD's hands, so I guess the right thing is just to close this ticket, but I'll leave its fate up to you. Thanks, Max.

tremby avatar Oct 17 '18 09:10 tremby

As you have already found, you can get a list of sound card names by typing: $ cat /proc/asound/cards The first digit is the index of the card, the name in square brackets is the identifier used by alsa libasound.

For example, I have an IQAudio DigiAMP+ rather than your HifiBerry DAC, and I also have the HDMI hardware enabled in the kernel but the 3.5mm jack disabled. So I get: $ cat /proc/asound/cards 0 [HDMI ]: bcm2835_hdmi - bcm2835 HDMI bcm2835 HDMI 1 [IQaudIODAC ]: IQaudIODAC - IQaudIODAC IQaudIODAC

In ALSA configurations I can refer to the HDMI card either as hw:0 or as hw:HDMI and the IQAudio card either as hw:1 or as hw:IQaudIODAC

ALSA then constructs names for each PCM device using the forms: hw:0,0 or hw:CARD=HDMI,DEV=0 hw:0,1 or hw:CARD=HDMI,DEV=1

hw:1,0 or hw:CARD=IQaudIODAC,DEV=0

and so on. You can get a full list of the hardware devices on your system with: $ aplay -L | grep ^hw: hw:CARD=HDMI,DEV=0 hw:CARD=IQaudIODAC,DEV=0

ALSA provides 2 control interfaces; MPD uses the "simple" control (scontrol) interface, and you can list all the scontrols for a particular card with: $ amixer -c CARDNAME scontrols where CARDNAME is the name of the card as reported by /proc/asound/cards. For example: $ amixer -c IQaudIODAC scontrols Simple mixer control 'DSP Program',0 Simple mixer control 'Analogue',0 Simple mixer control 'Analogue Playback Boost',0 Simple mixer control 'Auto Mute',0 Simple mixer control 'Auto Mute Mono',0 Simple mixer control 'Auto Mute Time Left',0 Simple mixer control 'Auto Mute Time Right',0 Simple mixer control 'Clock Missing Period',0 Simple mixer control 'Deemphasis',0 Simple mixer control 'Digital',0 Simple mixer control 'Max Overclock DAC',0 Simple mixer control 'Max Overclock DSP',0 Simple mixer control 'Max Overclock PLL',0 Simple mixer control 'Volume Ramp Down Emergency Rate',0 Simple mixer control 'Volume Ramp Down Emergency Step',0 Simple mixer control 'Volume Ramp Down Rate',0 Simple mixer control 'Volume Ramp Down Step',0 Simple mixer control 'Volume Ramp Up Rate',0 Simple mixer control 'Volume Ramp Up Step',0

In order to choose the appropriate scontrol to manage the volume you would need to consult the HiFiBerry documentation. For the IQAudio DAC it is the scontrol called "Digital"

Now to convert all this to mpd.conf terminology: "device" maps to a PCM playback device name (obtained from aplay -L) "mixer_device" maps to a card name (with the hw: prefix) "mixer_control" maps to a scontrol name (obtained from amixer -c ... scontrols)

So in my mpd.conf I have the following two outputs defined:

audio_output { type "alsa" name "IQAudio" device "hw:CARD=IQaudIODAC,DEV=0" mixer_type "hardware" mixer_device "hw:IQaudIODAC" mixer_control "Digital" }

audio_output { type "alsa" name "HDMI" device "hw:CARD=HDMI,DEV=0" mixer_type "hardware" mixer_device "hw:HDMI" mixer_control "HDMI" }

Hope this helps.

borine avatar Oct 24 '18 13:10 borine

Thanks @borine - I think that explanation was very helpful. Even I have learned something from it. It would be even more helpful to improve the MPD user manual to have those explanations. https://github.com/MusicPlayerDaemon/MPD/blob/master/doc/user.rst Pull request welcome!

MaxKellermann avatar Oct 24 '18 14:10 MaxKellermann

Fantastic, thank you, @borine. That all worked for me.

The mysteries which remain to me:

  • Why is the syntax for device so different from the syntax for mixer_device?
  • Which device would be chosen for the mixer if set to default -- the same as the output device, or some system default device which might in some circumstances be different?

tremby avatar Oct 24 '18 18:10 tremby

The values entered in mpd,conf against "device" and "mixer_device" are just meaningless strings as far as MPD is concerned - as Max says, MPD just passes them on the the ALSA libasound API. MPD does not define the syntax, nor does it attempt to parse it. If you want to understand the syntax, and the meaning of virtual names such as "default", then you need to be asking on an ALSA forum as it really has nothing to do with MPD.

borine avatar Oct 24 '18 19:10 borine

Sure, I understood that much, I just thought you may know the answer off the top of your head. Thanks.

tremby avatar Oct 24 '18 20:10 tremby

Where did you learn this shit? I haven't seen hw:CARD=xxx,DEV=xxx documented anywhere.

crocket avatar Dec 13 '19 04:12 crocket

@crocket alsa documentation is notoriously sparse, ambiguous and incomplete. Often reading the source code is the only way to make sense of a feature. In this case, start reading here: https://github.com/alsa-project/alsa-lib/blob/780f17126aa8d54fc09694cbf652d4135eb731c0/src/conf.c#L5174

borine avatar Dec 15 '19 14:12 borine

@borine Old thread but still saving sanity. I should have added this years ago for those that have topping D50 Dacs... # amixer -c 2 scontrols Simple mixer control 'D50 ',0 Simple mixer control 'D50 ',1

Somewhere firmware/alsa they added an extra space at the end of the name so in MPD config:

mixer_device "hw:D50" # optional # Note the HACK firmare or alsa configs have an added space so it NEVER finds the mixer mixer_control "D50\ " # optional mixer_index "0" # optional }

I hope that helps someone else some day like the scontrols tip from @borine helped me see it.

mwk1000 avatar Dec 18 '23 16:12 mwk1000

It's 2024 and that explanation from @borine is still hella informative. Thank you.

ezekieldas avatar Apr 15 '24 18:04 ezekieldas

Somewhere firmware/alsa they added an extra space at the end of the name so in MPD config:

mixer_device "hw:D50" # optional # Note the HACK firmare or alsa configs have an added space so it NEVER finds the mixer mixer_control "D50\ " # optional mixer_index "0" # optional }

I hope that helps someone else some day like the scontrols tip from @borine helped me see it.

My mixer_control appears as: Simple mixer control 'MISSION USB Audio 2.0 ',0 but I'm unable to put extra space in mpd.conf setting, also escape is ignored and log says: mixer: Failed to read mixer for 'MISSION USB Audio 2.0': no such mixer control: MISSION USB Audio 2.0

Any help?

mimmus avatar Jul 04 '24 08:07 mimmus

You must not insert a backslash into the given control name. If amixer gives:

amixer scontrols
...
Simple mixer control 'MISSION USB Audio 2.0 ',0
...

Then your mpd.conf entry should be

audio_output {
    ...
    mixer_type "hw"
    mixer_control "MISSION USB Audio 2.0 "
   ...
}

... and of course you need to make sure you use the correct mixer_device parameter

Just to be sure this really is the correct volume control, when you try

amixer sset 'MISSION USB Audio 2.0 ' 50%

Does the device volume actually change to 50%?

borine avatar Jul 04 '24 11:07 borine

I already tried with a space in my mpd.conf 'mixer_control' setting but it's ignored, probably trimmed by some internal routine.

amixer --card 3 sset 'MISSION USB Audio 2.0 ' 50% works

mimmus avatar Jul 04 '24 11:07 mimmus

probably trimmed by some internal routine.

No, MPD does not "trim" or otherwise modilfy the given string in any way. The string you put in mpd.conf is the string that MPD passes to the ALSA mixer API.

I just created an ALSA softvol control called 'MISSION USB Audio 2.0 '

$ amixer scontrols
Simple mixer control 'Master',0
Simple mixer control 'Headphone',0
Simple mixer control 'Speaker',0
Simple mixer control 'PCM',0
Simple mixer control 'Mic Boost',0
Simple mixer control 'IEC958',0
Simple mixer control 'IEC958',1
Simple mixer control 'IEC958',2
Simple mixer control 'Capture',0
Simple mixer control 'Auto-Mute Mode',0
Simple mixer control 'Digital',0
Simple mixer control 'Internal Mic Boost',0
Simple mixer control 'MISSION USB Audio 2.0 ',0

and modified my mpd.conf

audio_output {
        name "Default"
        type "alsa"
        device "default"
        mixer_type "hardware"
        mixer_device "default"
        mixer_control "MISSION USB Audio 2.0 "
}

re-started MPD and now mpc vol is controlling that softvol control correctly. So this is not a generic problem with MPD nor ALSA. Something very specific to your setup is happening.

borine avatar Jul 04 '24 11:07 borine

I’m trying ro get this DAC working without vendor support, all is possible.

Sorry I opened also another issue

mimmus avatar Jul 04 '24 12:07 mimmus