Prev: UEFI Booting for OpenSuSE | Next: VoIP Versus Intrusion Alarm |
(Index) |
Nothing has changed in your sound setup for three
years, and sound is playing correctly, e.g. aplay
/usr/share/sounds/alsa/test.wav
or similary for PulseAudio.
Then you sneeze, and sound stops playing.
Tested under strace, the program (alsamixer, this time) does not fail.
And then when you try to write down the
complete symptom set, it starts working again.
Command line tools report different error messages at different
times. A gallery of culprits:
ALSA lib conf.c:1697:(snd_config_load1) _toplevel_:2:1:Unexpected char
ALSA lib conf.c:1697:(snd_config_load1) _toplevel_:34:10:default is not a string
(this one is from memory, sorry.)
GUI tools such as xfce4-panel-plugin-mixer claim that there are no valid devices.
PulseAudio, which is configured to work through ALSA, cannot play any sounds.
Firefox cannot play any sounds, e.g. from Youtube videos.
I have no solid evidence. It feels to me like a race condition, or an uninitialized variable, or an overflow in the buffer containing one of the strings from ~/.asoundrc .
The device called default
is special: it is used
if no device is specified to play on (or capture from). It can be defined
in ~/.asoundrc by this motif:
pcm.!default = pcm.azalia;
I've found that when ALSA is failing, if I put the '!' before
default
it (usually) starts working again. Later if I remove it,
ALSA may or may not continue to work. '!' means that the assigned value
takes precedence over other assignments.
/proc/asound/cards gives a cross-reference between the card number, the alphabetic ID, the description, and the bus address.
/proc/asound/devices is a summary of the available devices. The line format goes like this:
3: [ 0- 3]: digital audio playback
Index: [ Card_nbr- device_nbr]: Description
~/.asoundrc is the place where the user can define names for the various devices, and other magical things if we could just find and then understand the documentation.
Here's an example of a very simple stanza in .asoundrc:
# AMD emulation of Soundblaster or Intel Azalia, with ATTR{id} = SB pcm.azalia = { type = hw; card = SB; device = 0; }; ctl.azalia = { type = hw; card = SB; }; pcm.!default = pcm.azalia;
You need to define both the pcm and ctl objects with the same name. The type and card have to be the same (except no card for Bluetooth). Only the pcm needs the device, not ctl. Each assignment must end with a semicolon. Lines beginning with # are comments, and empty lines are ignored. Whitespace is probably optional everwhere.
You can use the pcm's name in the -D option of aplay or arecord:
aplay -D azalia $soundfile
I know that this device usually ends up as card1. The bad old traditional pcm ID for this device would be:
aplay -D hw:1,0 $soundfile
In the modern kernel with udev and systemd, device drivers are loaded in parallel, producing a guaranteed race condition for picking device numbers, so major and sometimes minor numbers can change from one boot to the next. Recommended to mitigate this:
For sound cards, in /proc/asound you will find symbolic links from
the middle word of the description, such as Generic
, to one of
the numbered cards. Use this ID in place of the card number in sound
configurations such as ~/.asoundrc or in the -D option of command line
tools. For example: aplay -D hw:Generic,0 $soundfile
To assign a more memorable ID, add a udev rule similar to this one (with appropriately substituted product identifiers); suggested filename: /etc/udev/rules.d/26-sound.rules . It needs a low number; something that comes later prevents the rule from working.
ATTR{id}=="*" ATTRS{idVendor}=="06e1" ATTRS{idProduct}=="a155" ATTR{id}="FMRadio"
ATTR{id}=="*" picks a device that has an ID that you can set -- '==' is for comparison, '=' for assignment. Find one ancestor that has unique attributes (see below) and use ATTRS{…} to represent them. Finally, give a more useful ID to the target device.
To discover attributes that select your sound card, first you need its /dev/ path, e.g. /dev/snd/pcmC1D0p for card 1 device 0 playback. Then do:
udevadm info --attribute-walk --name=/dev/snd/pcmC1D0p |& less
For disc drives, provide a volume label and mount by that, or mount by UUID, which is the default on SuSE systems. I once had to maintain a super workstation with 4 discs which would enumerate them in a random order every time.
For network devices, names determined by the bus location have been available and have gone in and out of favor for the last few years. If your firewall is identical or similar on all hosts and gives special privileges or protection to particular interfaces, the bus names may be consistent over reboots but are individual per machine type.
Currently in SuSE Tumbleweed (2017-08-07) they are on by
default and you can select traditional
names by adding a kernel
command line parameter of net.ifnames=0 . Then you need to supply
a udev rule to stabilize the numbering, similar to this one
(substitute the actual MAC address, individual per network card, beware
in case of hardware repairs). Commonly used filename:
/etc/udev/rules.d/70-persistent-net.rules
# Net device eth0 0x10ec:0x8168 (r8169)
SUBSYSTEM=="net", DRIVERS=="?*", ATTR{address}=="00:01:c0:12:30:44", KERNEL=="eth*", NAME="eth0"
Prev: UEFI Booting for OpenSuSE | Next: VoIP Versus Intrusion Alarm |
(Index) |