web-dev-qa-db-fra.com

Régler la sortie audio HDMI automatiquement lors de la connexion / déconnexion

J'ai une configuration à double écran sur mon ordinateur portable (avec 12.04 LTS) à l'aide d'un écran connecté par HDMI. Tout fonctionne bien, mais chaque fois que je connecte/déconnecte le câble, je dois accéder aux préférences Son et changer le périphérique de sortie du son manuellement.

Est-il possible de changer le périphérique de sortie audio lors de la connexion/déconnexion du câble, de sorte que lorsque je connecte mon écran, la sortie audio est réglée sur HDMI et lorsque je le déconnecte, le son est renvoyé aux haut-parleurs de l'ordinateur portable?

18
Salem

J'ai finalement réussi à faire fonctionner ce travail en utilisant udev. Donc, si quelqu'un veut le même comportement, voici les étapes:

Nous devons d’abord créer un fichier /etc/udev/rules.d/hdmi_sound.rules avec le contenu suivant:

    SUBSYSTEM=="drm", ACTION=="change", RUN+="/usr/local/bin/hdmi_sound_toggle"

ceci va permettre à udev d'exécuter le script hdmi_sound_toggle chaque fois qu'il y a un changement de connexion HDMI. Ce script doit avoir une autorisation d'exécution et le contenu est le suivant:

#!/usr/bin/env python

import subprocess
from syslog import syslog

def output(cmd):
    return subprocess.check_output(cmd, Shell=True)

# the following variables may need some modification.
user = "my_username"
card = "/sys/class/drm/card0"
dev_speaker = "output:analog-stereo+input:analog-stereo"
dev_hdmi = "output:hdmi-stereo+input:analog-stereo"
#

interfaces = output("ls {0}".format(card), ).split("\n")

vga = filter(lambda x: "VGA" in x, interfaces)[0]
hdmi = filter(lambda x: "HDMI" in x, interfaces)[0]

syslog("HDMI connection was changed!")

hdmi_connected = output("cat {0}/{1}/status".format(card,hdmi)).startswith("connected")
title = "HDMI was {0}".format("connected" if hdmi_connected else "disconnected")
message = "Audio output has changed to {opt}.".format(opt = "HDMI" if hdmi_connected else "built-in speakers")

cmd = "Sudo -u " + user + " /usr/bin/pactl set-card-profile 0 " + (dev_hdmi if hdmi_connected else dev_speaker)

syslog("HDMI was connected." if hdmi_connected else "HDMI was disconnected.")
try:
    a = output(cmd)
    output("Sudo -u {0} notify-send \"{1}\" \"{2}\"".format(user, title, message))
    syslog("Audio output changed.")
except Exception as ex:
    syslog("Error changing output device: " + str(ex))

Cela peut probablement être fait facilement en bash, mais comme ma langue principale est python je l'ai utilisé. Tout fonctionne sauf la notification: cela ne s'affiche pas, je ne sais vraiment pas pourquoi. Si quelqu'un sait comment le réparer, dites quelque chose.

Remarque: les noms de règle de script/udev peuvent être modifiés, mais vous devez utiliser le chemin complet.

7
Salem

Pour le bénéfice des personnes qui tombent sur cette question - la solution de Salem a presque fonctionné pour moi en 13.04, j'ai fini par rassembler des fragments de tout le Web, je pense que la rupture de la transaction a été pour moi l'absence de la variable d'environnement Pulse_SERVER

Voici ma solution complète, qui consiste essentiellement à répéter la solution de Salem avec les quelques pièces manquantes. Je l'ai également refait en tant que script Shell (malgré mon amour pour Python) parce que j'avais peur au début que mon script Python se heurte à des problèmes de chemin d'importation:


(identique à la réponse de Salem) Créez un fichier /etc/udev/rules.d/hdmi_sound.rules en tant que root avec le contenu:

SUBSYSTEM=="drm", ACTION=="change", RUN+="/usr/local/bin/hdmi_sound_toggle"

Créez un fichier /usr/local/bin/hdmi_sound_toggle en tant que root avec le contenu:

#!/bin/sh
USER_NAME=`who | grep "(:0)" | cut -f 1 -d ' '`
USER_ID=`id -u $USER_NAME`
HDMI_STATUS=`cat /sys/class/drm/card0/*HDMI*/status`

export Pulse_SERVER="unix:/run/user/"$USER_ID"/Pulse/native"

if [ $HDMI_STATUS = "connected" ]
then
    Sudo -u $USER_NAME pactl --server $Pulse_SERVER set-card-profile 0 output:hdmi-stereo+input:analog-stereo
else
    Sudo -u $USER_NAME pactl --server $Pulse_SERVER set-card-profile 0 output:analog-stereo+input:analog-stereo
fi

Puis rendez-le exécutable avec chmod 0755 /usr/local/bin/hdmi_sound_toggle

J'ai essayé de rendre ce script aussi générique que possible, mais vous aurez peut-être encore besoin de changer certaines lignes, telles que le chemin du fichier HDMI_STATUS ou les profils utilisés. Vous pouvez voir une liste de profils en exécutant pactl list cards et en regardant sous Profils.

Notez que le script a échoué pour moi lorsque j'ai supprimé le mot clé "export" lors de la définition de Pulse_SERVER, je pense que pactl recherche la variable env.

N'oubliez pas de recharger vos règles udev: Sudo udevadm control --reload-rules

Mise à jour ce script est mis à jour pour 14.04. Avant cela, vous utiliseriez USER_NAME au lieu de USER_ID partout.

11
Daniel

Basé sur la réponse de Salem et sur celle de daniel

J'ai pris la réponse de Salem et celle de daniel et apporté les modifications nécessaires. Leur solution n'a pas fonctionné pour moi immédiatement:

(similaire à la réponse de Salem).

Créez un fichier /etc/udev/rules.d/hdmi_sound.rules en tant que root avec le contenu:

SUBSYSTEM=="drm", RUN+="/usr/local/bin/hdmi_sound_toggle"

Remarque ACTION=="change", est manquant!

Créez un fichier /usr/local/bin/hdmi_sound_toggle en tant que root avec le contenu:

#!/bin/sh
USER_NAME=`who | grep "(:0)" | cut -f 1 -d ' '| sort -u`
USER_ID=`id -u $USER_NAME`
HDMI_STATUS=`cat /sys/class/drm/card0/*HDMI*/status`

export Pulse_SERVER="unix:/run/user/"$USER_ID"/Pulse/native"

if [ $HDMI_STATUS = "connected" ]
then
    Sudo -u $USER_NAME pactl --server $Pulse_SERVER set-card-profile 0 output:hdmi-stereo+input:analog-stereo
else
    Sudo -u $USER_NAME pactl --server $Pulse_SERVER set-card-profile 0 output:analog-stereo+input:analog-stereo
fi

Remarque USER_NAME = who | grep "(:0)" | cut -f 1 -d ' '| sort -u J'ai ajouté | sort -u car sinon, il est retourné avec elemer elemer elemer --mon nom d'utilisateur 3 fois .

Puis rendez-le exécutable avec chmod 0755 /usr/local/bin/hdmi_sound_toggle

N'oubliez pas de recharger vos règles udev: Sudo udevadm control --reload-rules

Important ce script est mis à jour pour 14.04. Avant cela, vous utiliseriez USER_NAME au lieu de USER_ID partout.

Crédits: Salem et daniel .

3
elemer82

Ubuntu 16.04 - 17.04 Réponse

Cela fonctionne pour Ubuntu 16.04 - 17.04 qui introduisait un bogue avec Pulse Audio 8. Créez le fichier hotplugtv (ou hotplug-hdmi si vous préférez) et copiez-le dans les lignes suivantes:

#!/bin/bash

# NAME: hotplugtv
# PATH: /home/$USER/bin
# DESC: Update pulseaudio output device when HDMI TV plugged / unplugged
# CALL: called from /etc/udev/rules.d/99-hotplugtv.rules 
#       and /home/$USER/bin/lock-screen-timer
# 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.
#       Dec 21, 2016 - Relocated to /home/$USER/bin for calling by lock-screen-timer
#       Aug 06, 2017 - Convert from home grown log-file to universal logger command.

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

exit 0

IMPORTANT: Remplacez le nom d'utilisateur "Rick" par votre nom d'utilisateur.

Pour appeler ce script à partir de udev lors d'événements hot-plug, créez le fichier /etc/udev/rules.d/99-hotplugtv.rules contenant:

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

Remplacez /home/rick/bin/ par le chemin où vous avez placé le script hotplugtv.

1
WinEunuuchs2Unix