La Lanterne Rouge

La Lanterne Rouge

Warning: Geek Inside

Publié le par Nanawel
Publié dans : #linux | #nvidia | #intel | #pulseaudio | #systemd | #udev | #multiseat | #xorg

Si jusqu'à présent la plupart de mes articles concernant Linux étaient très orientés "serveur" ou du moins "headless", suite à mon changement de configuration matérielle et mon passage à Archlinux comme OS principal, je vais commencer à élargir un peu et tenter d'aborder certains aspects plus "desktops".

Comme je l'ai expliqué il y a quelques semaines, je suis passé d'un triple-head sous Windows XP à un (potentiel) triple-head sous Archlinux.

Si sous Windows le nombre d'écrans disponibles est presque un détail car le panneau de configuration autorise tous les agencements possibles facilement, sous Linux c'est encore un peu laborieux. Alors quand en plus il s'agit de faire cohabiter deux adaptateurs graphiques de constructeurs différents (j'entends NVidia, AMD ou Intel), il ne faut pas espérer conserver beaucoup de cheveux sur le crâne à la fin de l'opération... si fin il y a !

En parlant de fin, elle arrivera peut-être plus tard car ce que je vais présenter ici n'est pas - et de loin - ce que je qualifierai de "solution parfaite ferme et définitive". Mais je me lance quand même.

Schéma résumant ma précédente configuration sous Windows XP

Schéma résumant ma précédente configuration sous Windows XP

Quoi que c'est-y pour faire ?

J'ai la chance d'avoir mon PC sur mon bureau (enfin, sous, mais passons) à trois mètres à peine de mon canapé, ce qui me permet facilement de passer de l'un à l'autre au gré de mes envies. Cela fait quelques années que j'utilise un dual-head et je m'arrangeais jusque-là pour toujours avoir un des moniteurs visible depuis le "coin à glandouille", à savoir maintenant le canapé (mais avant c'était une chaise; mais ça c'était avant que je ne devienne milliardaire et que je n'exige que du mobilier suédois sur-mesure). C'était bien. Mais déménagements et réorganisations ont finalement eu raison de cette option. Et quand j'ai acquis la première version d'Usul j'ai également obtenu mon fameux moniteur HD "gratuit", un petit 22" en 16/9 mais qui me satisfait pleinement.

Au départ relié à mon PC via un adaptateur USB-VGA, j'ai finalement craqué pour une carte graphique secondaire en PCI-Express 1x (seul port disponible restant), une petite GeForce 210 qui fait autant de bruit qu'un Concorde à l'écrasement, je veux dire, à l'atterrissage.

Depuis, je disposais d'un bureau Windows de 5760x1080 réparti sur trois moniteurs. Bon, en fait la GeForce 210 peinait un peu à gérer la résolution HD pour tous les films et toutes les vidéos Flash, donc j'ai été obligé de réduire la définition de son affichage à 1440x900, ce qui en plus avait l'avantage de rendre les textes plus gros, donc plus lisibles (mouais, vite fait alors). J'avais donc réellement du 5280x1080 dont une bande supérieure était inutilisable sur le troisième moniteur.

Pour contrôler tout ça, il y avait tout d'abord le clavier et la souris filaires sur le bureau, et au départ un clavier et souris sans-fil pour le canapé. J'ai ensuite remplacé avantageusement ces derniers par un clavier K400r de Logitech avec touchpad plus compact, plus léger, donc plus maniable. J'y ai juste perdu le pavé numérique. Tout ce beau monde est évidemment en USB (cela aura une certaine importance pour la suite).

J'insiste donc maintenant sur le fait que tout était alors partagé : session, programmes, et évidemment : claviers et souris. Pendant que j'étais affairé à mon bureau, un petit malin pouvait depuis le canapé taper des bêtises sur la fenêtre ayant le focus sur n'importe quel moniteur (c'est-à-dire la plupart du temps celle sur laquelle j'opérais). Idem pour remuer le pointeur et m'empêcher de cliquer sur le bouton que je visais. Heureusement, la plupart du temps, la menace de retrait de bière et son remplacement par de l'eau plate suffisait à calmer le malin en question.

Cette configuration fonctionnait pour les raisons suivantes :

  • Windows retient plutôt bien les emplacement et tailles des fenêtres pour chacune des applications et les restaure à leur redémarrage. Il affiche cependant presque toujours les boîtes de dialogue sur le moniteur "courant" (celui contenant le pointeur), ce qui est un comportement "logique".
  • Media Player Classic HC - mon lecteur vidéo favori sous Windows - s'ouvre automatiquement sur le moniteur sur lequel se trouve le pointeur de la souris, il suffit donc de positionner un raccourci sur le moniteur du canapé pour que le lecteur apparaisse sur celui-ci quand on le lance.
  • Grâce au point 1 il suffit d'installer Firefox Portable et d'ajouter un raccourci sur le moniteur du canapé pour que celui-ci conserve son emplacement à chaque ouverture une fois positionné sans interférer avec le Firefox "fixe" dont la fenêtre s'affiche sur un des moniteurs du bureau.

Et sous Linux ?

Une fois mon Archlinux installé et grossièrement fonctionnel avec XFCE, j'ai évidemment (et "bêtement") souhaité reproduire le même schéma sous cet environnement. Mais il n'a pas fallu trop de recherches ni de tests pour me rendre compte que les trois points qui en faisaient une solution viable sous Windows étaient impossible à conjuguer sous Linux (en tout cas sous XFCE ou Gnome) : l'emplacement des fenêtres à leur ouverture dépend du bon vouloir de l'application :

  • VLC et Firefox s'ouvrent sur le moniteur courant (qui affiche le pointeur à ce moment-là)
  • Chromium conserve son emplacement précédent
  • SMPlayer s'ouvre toujours sur le moniteur principal (dans mon cas, celui du milieu)
  • De nombreuses autres applications ont leurs fenêtres qui s'affichent aux coordonnées (0,0), donc en haut du moniteur gauche du bureau

Je suis par contre régulièrement tombé sur des gens parlant de "multiseat", sans savoir au départ que c'était une solution possible et même préférable pour mon cas.

Après renseignement, j'ai décidé de tenter le coup.

 

Le multiseat, c'est - dixit Wikipédia - "une configuration par laquelle un ordinateur unique permet à plusieurs utilisateurs locaux indépendants (les "seats") de travailler en parallèle". Pour simplifier, il s'agit d'avoir une UC unique, et N couples moniteur-clavier-souris, N dépendant évidemment de la configuration matérielle de l'UC et des ports de chaque type dont elle dispose.

Multiseat 4 postes, By Tiago Vignatti / Rattus [GFDL (http://www.gnu.org/copyleft/fdl.html) or CC-BY-SA-3.0 (http://creativecommons.org/licenses/by-sa/3.0/)], via Wikimedia Commons

Multiseat 4 postes, By Tiago Vignatti / Rattus [GFDL (http://www.gnu.org/copyleft/fdl.html) or CC-BY-SA-3.0 (http://creativecommons.org/licenses/by-sa/3.0/)], via Wikimedia Commons

Je dois avouer que la mise en place d'une telle configuration nécessite une obstination (un acharnement même) et une implication de compétition. La tâche est - je pense - rendue encore plus ardue par l'utilisation de composants récents dont les pilotes ne sont évidemment ni complètement stables ni complets.

Je vais donc détailler à qui serait intéressé par le montage d'un système similaire les principales étapes indispensables.

Attention : il ne s'agit pas d'une tutorial générique mais de mon expérience, avec mes composants, et ma configuration. Des adaptations plus ou moins importantes peuvent être nécessaires en changeant de distribution Linux, de matériel, ou d'environnement de bureau.

Précision importante et potentiellement décevante : j'utilise le pilote libre Nouveau et non le pilote propriétaire NVidia. Cela permet d'obtenir des performances similaires en 2D mais la 3D est fortement dégradée ce qui interdit tout jeu un peu gourmand (même L4D2 ne tourne pas à plus de 15 FPS). La raison de ce choix est que cela n'en est pas un : en effet je ne suis pas arrivé à obtenir une configuration stable avec le pilote NVidia pour le moment. Cela reste néanmoins dans ma TODO-list car je sais que cela reste possible.

Présentation générale

Mon objectif ici a été de mettre en place un système de double session sur mon PC : un premier utilisateur pour le dual-head du bureau, pour les tâches usuelles (surf, dev, administration, lecture de musique et de vidéos) et un second utilisateur pour le canapé (principalement pour de la lecture de vidéos mais également du surf léger et de la lecture de musique). Le bureau aura son couple clavier-souris filaires, et le canapé son clavier sans-fil avec touchpad, chacun ne contrôlant que sa propre session évidemment.

Pourquoi deux utilisateurs ? Tout simplement car nous allons devoir lancer deux instances du serveur X, et qu'il n'est pas possible facilement et surtout pas conseillé de faire cela avec le même utilisateur. Ensuite cela permet de séparer clairement les configurations des environnements (XFCE et applications) qui, du reste, n'auront pas le même contexte (matériel), ainsi que d'appliquer des permissions plus fines à l'utilisateur du canapé et empêche le petit malin du paragraphe au-dessus de jouer avec les fichiers de l'utilisateur principal.

J'ai repris le diagramme du montage sous Windows que j'ai adapté aux nouveaux objectifs :

Une configuration multiseat sous GNU/Linux

Avertissement : si vous vous décidez de vous lancer ce genre de procédure, assurez-vous d'avoir mis en place au préalable un serveur SSH sur la machine et d'avoir un client SSH connecté au même réseau (filaire de préférence !) pour pouvoir relancer le gestionnaire d'affichage ou rebooter si nécessaire. Les bidouilles suivantes touchent en effet au clavier et à la souris, périphériques qui sont vos seuls moyens de communication avec le système !

Configuration de Xorg

Un gros morceaux !

Tout d'abord il faut savoir que Xorg depuis déjà quelques années fonctionne parfaitement en Plug-and-Play sans fichier de configuration sur la majorité des installations. Il saura trouver tout seul les périphériques, les cartes graphiques et les écrans et adapter la définition de l'affichage à chacun. Cependant il s'agit d'une configuration "par défaut" qui ne conviendra pas toujours à l'utilisateur, surtout s'il est un peu geek et qu'il a des lubies bizarres. Dans ce cas, la configuration manuelle (ou semi-manuelle) est inévitable. (attention, on perd dans ce cas cette "adaptabilité" automatique proposée par X)

L'objectif de cette section sera donc de définir les "seats" et leurs périphériques associés.

Pour générer un template de configuration j'ai utilisé Xorg -configure afin d'avoir déjà de nombreuses valeurs pré-remplies. J'ai ensuite largement modifié certaines directives et les ai réparties dans des fichiers séparés pour améliorer la lisibilité et la maintenance.

 

Avant de commencer, il est indispensable de connaître un minimum la structure des fichiers de configuration de Xorg (voir ici et ici). Je dois dire que j'ai beaucoup appris de cette expérience car jusqu'ici je n'avais eu qu'à modifier quelques lignes bien précises (remplacer un driver par un autre, ajouter des options au clavier, etc.).

Un schéma qui résume par ailleurs très bien les sections de configuration est disponible dans la doc de Fedora :

Une configuration multiseat sous GNU/Linux

Je ne vais pas paraphraser la page de documentation (qui est très bien faite d'ailleurs) mais sachez juste que j'ai dû créer un ServerLayout par seat.

J'ai regroupé les directives définissant chaque seat dans un fichier dédié. Je parlerai désormais de seat principal ("Main", bureau) et secondaire ("Aux", canapé).

ServerLayout "Main"

Les directives suivantes ont été placées dans le fichier /etc/X11/xorg.conf.d/50-serverlayout-main.conf

Section "ServerLayout"
    Identifier     "Layout-Main"
    Screen         "Screen-Main" 0 0
    InputDevice    "Logitech-Illuminated" "CoreKeyboard"
    InputDevice    "Logitech-G100S" "CorePointer"
    Option         "AllowEmptyInput"  "true"
EndSection

Section "InputDevice"
    Identifier     "Logitech-G100S"
    Driver         "evdev"
    
    Option         "Protocol" "auto"
    Option         "Device" "/dev/input/by-id/usb-Logitech_G100s_Optical_Gaming_Mouse-event-mouse"
    Option         "Emulate3Buttons" "no"
    Option         "ZAxisMapping" "4 5"
    Option         "GrabDevice" "on"
EndSection

Section "InputDevice"
    Identifier     "Logitech-Illuminated"
    Driver         "evdev"
    
    Option         "XkbLayout" "fr"
    Option         "XkbModel" "pc104"
    Option         "Device" "/dev/input/by-id/usb-Logitech_Logitech_Illuminated_Keyboard-event-kbd"
    Option         "GrabDevice" "on"
EndSection

Section "Monitor"
    Identifier     "Monitor0"
    VendorName     "Samsung"
    ModelName      "Samsung SyncMaster 2433"
    HorizSync       30.0 - 81.0
    VertRefresh     56.0 - 60.0
    Option         "DPMS"
EndSection

Section "Monitor"
    Identifier     "Monitor1"
    VendorName     "Samsung"
    ModelName      "Samsung SyncMaster 2333sw"
    HorizSync       30.0 - 81.0
    VertRefresh     56.0 - 60.0
    Option         "DPMS"
EndSection

Section "Device"
    Identifier     "NVIDIA-GTX760"
    Driver         "nouveau"
    VendorName     "NVIDIA Corporation"
    BoardName      "GeForce GTX 760"
EndSection

Section "Screen"
    Identifier     "Screen-Main"
    Device         "NVIDIA-GTX760"
    Monitor        "Monitor0"
    DefaultDepth    24
    SubSection     "Display"
        Depth       24
    EndSubSection
EndSection

Il y a donc une section par composant matériel (InputDevice, Monitor, Device), puis un couple carte graphique/moniteur pour former un écran (Screen) et enfin un agencement d'affichage qui utilise les briques précédentes (ScreenLayout). Le diagramme ci-dessous résume cette configuration de manière un peu plus graphique :

Une configuration multiseat sous GNU/Linux

Les points à noter :

  • section Screen : seul un moniteur est déclaré ("Monitor0"). En fait j'ai réalisé de nombreux tests infructueux avant d'opter pour cette configuration. La configuration en dual-screen sera appliquée une fois la session du DE lancée via xrandr (voir paragraphe plus loin). Sur l'écran de login, les deux moniteurs afficheront donc la même image en mode "clone".
  • section ServerLayout : la directive AllowEmptyInput a été ajoutée au départ, car si les périphériques utilisés par le seat ne sont pas disponibles/initialisés quand le serveur X se lance, le démarrage échoue. Nous verrons plus loin qu'après la mise en place des dépendances via udev/systemd ce cas ne peut normalement plus se produire, mais j'ai malgré tout conservé cette ligne.
  • sections InputDevice : par rapport à une configuration automatique j'ai renseigné précisément les périphériques à utiliser, et pour cela j'ai utilisé leurs alias disponibles dans le pseudo-système de fichiers /dev/input/by-id/*. Comme ces périphériques apparaissent souvent sous la forme de plusieurs entrées, il faut les essayer une par une si les noms seuls ne permettent pas de déterminer laquelle utiliser.


Exemple sur ma machine :

$ ls -l /dev/input/by-id/
lrwxrwxrwx 1 root root 10 29 juin 21:13 usb-Logitech_G100s_Optical_Gaming_Mouse-event-mouse -> ../event21
lrwxrwxrwx 1 root root 9 29 juin 21:13 usb-Logitech_G100s_Optical_Gaming_Mouse-mouse -> ../mouse0
lrwxrwxrwx 1 root root 10 29 juin 21:13 usb-Logitech_Logitech_Illuminated_Keyboard-event-if01 -> ../event20
lrwxrwxrwx 1 root root 10 29 juin 21:13 usb-Logitech_Logitech_Illuminated_Keyboard-event-kbd -> ../event19
lrwxrwxrwx 1 root root 10 30 juin 19:42 usb-Logitech_USB_Receiver-if02-event-mouse -> ../event22
lrwxrwxrwx 1 root root 9 30 juin 19:42 usb-Logitech_USB_Receiver-if02-mouse -> ../mouse1
  • À cela j'ai dû ajouter la directive "GrabDevice" qui, comme l'indique le commentaire, empêche les événements émis par le périphérique concerné d'être interceptés par les autres ServerLayout en empêchant un autre pilote d'initialiser le périphérique et d'envoyer les événements aux fichiers périphériques /dev/mice et /dev/kbd. Je présume que cette ligne est nécessaire pour "contrer" le fonctionnement Plug-and-Play de Xorg/evdev (un même périphérique pouvant être contrôlé par deux pilotes différents - ou deux instances du même pilote - pour deux utilisations complémentaires).
     

ServerLayout "Aux"

Pour le second ServerLayout, on reprend le même principe avec des composants matériels différents.

Les directives suivantes ont été placées dans le fichier /etc/X11/xorg.conf.d/51-serverlayout-aux.conf

Section "ServerLayout"
    Identifier     "Layout-Aux"
    Screen         "Screen-Aux" 0 0
    InputDevice    "K400r-keyboard" "CoreKeyboard"
    InputDevice    "K400r-keyboard-multimedia" "SendCoreEvents"
    InputDevice    "K400r-mouse" "CorePointer"
    Option         "AllowEmptyInput"  "true"
EndSection

Section "InputDevice"
    Identifier     "K400r-mouse"
    Driver         "evdev"
    
    Option         "Protocol" "auto"
    Option         "Device" "/dev/input/by-id/usb-Logitech_USB_Receiver-if02-mouse"
    Option         "Emulate3Buttons" "no"
    Option         "ZAxisMapping" "4 5"
    Option         "GrabDevice" "on"
EndSection

Section "InputDevice"
    Identifier     "K400r-keyboard"
    Driver         "evdev"
    
    Option         "XkbLayout" "fr"
    Option         "XkbModel" "pc104"
    Option         "Device" "/dev/input/by-id/usb-Logitech_USB_Receiver-if02-event-mouse"
    Option         "GrabDevice" "on"
EndSection

Section "InputDevice"
    Identifier     "K400r-keyboard-multimedia"
    Driver         "evdev"
    
    Option         "Device" "/dev/input/by-id/usb-Logitech_USB_Receiver-if02-event-mouse"
    Option         "XkbModel" "evdev"
    Option         "GrabDevice" "on"
EndSection

Section "Monitor"
    Identifier     "Monitor1"
    VendorName     "Compaq"
    ModelName      "Compaq Q2159"
    HorizSync       30.0 - 81.0
    VertRefresh     56.0 - 60.0
    Option         "DPMS"
EndSection

Section "Device"
    Identifier     "Intel-I915"
    Driver         "intel"
    VendorName     "Intel"
    BoardName      "Intel IGP"
    BusID          "PCI:0:2:0"
EndSection

Section "Screen"
    Identifier     "Screen-Aux"
    Device         "Intel-I915"
    Monitor        "Monitor1"
    DefaultDepth    24
EndSection
Une configuration multiseat sous GNU/Linux

La configuration ressemble énormément à la précédente (on retrouve notamment la directive "GrabDevice") sauf sur un point :

  • une section InputDevice supplémentaire permet de déclarer le périphérique système à utiliser pour gérer les touches multimédia du clavier (grâce à l'option "Xkbmodel evdev"). Celle-ci est nécessaire car autrement rien ne détectait cette capacité et le volume n'était pas ajustable depuis le canapé (un comble !). Ici le nom défini par udev n'est pas explicite et il faut y aller à tâton pour trouver la correspondance de chaque fichier présent dans /dev/input et son utilité.

Le fichier /etc/X11/xorg.conf.d/10-evdev.conf fourni avec la distrib est conservé et n'a pas été touché. Au départ je l'avais commenté mais il semblerait que ce soit lui qui permette d'utiliser les touches multimédias du clavier du seat Main (donc très important !).

Configuration du gestionnaire de bureau

 

 


EDIT 14/10/2014

Attention : cette méthode ne fonctionne plus depuis très récemment sous Archlinux car la définition des seats se fait désormais avec logind. Je laisse le paragraphe ci-dessous car il restera probablement d'actualité pendant encore quelques mois pour de nombreuses autres distributions moins "cutting-edge".

Je n'ai pas encore la procédure pour configurer le multiseat avec logind, malheureusement...


 

Xorg étant configuré, ce n'est pas pour cela que tout va fonctionner tout seul (oh non, loin de là...). Il faut à présent configurer le gestionnaire de session pour qu'il instancie les 2 seats au démarrage. J'ai choisi d'utiliser Lightdm qui est particulièrement bien adapté au multiseat (GDM était également compatible avant, puis - comme le reste de Gnome... - il y a eu quelques régressions qui font qu'il est préférable de l'éviter pour cette utilisation pour le moment).

On éditera donc le fichier /etc/lightdm/lightdm.conf :

[LightDM]
minimum-vt=1
run-directory=/run/lightdm

[SeatDefaults]
greeter-session=lightdm-gtk-greeter
greeter-show-manual-login=true
session-wrapper=/etc/lightdm/Xsession
pam-service=lightdm-autologin

[Seat:0]
xserver-command=/usr/bin/X :0 -sharevts
xserver-layout=Layout-Main

[Seat:1]
xserver-command=/usr/bin/X :1 -sharevts -novtswitch
xserver-layout=Layout-Aux

Je n'ai conservé ici que les lignes non-commentées (mais je vous conseille de tout conserver dans votre fichier au cas où !).

Les points clés ici sont évidemment les deux sections [Seat:0] et [Seat:1] respectivement pour la configuration des seats Main et Aux.

En ce qui concerne les options -sharevts et -novtswitch je ne me hasarderai pas à donner des explications que je ne pourrais justifier. Je me suis longuement documenté à leur sujet et la seule configuration fonctionnelle que j'ai trouvée (celle ci-dessus donc) est justement celle qui est marquée à plusieurs reprises comme à éviter dans les notes du wiki d'Archlinux et sur la plupart des sites que j'ai consultés (Gentoo, Ubuntu, etc.).

Normalement à partir de ce moment, si je relance Lightdm je vois apparaître les deux écrans de sessions sur les trois moniteurs. Et si je manipule la souris du seat Main, le curseur reste immobile sur le seat Aux, et vice-versa. Je peux me logger sur l'une des sessions sans toucher à l'autre et... ah non je ne peux pas me logger avec le même utilisateur sur l'autre. Comme je l'ai dit au début, il faut créer un utilisateur dédié. On pourra ensuite se logger avec sans problème. Mon seat Aux étant prévu pour paresser depuis le canapé, je l'ai appelé couchy. Je ne détaillerai pas ici comment ajouter un utilisateur, il existe des interfaces graphiques ou des petites lignes de commande pour ça.

 

Une fois la session démarrée, tout n'est pas encore parfait : sur mon dual-head, les moniteurs sont par exemple inversés. Or, je tiens à conserver mon moniteur de droite comme écran primaire (simplement parce qu'il est en face de moi en réalité), et celui de gauche comme écran secondaire. Pour cela c'est très simple, il suffit de lancer la bonne commande utilisant xrandr à l'ouverture de la session.

Pour savoir qu'elle est cette commande et si "man xrandr" est un peu indigeste, on peut utiliser arandr, une application graphique similaire au gestionnaire d'affichage de Gnome ou de Windows, permettant de placer à la souris les écrans l'un par rapport à l'autre. Il est ensuite possible d'enregistrer l'agencement directement sous forme de script shell dans son dossier personnel (par exemple), puis d'ajouter l'entrée correspondante dans les programmes lancés au démarrage. Sur XFCE, c'est dans "Session et démarrage".

L'application de configuration d'affichage arandr

L'application de configuration d'affichage arandr

Dans mon cas, le contenu du script shell ressemble à ceci :

xrandr --output DVI-D-0 --mode 1920x1080 --pos 0x0 --rotate normal --output HDMI-0 --off --output DVI-I-1 --mode 1920x1080 --pos 1920x0 --rotate normal --output DVI-I-0 --off --output DP-1 --off --output DP-0 --off

(remarque : c'est une unique commande, donc sur une seule ligne)

Ça c'est pour ma session Main, avec le dual-head. Mais il y a aussi quelques ajustements à faire côté canapé avec la session Aux. Le principal est surtout d'adapter le zoom, enfin, plutôt la taille des polices d'affichage et des éléments d'interface. En effet, avec mon petit 22", à deux mètres de distance les textes ne sont plus lisibles. L'avantage d'avoir un utilisateur dédié est de pouvoir gérer ce type de préférences sans risquer de provoquer des effets de bord sur l'utilisateur principal. Chacun gère son affichage et ses préférence de bureau à sa sauce. SUr XFCE, cela se configure notamment dans Paramètres > Apparence.

Une configuration multiseat sous GNU/Linux

Configuration de Pulseaudio

La partie affichage étant réglée, on va tester si la lecture de vidéos passe bien sur le seat Main.

Pas de problème ? Parfait.

La même chose côté Aux à présent.

Ah la vidéo s'affiche bien mais aucun son ne sort ? Eh oui, c'est bien le problème.

 

Les systèmes Linux utilisent depuis déjà pas mal de temps maintenant un (nouvel) intermédiaire logiciel pour la gestion du son qui, comme systemd, a subit les foudres de nombreux libristes au début de son adoption par les différentes distributions (tiens, d'ailleurs c'est le même auteur ^^).

Je passe rapidement car ce n'est pas le propos ici mais ALSA (et OSS avant lui) s'impose comme intermédiaire de la carte son (d'UNE carte son à la fois). Tout programme souhaitant l'utiliser doit donc collaborer avec ALSA qui va assurer le mixage matériel ou logiciel, permettant à plusieurs applications de lire par exemple chacune du son en parallèle.

Cependant, ALSA n'est disponible que sous Linux, ce qui peut être limitant lorsqu'on essaye de créer des applications multimédia multi-plateformes. Il ne bénéficie pas non plus de capacités avancées de mixage, de flux de sortie (réseau par exemple) et de contrôle de volume par application, bref des choses qui s'il y a quelques années seraient apparues comme des fonctionnalités de niches, sont aujourd'hui beaucoup plus abordables (et abordées) grâce à la multiplication des matériels existants (que ce soit les appareils mobiles ou les équipements home-cinema).

Pour tout cela il y a donc Pulseaudio, qui vient grossièrement s'intercaler entre ALSA et les applications, afin d'y ajouter les fonctionnalités avancées dont ALSA manque cruellement. C'est bien une chance pour moi car c'est exactement ce dont j'ai besoin pour ma configuration multi-seat (en tout cas cela permet une gestion assez fine de celle-ci).

Pour plus d'infos (en anglais) et sûrement moins de bêtises que je n'en dis : http://tuxradar.com/content/how-it-works-linux-audio-explained

 

Mais pour le moment, Pulseaudio dans sa configuration par défaut m'empêche purement d'atteindre mon objectif, à savoir pouvoir utiliser la même carte son depuis mes deux seats. Pulseaudio est en effet lancé lors de l'ouverture de la session (ici XFCE) et accapare la carte son de manière à être sûr qu'ALSA (et donc les applications) passe par lui. Une carte son virtuelle est ensuite mise à disposition d'ALSA qui peut faire son travail. Le problème est qu'ici Pulseaudio est lancé avec l'utilisateur de la session, sur lequel l'autre utilisateur n'a pas la main. La première session ouverte sur la machine verrouille donc la carte son et l'autre ne peut tout simplement pas l'utiliser.

Avant d'aller plus loin je précise qu'il est possible d'utiliser la fonctionnalité de "carte son distante" offerte par Pulseaudio pour mettre le serveur de son à disposition de l'autre utilisateur par le réseau. Cela fonctionne, mais pour que la configuration soit stable il faut forcément que l'utilisateur configuré pour gérer la carte son soit toujours préalablement loggé. Enfin bref, c'est un merdier pas possible, je vous demande pas de retenir ce genre de détail (mais je tiens à signaler que je m'y suis essayé et cassé les dents, à bon entendeur).

Diagramme de l'architecture de Pulseaudio, By Pulseaudio-diagram.svg / Pulseaudio-diagram.png: Manuel Amador Briz derivative work: Tsaitgaist (talk) (SVG Version) derivative work: Emeric Grange (French version) (Pulseaudio-diagram.svg) [GFDL (http://www.gnu.org/copyleft/fdl.html) or CC-BY-SA-3.0 (http://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons

Diagramme de l'architecture de Pulseaudio, By Pulseaudio-diagram.svg / Pulseaudio-diagram.png: Manuel Amador Briz derivative work: Tsaitgaist (talk) (SVG Version) derivative work: Emeric Grange (French version) (Pulseaudio-diagram.svg) [GFDL (http://www.gnu.org/copyleft/fdl.html) or CC-BY-SA-3.0 (http://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons

Non ce qu'il faudrait, c'est un daemon système et non de session.

Un serveur Pulseaudio qui serait lancé au boot avec des droits adaptés et auxquel les applications de différentes sessions se connecteraient pour utiliser la carte son chacune de leur côté avec les mêmes droits. C'est le principe de Pulseaudio en mode système, une configuration qui présente des limitations et des risques pour la sécurité mais qui est ici tout indiquée, et pour laquelle il n'y a encore aucune alternative (à ma connaissance).

Sur Archlinux, le plus simple est d'installer le package AUR permettant d'activer le mode système pour PA. Celui-ci  installe notamment un fichier de configuration pour systemd et crée  l'utilisateur dédié que Pulseaudio utilisera (on va quand même pas le  faire tourner en root !). Lors de mes bidouillages je ne l'ai découvert qu'après et ai donc perdu beaucoup de temps, bien que cela m'ait servi à comprendre un peu le fonctionnement de l'ensemble...

Pour l'installer facilement :

$ yaourt pulseaudio-systemd

On a ensuite un utilisateur pour le daemon système de PA :

$ tail -1 /etc/passwd
pulse:x:619:618:PulseAudio:/var/run/pulse:/bin/false

Ainsi qu'un groupe correspondant pour cet utilisateur, et un groupe supplémentaire dans lequel nous placerons les utilisateurs autorisés à accéder au daemon, c'est-à-dire ceux souhaitant émettre du son : pulse-access.

$ tail -2 /etc/group
pulse:x:618:
pulse-access:x:617:
# usermod -a -G pulse-access nanawel
# usermod -a -G pulse-access couchy

Si on veut que le dameon soit lancé au boot, il vaut mieux le dire :

# systemctl enable pulseaudio.service

 

À ce stade il vaut mieux rebooter pour repartir sur une base saine, ou au moins déconnecter les sessions courantes ayant lancé PA et lancer le nouveau daemon manuellement :

# systemctl start pulseaudio.service

Si tout va bien - et grâce à ce package AUR qui fait une bonne partie du travail pour nous - il suffit d'ouvrir à nouveau une session avec les deux utilisateurs précédents pour pouvoir lire simultanément deux fichiers audio sur chacune des sessions.

L'utilisation de Pavucontrol depuis l'une ou l'autre permet ensuite de régler finement le volume de chacune des applications (et là, merci Pulseaudio).

Si après un reboot il n'y a plus du tout de son, alors cela signifie peut-être que vous en avez une grosse comme moi (de configuration matérielle - merci le Core i7 et le SSD) et que le boot orchestré par systemd est trop rapide pour laisser le temps à la carte son de s'initialiser. Lisez alors le paragraphe "Configuration de udev/systemd" plus bas.

Pour les raccourcis clavier à présent, c'est un peu plus la galère, mais pas partout. Sous Gnome normalement aucun problème, les touches sont déjà mappées correctement et fonctionnent bien avec PA (je n'ai pas testé, donc à prendre avec des pincettes). Sous XFCE je n'ai pas réussi à les faire fonctionner en utilisant le package xfce4-volumed-pulse pourtant prévu pour ça.

Le wiki d'Archlinux mentionne les commandes à assigner aux touches pour régles le volume, soit directement celui d'ALSA (bof) soit plutôt celui de Pulseaudio. Mais dans les deux cas, chez moi ça fait que quand je baisse un peu trop le volume, celui-ci se coupe et il me faut passer par Pavucontrol pour le rétablir (aucune touche ne peut plus le débloquer).

Configuration de udev/systemd

Carte(s) son

Après avoir mis en place PA en mode système, il m'a fallu résoudre un autre problème qui m'a paru loin d'être évident au début. J'ai pu constater qu'après chaque reboot je n'avais plus de son. Mais il me suffisait cependant de relancer le daemon de Pulseaudio pour le retrouver.

C'était dû au fait que le temps entre GRUB et l'écran de login était extrêmement court (environ 1 à 2 seconde, ça fait rêver les Windowsiens ^^), grâce notamment à systemd. Mais "grâce" à systemd, ce qui auparavant était séquentiel ne l'est plus. Et l'initialisation des périphériques peut donc également être terminée après... disons par exemple le lancement du gestionnaire de session.

Dans mon cas, le problème était que la carte son était initialisée après le daemon Pulseaudio. Je pensais que c'était une limitation de PA de ne pas pouvoir détecter de périphériques après son lancement, mais en fait je pense qu'il s'agit plus d'une conséquence de la désactivation du chargement de modules à chaud, précaution de sécurité inhérente au mode "système" et présente dans le package pulseaudio-systemd (voir fichier pulseaudio.service).

 

Toujours est-il qu'il est nécessaire de contourner cette limitation. La solution qui m'a été tout simplement proposée par un Archer sur le forum est de définir une dépendance entre la carte son et le daemon PA, et cela au moyen de udev. Le principe est de forcer le daemon a attendre que la carte son soit initialisée avant de se lancer.

Pour cela il faut s'intéresser au fonctionnement des règles udev, un formidable outil que je n'avais jusque-là jamais eu à toucher, bien que j'en ai souvent entendu parler. Ce qui est notamment bien - surtout pour moi ici - c'est qu'il est possible de tagger des éléments du système de manière à pouvoir les identifier dans les unités de systemd.

Je ne vais pas m'étendre sur la syntaxe et les possibilités offertes par le système de règles proposé par udev, il faudrait au moins un article aussi long. Je vais simplement présenter ce que j'ai effectué, et les effets que cela a.

Tout d'abord j'ai créé un fichier de règles /etc/udev/rules.d/99-soundcard-tagging.rules dans lequel j'ai mis la simple ligne :

ACTION=="add", KERNEL=="card*", SUBSYSTEM=="sound", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/sound/devices/$attr{id}"

(toujours une seule ligne, ma colonne n'est pas assez large)

Celle-ci permet, à l'initialisation des périphériques de type carte (card) son (sound) de créer un périphérique virtuel (un alias) au chemin (virtuel)

/sys/subsystem/sound/devices/$attr{id}

$attr{id} est évidemment une variable qui sera évaluée à l'exécution. Pour connaître sa valeur pour ma carte par exemple, il me suffit d'exécuter la commande suivante :

$ cat /sys/class/sound/card0/id
DGX
$ cat /sys/class/sound/card1/id
NVidia

On peut voir ici qu'il y a en fait deux cartes son : une "vraie" (la DGX) et une "fausse" (la sortie HDMI de la carte graphique).

Le chemin virtuel généré par la règle udev sera donc pour la "vraie" carte son :

/sys/subsystem/sound/devices/DGX

Ce qui, selon les règles de de correspondance de nommage de udev/systemd, correspond à l'unité suivante :

sys-subsystem-sound-devices-DGX.device

 

J'ai à présent un moyen sûr d'identifier de manière précise ma carte son comme unité systemd. Il suffit donc à présent d'ajouter la dépendance avec le daemon Pulseaudio.

# mkdir /etc/systemd/system/pulseaudio.service.d
# nano /etc/systemd/system/pulseaudio.service.d/10-wait-for-soundcards.conf
[Unit]
Wants=sys-subsystem-sound-devices-DGX.device
After=sys-subsystem-sound-devices-DGX.device
# systemctl daemon-reload

Et un reboot plus tard : tadaa ! Le boot prend bien deux à trois secondes de plus, mais au moins Pulseaudio détecte bien la carte son !

Lennart Poettering, By ramkrsna (http://www.flickr.com/photos/ramkrsna/2106127348/) [CC-BY-SA-2.0 (http://creativecommons.org/licenses/by-sa/2.0)], via Wikimedia Commons

Lennart Poettering, By ramkrsna (http://www.flickr.com/photos/ramkrsna/2106127348/) [CC-BY-SA-2.0 (http://creativecommons.org/licenses/by-sa/2.0)], via Wikimedia Commons

Périphériques de saisie

Un autre inconvénient dû à la configuration choisie pour Xorg est qu'il n'est plus possible de se reposer sur l'auto-détection des claviers/souris par le serveur d'affichage. En ayant manuellement assigné (dans les fichiers de configuration pour chaque seat vus plus haut) les claviers et souris à chacun des ServerLayouts, je me suis retrouvé dans la situation où là encore Lightdm/Xorg se lançait avant que les périphériques ne soient initialisés.

Ce qui était frustrant était le côté aléatoire du fonctionnement : parfois après le reboot tout fonctionnait (rarement), souvent il fallait relancer Lightdm depuis une connexion SSH (toujours pas de terminal virtuel je rappelle). Après cela, tout fonctionnait bien jusqu'au prochain reboot.

 

Une fois la source du problème comprise, j'ai simplement réutilisé la même méthode que pour la carte son : j'ai ajouté une règle udev pour tagger les périphériques (une fois ceux-ci identifiés, ce qui n'a pas été sans mal), puis j'ai ajouté une dépendance entre les unités systemd correspondantes et le daemon Lightdm.

La règle udev dans le fichier /etc/udev/rules.d/99-input-tagging.rules :

ACTION=="add", KERNEL=="event*", SUBSYSTEM=="input", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/input/devices/$env{ID_SERIAL}"

Ce qui m'a donné les nouvelles unités systemd suivantes, dont les noms sont parfaitement évocateurs :

sys-subsystem-input-devices-Logitech_G100s_Optical_Gaming_Mouse.device
sys-subsystem-input-devices-Logitech_Logitech_Illuminated_Keyboard.device
sys-subsystem-input-devices-Logitech_USB_Receiver.device

Je peux ensuite utiliser ces unités dans le fichier /etc/systemd/system/display-manager.service.d/10-wait-for-input-devices.conf

[Unit]
Wants=sys-subsystem-input-devices-Logitech_Logitech_Illuminated_Keyboard.device sys-subsystem-input-devices-Logitech_G100s_Optical_Gaming_Mouse.device sys-subsystem-input-devices-Logitech_USB_Receiver.device
After=sys-subsystem-input-devices-Logitech_Logitech_Illuminated_Keyboard.device sys-subsystem-input-devices-Logitech_G100s_Optical_Gaming_Mouse.device sys-subsystem-input-devices-Logitech_USB_Receiver.device

J'ai également ajouté une dépendance entre Pulseaudio et Lightdm dans le fichier /etc/systemd/system/display-manager.service.d/10-wait-for-pulseaudio.conf. De cette manière je suis sûr que quand un utilisateur se logge tout est fonctionnel.

[Unit]
Wants=pulseaudio.service
After=pulseaudio.service

Enfin, une dépendance également entre Dbus et Pulseaudio (dans une configuration classique, Dbus est lancé bien avant Pulseaudio, mais ici nous sommes au même "niveau" : celui des daemons systèmes) :

$ ls -l /etc/systemd/system/pulseaudio.service.wants
lrwxrwxrwx 1 root root 36 25 avril 14:13 dbus.service -> /usr/lib/systemd/system/dbus.service

Là normalement, on est paré !

C'est quand on essaye de mettre en place ce genre de configuration qui sort un peu des sentiers battus, qu'on comprend le travail qui a été fait depuis dix ans en termes de "plug-and-playability" sur les environnements GNU/Linux, car avant on pouvait se retrouver à tâtonner autant pour mettre en place un environnement single-seat/single-head tout ce qu'il y a de plus basique...

Résumé

J'ai à présent un système comprenant une UC unique, disposant de deux cartes graphiques : l'une externe (NVidia GeForce 760 sur port PCI-Express), l'autre intégrée au CPU (IGP Intel).

Sur la première j'ai deux moniteurs HD branchés en DVI, sur lesquels j'affiche un bureau étendu pour toutes les tâches usuelles (bureautique, dev, jeu, video, moulage divers) utilisant XFCE.

Sur la seconde, j'ai un unique moniteur HD branché en VGA et accessible depuis le canapé, avec un utilisateur (Linux) dédié, donc un bureau spécifique (mais toujours XFCE). Chaque seat possède son couple clavier/souris propre, ce qui permet d'utiliser chacun d'eux indépendamment (le crash d'un environnement n'entraînant pas l'autre, oui ça arrive...).

 

D'autre part, la carte son de l'UC est partagée entre les deux sessions ce qui me permet de contrôler le son depuis l'un ou l'autre seat de la même manière. C'est un point de la configuration qui peut être facilement adapté dans le cas où chaque seat possède ses propres enceintes/écouteurs.

D'ailleurs, en réalité j'ai volontairement simplifié mes explications car j'ai moi-même deux cartes son : celle intégrée à la carte mère et la carte Asus Xonar DGX (mentionnée dans mon l'article où je présentais ma nouvelle configuration matérielle), mais je n'en utilise qu'une seule 99% du temps. Il est néanmoins très facile grâce à Pulseaudio de rediriger le flux audio d'une application vers l'une ou l'autre carte.

Ma configuration (fonctionnelle !) actuelle

Ma configuration (fonctionnelle !) actuelle

Les bugs et limitations

Oui malheureusement, même après plusieurs jours de batailles et de frustration le résultat est encore loin de la perfection, mais il s'agit d'une bonne base tout à fait utilisable

 Afin d'être tout à fait honnête voici les bugs et les limitations de la configuration présentée. Certains points ne sont néanmoins pas directement liés au multi-seat mais simplement à l'état de l'art sous GNU/Linux...

  • Obligation d'utiliser le pilote Nouveau, ce qui interdit tout jeu 3D gourmand (mais laisse la possibilité d'utiliser Steam avec des jeux plus légers). Aucun problème par contre avec les vidéos HD (y compris 4K).
  • Directement lié au point précédent, le pilote Nouveau plante régulièrement, même si je dois avouer que c'est nettement plus rare depuis quelques semaines (en même temps il est en perpétuelle évolution). Un crash se traduit par un retour à l'écran de login de Lightdm, fermant brutalement les applications de la session en cours, mais sans affecter le second Seat (utilisant lui le GPU Intel). Au départ j'observais en moyenne un à deux crashs par jour, mais il s'agit à présent plutôt d'un à deux crashs par semaine maximum.
  • Malgré les règles udev mentionnées plus haut, il arrive parfois qu'un ou plusieurs périphériques de saisie ne soient pas détectés après le boot, et donc ne soient pas utilisables, mais c'est très rare (une fois tous les 10-20 reboots peut-être, et encore cela ne m'est plus arrivé depuis un moment).
  • Le combo clavier-touchpad Logitech du canapé a la fâcheuse tendance à devenir inactif, parfois, au bout de plusieurs heures ou jours, ce qui oblige au reboot pour pouvoir l'utiliser à nouveau. Là également c'est très rare et ne m'est pas arrivé depuis plusieurs semaines, mais je préfère le signaler (après, savoir d'où ça vient : noyau, pilotes, connexion sans-fil, USB, etc... aucune idée).
  • La lecture de vidéos sur le moniteur branché sur le GPU Intel affichait jusqu'à très récemment une ligne de tearing très désagréable à 2/3 de la hauteur de l'écran, mais il semblerait que la dernière mise à jour du noyau et des pilotes Intel ait corrigé ce problème. Un bon point s'il persiste !
  • Sous XFCE, le contrôle du volume avec les touches multimédia "coince" le son en sourdine si on abaisse trop le volume. Il n'est ensuite plus possible de le rétablir sans passer par une interface telle que Pavucontrol. C'est un bug qui touche Pulseaudio de manière générale et qui est présent dans de très nombreuses discussions sur le Net...
  • Sur le seat Main, les applications Wine ne sont utilisables que sur l'écran de gauche (alors que les applications de configuration de Wine fonctionnent sur les deux) mais présentent de nombreux artefacts : de gros rectangles noirs apparaissent notamment aux endroits masqués par une fenêtre recouvrante. Le placement de la fenêtre sur l'écran de droite rend les boutons et autres menus totalement insensibles aux clics ou aux touches du clavier. Utilisant un dual-screen sur le PC du boulot avec Archlinux, Mate et les pilotes NVidia, je pense qu'il s'agit d'un problème lié à Nouveau car je n'ai jamais rencontré ce comportement sur cette configuration, mais sans certitude aucune.
Un des glitches des applications Wine...

Un des glitches des applications Wine...

Ceci fait, j'espère que cet article aura pu intéresser les geeks ayant des lubies bizarres et souhaitant s'amuser avec leur matériel flambant neuf (mais hormis le challenge technique, c'est super pratique, faut le relever).

Moi en tout cas  - et rétrospectivement, maintenant que tout fonctionne au poil ! - je dois dire que j'apprécie le résultat. Et lancer un petit XBMC sur le moniteur du canapé reste un plaisir bien sympathique (même si j'utilise plus volontier VLC et SMPlayer depuis Thunar ^^).

 

 

Ah, et pour info, les schémas de cet article (ainsi que du précédent sur les honeypots) ont été créés avec draw.io.

Commenter cet article

Kris 26/09/2015 17:22

Bonjour
J'ai un pc en multiseat depuis des années et j'ai enfin decidé de m'attaquer au probleme du son pour le 2ieme utilisateur .Mon probleme est que je suis sous Mageia5 et je n'ai pas de paquet pulseaudio-systemd :-( . Donc je voudrais savoir comment je pourrais faire pour creer les groupes pulse et pulse-access ??? J'ai chercher un peu partout et j'ai pas trouver de solution .
Merci :-)

Nanawel 26/09/2015 17:44

Salut Kris,
Ces groupes peuvent être créés à la main via un shell en root. Cela devrait se résumer aux commandes suivantes :
# groupadd -r pulse
# groupadd pulse-access

La première crée un groupe système (qui ne sera pas utilisé par des humains, pour résumer), la seconde un groupe "normal", dans lequel tu pourras ajouter tes utilisateurs avec la troisième commande ci-dessous :
# usermod -aG pulse-access toto

"toto" est bien sûr à remplacer par le nom réel de l'utilisateur.

Le reste devrait correspondre peu ou prou à ce que j'ai pu marquer dans mon post.
Bon courage et amuse-toi bien !

lliseil 25/08/2014 17:48

Bjr
Sacrée config(uration;-)
Je ne fais que passer. As-tu noté pulseaudio-ctl (by Grayski) pour gérer le son via les raccourcis claviers ?
« Optional volume control via mapped keyboard keys: pulseaudio-ctl » sur https://wiki.archlinux.org/index.php/PulseAudio

Nanawel 25/08/2014 19:20

Oui je l'ai essayé, mais il ne semble pas très compatible avec le mode système que j'utilise (erreur "Aucun démon PulseAudio en cours d'exécution, ou ne s'exécutant pas dans une session de type démon."). D'autre part, il utilise des pas de 5% pour le volume ce que je trouve trop important. J'utilise donc des pas de 2% via pactl.

Le mode système de PA n'est clairement pas suffisamment supporté. Ou alors il faudrait un mode non-système qui permette de gérer correctement les configurations multiseats...

Sim 09/08/2014 02:39

Merci pour le partage d'expérience ! D'autant plus qu'on trouve peu d'informations sur ce genre de conf.
Pour ma part je m'arrache les cheveux pour faire fonctionner un triple screens bureau étendu dont 2 sur une nvidia et le troisième sur une Intel intégrée. J'ai un peu lâché l'affaire à la vue du temps passé..

Nanawel 09/08/2014 10:21

J'ai eu moi-même énormément de mal à trouver des informations précises et récentes sur ce type de configuration. J'ai dû finalement me baser sur une bonne dizaine de pages différentes n'ayant que très peu en commun, et recoller le tout en lisant de la doc et en tâtonnant. J'ai rapidement compris que synthétiser tout ça dans un post pourrait en aider plus d'un :)