Configure la salida de sonido HDMI automáticamente al conectar / desconectar

20

Tengo una configuración de pantalla dual en mi computadora portátil (usando 12.04 LTS) usando una pantalla conectada a HDMI. Todo funciona bien, pero cada vez que conecto / desconecto el cable tengo que ir a Preferencias de sonido y cambiar el dispositivo de salida de sonido manualmente.

¿Hay alguna forma de cambiar el dispositivo de salida de sonido en la conexión / desconexión del cable, de modo que cuando conecto mi pantalla la salida de sonido está configurada en HDMI y cuando la desconecto, el sonido vuelve a los altavoces de la computadora portátil?

Salem
fuente
El mismo problema aqui.
ThiagoPonte
Esta es la primera vez que vengo aquí por ayuda ... Estoy en el mismo barco el 12.10. Es molesto. Ha sido así desde la 10.10 en mi experiencia. Tiene que haber una configuración en algún lugar que pueda manejar esto. EDITAR: voices.canonical.com/david.henningsson/2012/04/14/… Se establece de esa manera a propósito. Esto es horrible.
user138216
Comprueba si mi respuesta funciona contigo.
Salem

Respuestas:

11

Para beneficio de las personas que se topan con esta pregunta: la solución de Salem casi funcionó para mí en 13.04, terminé recolectando partes de toda la web, creo que el factor decisivo para mí fue la falta de la variable de entorno PULSE_SERVER

Aquí está mi solución completa, que básicamente es repetir la solución de Salem con las pocas piezas que faltan. También lo rehice como un script de shell (a pesar de mi amor por Python) porque al principio tenía miedo de que mi script de Python se encuentre con problemas de ruta de importación:


(igual que la respuesta de Salem) Cree un archivo /etc/udev/rules.d/hdmi_sound.rulescomo raíz con el contenido:

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

Cree un archivo /usr/local/bin/hdmi_sound_togglecomo root con el contenido:

#!/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

Luego hazlo ejecutable con chmod 0755 /usr/local/bin/hdmi_sound_toggle

Intenté hacer que este script sea lo más genérico posible, pero es posible que deba cambiar algunas líneas, como la ruta del archivo HDMI_STATUS o los perfiles utilizados. Puede ver una lista de perfiles ejecutando pactl list cardsy buscando en Perfiles.

Tenga en cuenta que el script falló cuando eliminé la palabra clave "exportar" cuando configuré PULSE_SERVER, creo que pactl está buscando la variable env

No olvides recargar tus reglas de udev: sudo udevadm control --reload-rules

Actualizar este script se actualiza para 14.04. Antes de eso, usaría USER_NAME en lugar de USER_ID en todas partes

Daniel
fuente
1
Tenga en cuenta que necesitaba agregar | uniqal comando USER_NAME. También tenga en cuenta que la configuración de sonidos en Ubuntu puede ser engañosa. No estaba viendo los cambios en el panel de configuración de sonido, pero una vez que estaba reproduciendo algo, el audio cambiaba de un lado a otro sin problemas, también noté que después de algunas veces de enchufar y desconectar el HDMI, el script dejó de ejecutarse (tal vez algunos tipo de error en udev).
FuegoFro
1
He añadido | sort -ual nombre de usuario porque estaba diciendo opción adicional Elemer Elemer --- Mi nombre de usuario. Igual que la solución de FuegoFro al final del día.
elemer82
Solía | grep -v ptshacerlo, porque en realidad también tenía un usuario "root", debido al hecho de que estaba editando el script a través de kate, que tenía un terminal raíz abierto.
Auspex
Sigue apareciendo "Error de conexión: Conexión rechazada pa_context_connect () falló: Conexión rechazada" cuando se ejecuta pactl. : \
Tomislav Nakic-Alfirevic
7

Finalmente logré hacer que esto funcione usando udev. Entonces, si alguien quiere el mismo comportamiento, estos son los pasos:

Primero necesitamos crear un archivo /etc/udev/rules.d/hdmi_sound.rulescon el siguiente contenido:

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

esto hará que udevejecute el script hdmi_sound_togglecada vez que haya un cambio en la conexión HDMI. Ese script debe tener permiso de ejecución y el contenido es el siguiente:

#!/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))

Probablemente esto se puede hacer fácilmente en bash, pero como mi idioma principal es python, lo usé. Todo funciona excepto la notificación: no aparece, realmente no sé por qué. Si alguien sabe cómo solucionarlo, por favor diga algo.

Nota: los nombres de la regla de script / udev se pueden cambiar, pero debe usar la ruta completa.

Salem
fuente
3

Sobre la base de Salem 's respuesta y Daniel respuesta' s

Tomé la respuesta de Salem y la respuesta de Daniel e hice algunos cambios necesarios, su solución no me funcionó de inmediato:

(similar a la respuesta de Salem).

Cree un archivo /etc/udev/rules.d/hdmi_sound.rulescomo root con el contenido:

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

ACTION=="change", ¡Falta una nota !

Cree un archivo /usr/local/bin/hdmi_sound_togglecomo root con el contenido:

#!/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

Nota USER_NAME =who | grep "(:0)" | cut -f 1 -d ' '| sort -u he añadido| sort -uporque de lo contrario se volvió conelemer elemer elemernombre de usuario --Mi 3 veces.

Luego hazlo ejecutable con chmod 0755 /usr/local/bin/hdmi_sound_toggle

No olvides recargar tus reglas de udev: sudo udevadm control --reload-rules

Importante este script se actualiza para 14.04. Antes de eso, usaría USER_NAME en lugar de USER_ID en todas partes

Créditos: Salem y Daniel .

elemer82
fuente
1

Ubuntu 16.04 - 17.04 Respuesta

Esto funciona para Ubuntu 16.04 - 17.04 que introdujo un error con Pulse Audio 8. Cree el archivo hotplugtv(o hotplug-hdmisi lo prefiere) y copie en las siguientes líneas:

#!/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

IMPORTANTE: Cambie el nombre de usuario "rick" por su nombre de usuario.

Para llamar a este script desde udeveventos de conexión en caliente, cree el archivo que /etc/udev/rules.d/99-hotplugtv.rulescontiene:

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

Cambie /home/rick/bin/a la ruta donde colocó el hotplugtvscript.

WinEunuuchs2Unix
fuente
Muchas gracias! ¡Funcionó también en Ubuntu 17.04! Esto me ha estado molestando durante mucho tiempo y esa fue una solución simple :)
Georgi Koemdzhiev
1
De nada. Gracias por el comentario que confirma que también es necesario para 17.04.
WinEunuuchs2Unix