web-dev-qa-db-fra.com

Basculer automatiquement entre les haut-parleurs internes et HDMI

Vous savez comment, lorsque vous branchez un casque dans la prise auxiliaire de votre ordinateur portable, les haut-parleurs internes sont automatiquement coupés et les sons sortent de votre casque? Je veux exactement ça pour HDMI.

Je connecte un moniteur avec des haut-parleurs intégrés à mon ordinateur portable pour regarder des vidéos, parfois. C'est très bizarre quand la vidéo est sur l'écran (qui est placé à 3 m de mon bureau) mais le son sort des haut-parleurs internes de mon ordinateur portable (l'ordinateur portable est assis sur le bureau).

Bien sûr, je ne peux que passer aux paramètres sonores et basculer le canal de sortie en HDMI. Mais ensuite, plus tard, lorsque j'ai débranché le câble HDMI il y a quelques heures et que je pourrais même être dans un emplacement totalement différent, le son ne sera pas lu car le serveur de son essaie toujours de le lire via HDMI mais rien ne lui est connecté. .

Il est plus important de revenir automatiquement aux haut-parleurs internes quand aucun appareil n'est connecté via HDMI, mais passer à la sortie du son via HDMI quand un appareil est connecté serait toujours très agréable.

Cela a apparemment fonctionné avec 11.1 mais cela ne fonctionne pas avec 16.04.

17
UTF-8

Contexte

J'ai eu un problème similaire lors de la suspension/reprise lorsque le son passait d'une télévision HDMI à une enceinte d'ordinateur portable. Lors de la reprise, le son reste sur les haut-parleurs de l'ordinateur portable et je dois réinitialiser manuellement le périphérique de sortie sur TV dans System Settings -> Sound.

Ce fut l'une de mes premières expériences ennuyeuses avec la mise à niveau de buntu 14.04 à 16.04 et la racine était une mise à niveau vers PulseAudio 8 fournie avec 16.04 LTS

Après de nombreuses recherches, j'ai créé un script appelé TV-sound. Bien que je ne branche pas et ne débranche pas le téléviseur comme vous, j'ai fait quelques recherches sur Google et créé une variante du script qui convient à votre situation. Je l'ai testé et ça marche.

Étape 1: Créer un script pour basculer l'audio entre les périphériques connectés

Nous allons créer un script appelé hotplugtv qu'udev appelle. Ce même script peut cependant être appelé dans de nombreux endroits. Par exemple, lors des tests, je l'ai utilisé dans lock-screen-timer, où le son est revenu sur l'ordinateur portable pendant le verrouillage de l'écran.

cd /usr/local/bin
Sudo touch hotplugtv
Sudo chmod +x hotplugtv
gksu gedit hotplugtv

Lorsque l'éditeur s'ouvre avec un écran vide, copiez et collez les éléments suivants dans celui-ci:

#! /bin/bash

# NAME: hotplugtv
# PATH: /usr/local/bin
# DESC: Update pulseaudio output device when HDMI TV plugged / unplugged
# CALL: called from /etc/udev/rules.d/99-monitor-hotplug.rules
# DATE: Created Nov 26, 2016.
# NOTE: logs output using log-file
# UPDT: Dec 14, 2016 - Sometimes /sys/class/drm/card0 & sometimes /sys/class/drm/card1
#       so use /sys/class/dmcard* instead.

if [[ $(cat /sys/class/drm/card*-HDMI-A-1/status | grep -Ec "^connected") -eq 1 ]]; then
#        log-file "HDMI TV connected" ~/bin/log-hotplugtv;
        /bin/sleep 2;
        export Pulse_RUNTIME_PATH="/run/user/1000/Pulse/";
        Sudo -u rick -E pacmd set-card-profile 0 output:hdmi-stereo;
else
#        log-file "HDMI TV disconnected" ~/bin/log-hotplugtv;
        export Pulse_RUNTIME_PATH="/run/user/1000/Pulse/";
        Sudo -u rick -E pacmd set-card-profile 0 output:analog-stereo;
fi

exit 0

Vous devrez remplacer les deux occurrences de rick par votre propre ID utilisateur, à savoir UTF-8, etc.

Je sais que cela peut être plus professionnel avec un nom d'utilisateur automatiquement défini sur une variable bash, mais je ne suis pas encore qualifié :( Quoi qu'il en soit, sauvegardez le fichier et quittez gedit.

Étape 2: Créer des règles udev

udev surveille les événements hotplug lorsque vous branchez et débranchez votre moniteur HDMI. Tapez ce qui suit pour créer une nouvelle règle.

cd /etc/udev/rules.d
Sudo cp 70-persistent-net.rules 99-hotplugtv.rules
gksu gedit 99-hotplugtv.rules

NOTE: Si le fichier 70-persistent-net.rules n'existe pas dans votre répertoire, copiez-y un autre fichier. Nous n'avons pas besoin du contenu du fichier, mais simplement des autorisations de fichier pour nous assurer que les nôtres sont identiques.

L'éditeur affichera un tas de texte non pertinent, le mettra en surbrillance et le supprimera. Puis mettez en surbrillance le code ci-dessous et collez-le dans l'éditeur:

# NAME: 99-hotplugtv.rules
# PATH: /etc/udev/rules.d
# DESC: Update pulseaudio output device when HDMI TV plugged / unplugged
# CALL: automatically called on system events
# DATE: Created Nov 26, 2016.
# NOTE: in future may requre systemd service hooks

ACTION=="change", SUBSYSTEM=="drm", ENV{HOTPLUG}=="1", RUN+="/usr/local/bin/hotplugtv"

Enregistrez le fichier et quittez.

Pour activer la règle (sans redémarrer), nous devons recharger udev:

Sudo udevadm control --reload-rules

Vous pouvez maintenant brancher et débrancher votre moniteur/téléviseur HDMI et le son commute correctement.

Caveat

Sur mon système, le son revient automatiquement aux haut-parleurs de l'ordinateur portable lorsque HDMI est débranché. Sur votre système, ce n'est pas le cas. Des améliorations supplémentaires du code peuvent être nécessaires si le son n’est pas diffusé sur les haut-parleurs de votre ordinateur portable lorsque HDMI est débranché. S'il vous plaît répondez via commentaire ci-dessous comment les choses fonctionnent/ne fonctionnent pas.

Test rapide dans la CLI

Vous pouvez rapidement tester le code sur le terminal en utilisant:

    export Pulse_RUNTIME_PATH="/run/user/1000/Pulse/";
  • Basculer vers HDMI/TV:

        Sudo -u rick -E pacmd set-card-profile 0 output:hdmi-stereo;
    
  • Revenez aux haut-parleurs intégrés:

        Sudo -u rick -E pacmd set-card-profile 0 output:analog-stereo;
    
  • N'oubliez pas de remplacer rick par votre nom d'utilisateur.

  • La ligne initiale export n'est probablement pas nécessaire, mais je l'ai incluse uniquement pour des raisons de sécurité.
  • Si vous avez plusieurs cartes son, ou quelque chose d'autre que hdmi-stereo, des ajustements sont évidemment nécessaires pour connaître les paramètres corrects avant d'écrire votre script.

Déchiffrer le nom de votre appareil dans PulseAudio

Le code ci-dessous utilise la même commande deux fois. Une fois lorsque le son est réglé sur un téléviseur HDMI externe. Une deuxième fois lorsque le son est réglé sur les haut-parleurs intégrés de l'ordinateur portable. Chaque fois que vous voyez le nom utilisé par PulseAudio:

$ pacmd list-sinks | grep -e 'name:' -e 'index'
  * index: 28
    name: <alsa_output.pci-0000_00_1b.0.hdmi-stereo>
───────────────────────────────────────────────────────────────────────────────
$ pacmd list-sinks | grep -e 'name:' -e 'index'
  * index: 30
    name: <alsa_output.pci-0000_00_1b.0.analog-stereo>

Lorsque vous avez plusieurs cartes son

Utilisez la commande aplay -l pour voir si vous avez des cartes dont le numéro est supérieur à 0. Dans ce cas, vous devrez utiliser le numéro de carte approprié dans vos scripts. Par exemple:

$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: PCH [HDA Intel PCH], device 0: 92HD91BXX Analog [92HD91BXX Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 3: HDMI 0 [HDMI 0]
  Subdevices: 0/1
  Subdevice #0: subdevice #0

Dans l'exemple ci-dessus, tous les numéros de carte sont 0 avec des sources de sortie différentes. Si vous avez des haut-parleurs USB, ils peuvent avoir un numéro de carte différent de 0.

Edit 2 décembre 2016

Pour une raison inconnue, le script a été rompu aujourd'hui. Le code ci-dessus se lisait comme suit: "$ (cat/sys/classe/drm/card0-HDMI-A-1/status"), mais je devais changer card0 en card1 et le code ci-dessus a été modifié en tant que tel. Je ne peux pas expliquer. Ce qui a changé sur mon système autre que les mises à jour régulières d'Ubuntu depuis le 26 novembre 2016.

Edit 14 décembre 2016

Le code ci-dessus devait être à nouveau remplacé par: "$ (cat/sys/class/drm/card0-HDMI-A-1/status". Au lieu de modifier le code entre card0 et card1 en fonction du démarrage, modifiez le programme en référence à card* en capturer les deux scénarios.

7
WinEunuuchs2Unix