Artisan Numérique

/système/audio/alsa/ Prédéterminer les indexes des périphériques Alsa

Le problème classique lorsque l'on gère plusieurs cartes son est leur indexation non déterministe qui empêchent d'allouer proprement et de manière systématique telle application à telle sortie. Fort heureusement le problème n'est pas insoluble, loin de là.

Le problème posé

Rappelons-le, les indexes des périphériques audio sont utilisés pour configurer la sortie des applications comme mplayer ou encore mpd. Et cela pose du coup un vrai problème lorsque ces indexes changent en fonction des circonstances.

Les indexes des cartes sont par défaut liés à l'ordre dans lequel leurs pilotes sont chargés par le noyau. Rien qu'à ce stade il y a déjà une bonne dose de hasard plus ou moins dépendant de leur disposition sur un bus PCI ou un hub USB, ou encore des états d'âme d'udev. Mais c'est surtout les cartes son USB qui posent finalement un vrai problème. En effet tout aléatoire qu'il soit, l'ordre est grosso-modo stable d'un redémarrage à l'autre. Mais cela devient une tout autre histoire dés que l'on débranche et rebranche des dongles USB, ou encore que l'on redémarre Alsa.

Il faut donc d'une manière ou d'une autre trouver un moyen de lier ces indexes à la carte et non plus à l'ordre de chargement.

Mon exemple

Sur mon portable (un Dell Vostro 3300), j'ai comme qui dirait "quelques" cartes son. J'ai tout d'abord une carte Intel, une carte nVidia, une carte son dans le clavier externe (enermax), une carte son dans les baffles Logitech, et enfin une autre pour mon casque sans fil.

Mon objectif est de placer la carte Intel en index 0 (carte par défaut), les baffles en index 1, le casque en index 2, et enfin de virer la carte du clavier et aussi la carte nVidia qui me fournit de très utiles sorties HDMI alors que je n'ai sur ce portable aucune prise de ce genre...

Les cartes fixes

Première partie de la résolution de notre problème, les pilotes Alsa permettent généralement tous de fixer l'indexe sur lequel ils se place. La seule information nécessaire pour procéder est donc de savoir quel pilote est utilisé par GNU/Linux pour quelle carte. Pour cela, nous allons utiliser la commande lsmod dont le rôle est justement de lister les pilotes chargés. Pour esquiver le flood, nous allons limiter cette liste aux pilotes audio par un grep snd :

gastonsudo lsmod | grep snd
Module                  Size  Used by
snd_hda_intel          20035  0
snd_usb_audio          64070  0
snd_usb_lib            13960  1 snd_usb_audio
(...)
A la recherche des pilotes audio

Ici nous voyons que deux modules audio sont utilisés snd_hda_intel et snd_usb_audio. Tout le reste sont des modules qui fournissent divers services (midi, timer, etc.).

Laissons de côté la partie USB pour se concentrer sur le pilote intel qui gère la sortie audio de la carte mère, et disons que nous voulons qu'en toute circonstance son index soit 0. C'est le cas généralement sauf si l'on s'amuse à redémarrer la couche Alsa par un sudo alsa force-reload. Dans ce cas il se trouve propulsé en dernière position et c'est le souk.

Pour fixer cet index nous allons devoir modifier le fichier /etc/modeprobe.d/alsa-base.conf (sous Debian, à faire varier selon les distributions) qui contient les options transmises aux modules en cours de chargement. Nous allons ajouter (ou modifier si elle existe déjà), la ligne suivant :

options snd-hda-intel index=0
Placement de la carte hda-intel à l'index alsa 0

Pas très sorcier hein... Notez cependant une chose, le remplacement des _ du nom du pilote par des - dans l'option correspondante. Ceci dit, je n'ai pas testé pour voir les les soulignés marchaient aussi. Pour info, les options d'un modules sont décrites par la commande modinfo prenant le module en paramètre. Et sans surprise nous y trouverons notion option index.

Pour que cette modification soit pris en compte, il suffit généralement de redémarrer la couche ALSA par sudo alsa force-reload.

Suppression d'une carte PCI

Pour la carte nVidia, c'est un peu plus galère. Elle n'a en effet aucun pilote que je puisse blacklister puisque cette puce est en réalité liée au chipset Intel. Heureusement elle il s'agit d'une carte pci : <

Voyons maintenant comme régler leur compte aux cartes USB.

Carte son via USB

Là ça se corse car il n'y a pas de pilote différencié par carte son USB. Toute utilise le générique snd_usb_audio. Mais si nous donnons un coup de sudo modinfo snd_usb_audio nous découvrons, en plus d'index, trois options intéressantes :

gastonsudo modinfo snd-usb-audio
filename:       /lib/modules/2.6.32-5-amd64/kernel/sound/usb/snd-usb-audio.ko
license:        GPL
description:    USB Audio
author:         Takashi Iwai <tiwai@suse.de>
(...)
parm:           index:Index value for the USB audio adapter. (array of int)
parm:           enable:Enable USB audio adapter. (array of bool)
(...)
parm:           vid:Vendor ID for the USB audio device. (array of int)
parm:           pid:Product ID for the USB audio device. (array of int)
(...)
information sur le module usb audio

Il s'agit de enable, vid et pid. Intéressons nous d'abord à vid et pid qui désignent respectivement le code vendeur et produit d'une périphérique USB. Utilisons donc la commande lsmod pour déterminer ces codes pour nos cartes audio :

gastonlsusb
(...)
Bus 008 Device 002: ID 046d:0a13 Logitech, Inc. Z-5 Speakers
(...)
Bus 002 Device 002: ID 046d:0a29 Logitech, Inc.
(...)
Bus 001 Device 007: ID 0d8c:000e C-Media Electronics, Inc. Audio Adapter (Planet UP-100, Genius G-Talk)
(...)
liste des périphériques audio USB

Les codes vendeurs sont donc 046d pour les deux cartes logitech et 0d8c pour la carte C-Media. Les codes produit sont 0a13 pour mes baffles, 0a29 pour mon casque et 000e pour la carte son intégrée au clavier. Reportons tout cela dans le fichier /etc/modprobe.d/alsa-base.conf. Notez la présences du 0x devant chaque code (c'est de l'hexa)

options snd-usb-audio index=1,2,3 vid=0x046d,0x046d,0x0d8c pid=0x0a29,0x0a13,0x000e
Indexes pour les cartes USB

De la sorte, l'index 1 est pour le casque, l'index 2 pour les baffles et 3 pour le clavier. Pour tester, relançons comme d'habitude la couche ALSA et regardons ce que cela donne :

gastonsudo rmmod snd_usb_audio snd_hda_intel
gastonsudo modprobe snd_usb_audio snd_hda_intel
gastoncat /proc/asound/cards
0 Intel          : HDA-Intel - HDA Intel
HDA Intel at 0xfa100000 irq 22
1 Headset        : USB-Audio - Logitech Wireless Headset
Logitech Logitech Wireless Headset at usb-0000:00:1a.0-1, full speed
2 Speakers       : USB-Audio - Logitech Z-5 Speakers
Logitech Logitech Z-5 Speakers at usb-0000:00:1d.2-1, full speed
3 Keyboard       : USB-Audio - Generic USB Audio Device
Generic USB Audio Device    at usb-0000:00:1a.7-3.2, full speed
test des indexes

C'est presque bon. Voyons maintenant comment virer la carte 3 qui ne me sert à rien.

Conclusion

Et voilà, c'est gagné. Maintenant les indexes sont stables en toutes circonstances. Reste cependant un cas non traité, les indexes des cartes audio strictement identiques. Pour cela je n'ai jamais trouvé de solution. Mais pour tout le reste, le fait de pouvoir ainsi fixer les indexes permet de paramétrer proprement nos applications carte par carte, sans risque de se retrouver à court de son.