Defina a saída de som HDMI automaticamente ao conectar / desconectar

20

Tenho uma configuração de tela dupla no meu laptop (usando 12.04 LTS) usando um monitor conectado a HDMI. Tudo funciona bem, mas sempre que eu conecto / desconecto o cabo, tenho que ir para as preferências de som e alterar o dispositivo de saída de som manualmente.

Existe alguma maneira de alterar o dispositivo de saída de som ao conectar / desconectar o cabo; portanto, quando conecto meu monitor, a saída de som é definida como HDMI e, quando o desconecto, o som volta aos alto-falantes do laptop?

Salem
fonte
Mesmo problema aqui.
ThiagoPonte
Esta é a primeira vez que venho aqui para qualquer ajuda nisso ... Estou no mesmo barco às 12h10. É irritante. Tem sido assim desde as 10h10 na minha experiência. Tem que haver uma configuração em algum lugar que possa lidar com isso. EDIT: voices.canonical.com/david.henningsson/2012/04/14/… É definido dessa maneira de propósito. Isso é horrível.
user138216
Verifique se minha resposta funciona com você.
Salem

Respostas:

11

Para o benefício de pessoas que se deparam com essa pergunta - a solução de Salem quase funcionou para mim em 13.04, acabei coletando pedaços de toda a web, acho que o rompimento de contrato para mim foi a falta da variável de ambiente PULSE_SERVER

Aqui está minha solução completa, que basicamente repete a solução de Salem com as poucas peças que faltam. Também o refiz como um script de shell (apesar do meu amor pelo Python) porque, inicialmente, eu tinha medo de que meu script Python estivesse com problemas no caminho de importação:


(igual à resposta de Salem) Crie um arquivo /etc/udev/rules.d/hdmi_sound.rulescomo root com o conteúdo:

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

Crie um arquivo /usr/local/bin/hdmi_sound_togglecomo raiz com o conteúdo:

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

Em seguida, torne-o executável com chmod 0755 /usr/local/bin/hdmi_sound_toggle

Tentei tornar esse script o mais genérico possível, mas você ainda pode precisar alterar algumas linhas, como o caminho do arquivo HDMI_STATUS ou os perfis usados. Você pode ver uma lista de perfis executando pactl list cardse procurando em Perfis.

Observe que o script falhou para mim quando removi a palavra-chave "export" ao definir PULSE_SERVER, acho que o pactl está procurando a variável env

Não se esqueça de recarregar suas regras do udev: sudo udevadm control --reload-rules

A atualização deste script é atualizada para 14.04. Antes disso, você usaria USER_NAME em vez de USER_ID em qualquer lugar

Daniel
fonte
11
Observe que eu precisava anexar | uniqao comando USER_NAME. Observe também que as configurações de sons no Ubuntu podem enganar. Eu não estava vendo as alterações no painel de configurações de som, mas uma vez que eu estava reproduzindo algo, o áudio alternava suavemente e reparei que, depois de algumas vezes conectando e desconectando o HDMI, o script parou de ser executado (talvez alguns tipo de bug no udev).
precisa saber é o seguinte
11
Eu adicionei | sort -uao nome de usuário porque estava dizendo a opção extra elemer elemer --- Meu nome de usuário. O mesmo que a solução da FuegoFro no final do dia.
Elemer82
Eu usei | grep -v pts, porque na verdade também consegui um usuário "root" - por estar editando o script via kate, que tinha um terminal raiz aberto.
Auspex
Continue recebendo "Falha na conexão: conexão recusada pa_context_connect () falhou: conexão recusada" ao executar o pactl. : \
Tomislav Nakic-Alfirevic
7

Eu finalmente consegui fazer esse trabalho usando udev. Portanto, se alguém quiser o mesmo comportamento, aqui estão as etapas:

Primeiro, precisamos criar um arquivo /etc/udev/rules.d/hdmi_sound.rulescom o seguinte conteúdo:

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

isso fará com que udevo script seja executado hdmi_sound_toggletoda vez que houver uma alteração na conexão HDMI. Esse script deve ter permissão de execução e o conteúdo é o seguinte:

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

Provavelmente isso pode ser feito facilmente no bash, mas como minha linguagem principal é python, eu o usei. Tudo funciona, exceto a notificação: não aparece, eu realmente não sei por que. Se alguém souber como consertá-lo, diga alguma coisa.

Nota: os nomes da regra de script / udev podem ser alterados, mas você precisa usar o caminho completo.

Salem
fonte
3

Baseado em Salem 's resposta e daniel resposta' s

Peguei a resposta de Salem e a de Daniel e fiz algumas alterações necessárias, a solução deles não funcionou para mim imediatamente:

(semelhante à resposta de Salem).

Crie um arquivo /etc/udev/rules.d/hdmi_sound.rulescomo raiz com o conteúdo:

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

Nota ACTION=="change", está faltando!

Crie um arquivo /usr/local/bin/hdmi_sound_togglecomo raiz com o conteúdo:

#!/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 adicionei| sort -uporque, caso contrário, ele voltava comelemer elemer elemer--my username três vezes.

Em seguida, torne-o executável com chmod 0755 /usr/local/bin/hdmi_sound_toggle

Não se esqueça de recarregar suas regras do udev: sudo udevadm control --reload-rules

Importante: este script foi atualizado para 14.04. Antes disso, você usaria USER_NAME em vez de USER_ID em qualquer lugar

Créditos: Salem e Daniel .

elemer82
fonte
1

Ubuntu 16.04 - 17.04 Resposta

Isso funciona no Ubuntu 16.04 - 17.04, que apresentou um bug no Pulse Audio 8. Crie o arquivo hotplugtv(ou hotplug-hdmise preferir) e copie nas seguintes linhas:

#!/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: Altere o nome de usuário "rick" para o seu nome de usuário.

Para chamar esse script udevdurante os eventos de hot plug, crie o arquivo que /etc/udev/rules.d/99-hotplugtv.rulescontém:

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

Mude /home/rick/bin/para o caminho em que você colocou o hotplugtvscript.

WinEunuuchs2Unix
fonte
Muito obrigado! Também funcionou no Ubuntu 17.04! Este foi me incomodando há muito tempo e que foi uma solução simples :)
Georgi Koemdzhiev
11
Você é muito bem-vindo. Obrigado pelo comentário confirmando que também é necessário para o dia 17.04.
WinEunuuchs2Unix 9/17/17