Автоматическая настройка звука HDMI при подключении / отключении

20

У меня на ноутбуке двойная настройка экрана (с использованием 12,04 LTS) с использованием дисплея, подключенного через HDMI. Все работает нормально, но каждый раз, когда я подключаю / отключаю кабель, приходится переходить в настройки звука и вручную менять устройство вывода звука.

Есть ли способ изменить устройство вывода звука при подключении / отключении кабеля, поэтому при подключении к моему дисплею вывод звука устанавливается на HDMI, а при отключении звука звук возвращается к динамикам ноутбука?

Salem
источник
Та же проблема здесь.
ThiagoPonte
Это первый раз, когда я прихожу сюда за какой-либо помощью в этом вопросе ... Я нахожусь в одной лодке 12.10. Это раздражает. По моему опыту, так было с 10.10. Где-то должен быть конфиг, который может с этим справиться. РЕДАКТИРОВАТЬ: voices.canonical.com/david.henningsson/2012/04/14/… Он установлен таким образом специально. Это ужасно.
user138216
Проверьте, работает ли мой ответ с вами.
Салем

Ответы:

11

Для людей, которые наткнулись на этот вопрос - решение Салема почти сработало для меня в 13.04, я закончил сбором кусочков со всего интернета, я думаю, что преградой для меня было отсутствие переменной среды PULSE_SERVER

Вот мое полное решение, которое в основном повторяет решение Салема с несколькими недостающими частями. Я также переделал его как скрипт оболочки (несмотря на мою любовь к Python), потому что сначала боялся, что мой скрипт Python сталкивается с проблемами пути импорта:


(аналогично ответу Салема) Создайте файл /etc/udev/rules.d/hdmi_sound.rulesс правами root с содержанием:

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

Создайте файл /usr/local/bin/hdmi_sound_toggleкак root с содержимым:

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

Затем сделайте его исполняемым с chmod 0755 /usr/local/bin/hdmi_sound_toggle

Я попытался сделать этот сценарий как можно более универсальным, но вам все еще может потребоваться изменить некоторые строки, например путь к файлу HDMI_STATUS или используемые профили. Вы можете увидеть список профилей, запустив pactl list cardsи просмотрев под Профили.

Обратите внимание, что сценарий завершился неудачно для меня, когда я удалил ключевое слово «экспорт» при установке PULSE_SERVER, я думаю, что pactl ищет переменную env

Не забудьте перезагрузить ваши правила udev: sudo udevadm control --reload-rules

Обновление этого скрипта обновлено до 14.04. До этого вы бы везде использовали USER_NAME вместо USER_ID

Даниил
источник
1
Обратите внимание, что мне нужно было добавить | uniqкоманду USER_NAME. Также обратите внимание, что настройки звука в Ubuntu могут быть обманчивы. Я не видел изменений на панели настроек звука, но когда я что-то проигрывал, звук плавно переключался назад и вперед, я также заметил, что после нескольких подключений и отключений HDMI сценарий перестал работать (возможно, некоторые ошибка в udev).
FuegoFro
1
Я добавил | sort -uк имени пользователя, потому что он говорил дополнительную опцию elemer elemer --- Мое имя пользователя. То же, что и решение FuegoFro в конце дня.
elemer82
Я использовал | grep -v pts, потому что у меня там тоже был «root» пользователь - из-за того, что я редактировал скрипт через kate, у которого был открыт корневой терминал.
Auspex
Продолжайте получать сообщение «Ошибка подключения: соединение отклонено. Pa_context_connect () Сбой: соединение отклонено» при запуске pactl. : \
Томислав Накич-Альфиревич
7

Мне наконец удалось сделать эту работу с помощью udev. Так что, если кто-то хочет такого же поведения, вот шаги:

Сначала нам нужно создать файл /etc/udev/rules.d/hdmi_sound.rulesсо следующим содержимым:

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

это заставит udevвыполнять скрипт hdmi_sound_toggleкаждый раз, когда происходит изменение в соединении HDMI. Этот сценарий должен иметь разрешение на выполнение, а его содержимое выглядит следующим образом:

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

Возможно, это легко сделать в bash, но так как мой основной язык - python, я использовал его. Все работает, кроме уведомления: оно не появляется, я действительно не знаю почему. Если кто-то знает, как это исправить, скажите, пожалуйста.

Примечание: имена скриптов / правил udev могут быть изменены, но вам нужно использовать полный путь.

Salem
источник
3

Исходя из Салема «S ответить , и DANIEL ответ» ю.ш.

Я взял ответ Салема и ответ Дэниела и внес некоторые необходимые изменения, их решение не сработало для меня из коробки:

(похоже на ответ Салема).

Создайте файл /etc/udev/rules.d/hdmi_sound.rulesкак root с содержимым:

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

Примечание ACTION=="change", отсутствует!

Создайте файл /usr/local/bin/hdmi_sound_toggleкак root с содержимым:

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

Примечание. USER_NAME =who | grep "(:0)" | cut -f 1 -d ' '| sort -u Я добавил,| sort -uпотому что в противном случае он возвращался сelemer elemer elemer--my username 3 раза.

Затем сделайте его исполняемым с chmod 0755 /usr/local/bin/hdmi_sound_toggle

Не забудьте перезагрузить ваши правила udev: sudo udevadm control --reload-rules

Важно, этот скрипт обновлен до 14.04. До этого вы бы везде использовали USER_NAME вместо USER_ID

Кредиты: Салем и Даниил .

elemer82
источник
1

Ubuntu 16.04 - 17.04 Ответ

Это работает для Ubuntu 16.04 - 17.04, в котором появилась ошибка с Pulse Audio 8. Создайте файл hotplugtv(или, hotplug-hdmiесли хотите) и скопируйте в следующие строки:

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

ВАЖНО: Измените имя пользователя «rick» на ваше имя пользователя.

Чтобы вызвать этот сценарий udevво время событий горячей замены, создайте файл, /etc/udev/rules.d/99-hotplugtv.rulesсодержащий:

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

Перейдите /home/rick/bin/на путь, где вы разместили hotplugtvскрипт.

WinEunuuchs2Unix
источник
Спасибо огромное! Это работало и на Ubuntu 17.04! Это долго мучало меня, и это было простое решение :)
Георгий Коемджиев
1
Добро пожаловать. Спасибо за комментарий, подтверждающий, что он необходим и для 17.04.
WinEunuuchs2Unix