I understand that the intended way of restoring a custom mixer state for ASLA sound cards on boot, is to do something like
alsactl store -f /storage/.config/sound.conf
which would then restore the state of the mixers of all devices to that stored when the above command was executed. This does not quite work for me.
Running
alsactl restore-f $HOME/.config/sound.conf
manually at any point via SSH works fine, but it doesn't work on boot, even though the soundconfig script does run (i.e. I do see "Setting up sound card" in the journal logs).
There seem to be various interesting things about that setup. First, the udev rule in charge of running this script, is
KERNEL=="controlC[0-9]*", NAME="snd/%k", ACTION=="add", RUN+="soundconfig %k"
Now that NAME="snd/%k" part, which presumably is meant to say something like "match only events having to do with snd/controlC*", actually is an action saying "rename this network interface to that". As this is not a network inteface, the journal has lines like
Quote
(udev-worker)[402]: controlC1: /usr/lib/udev/rules.d/90-alsa-restore.rules:5 Only network interfaces can be renamed, ignoring NAME="snd/%k".
and that action has no effect. The system-shipped rule on my PC additionally has a KERNELS!="card*" rule. I'm not quite clear on what it's there for, but if I'm interpreting the intent of that NAME action correctly, I suspect it's doing something similar.
On another note, that KERNEL=="controlC[0-9]*" looks like its meant to be a regular expression, saying "controlC, potentially followed by numbers", but these are actually glob patterns, so it means "controlC, followed by a number and whatever else". If that is the case, it doesn't hurt, but the rule on my PC has just KERNEL=="controlC*", which is probably enough.
Moving on to the soundconfig script, the relevant portion in it, reads:
if [ -f $HOME/.config/sound.conf ]; then
alsactl restore -f $HOME/.config/sound.conf
else
...
One issue with this, is that it gets run when each card gets added to the system, and when there's no saved state, it does initialize that specific card. When there is a saved state though, it attempts to reset the state of all cards each time a new card gets added. That probably doesn't break anything but it should result in some wasted work. The restore command does take an optional card argument, so that can be improved.
Anyway, all of that doesn't seem to have anything to do with my problem. My problem seems to be more insidious and I suspect there's some sort of race going on. I've tried various changes and got it to work, but I'm not sure as to the how and why. It seems that after attaching something like > /tmp/log 2>&1 to the end of the alsactl command (which I did just to get any error messages) it did work. If I then removed it, it kept working for some reason. (I should say here that for testing purposes, I installed a copy of the system-wide udev rule inside /etc/udev/rules.d, running a copy of soundconfig, which I could then edit and retry, by removing and reloading my sound card's module to get the device to disappear and reappear.)
I took a guess and removed that final & in the soundconfig script, backgrounding the whole subshell and it now works correctly. I'm not sure why, but I have the vague notion that the main script's shell exits before the subshell has finished and something tricky happens there.
So, in conclusion:
1. Does this work for you?
2. Is there some specific reason for backgrounding the subshell?
3. I have a patch for most of the changes discussed here. Would there be interest in trying them out and potentially applying them? Should I open a PR?