У меня есть двойная установка экрана на моем ноутбуке (используя 12.04 LTS) с помощью подключенного дисплея HDMI. Все работает нормально, но каждый раз, когда я подключаю / отключаю кабель, приходится переходить в настройки звука и вручную менять устройство вывода звука.
Есть ли способ изменить устройство вывода звука при подключении / отключении кабеля, поэтому при подключении моего дисплея вывод звука устанавливается на HDMI, а когда я отключаю его, звук возвращается в динамики ноутбука?
В интересах людей, которые натыкаются на этот вопрос - решение Салема почти сработало для меня в 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
и заглянув под Профили.
Обратите внимание, что сценарий не удался для меня, когда я удалил ключевое слово «export» при установке PULSE_SERVER, я думаю, что pactl ищет переменную env
Не забудьте перезагрузить ваши правила udev: sudo udevadm control --reload-rules
Обновление Этот скрипт обновлен до 14.04. До этого вы бы везде использовали USER_NAME вместо USER_ID
. Это работает для 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
скрипт.
Мне наконец удалось сделать эту работу, используя udev
. Итак, если кто-то хочет такого же поведения, вот шаги:
Сначала нам нужно создать файл /etc/udev/rules.d/hdmi_sound.rules
со следующим содержанием:
SUBSYSTEM=="drm", ACTION=="change", RUN+="/usr/local/bin/hdmi_sound_toggle"
это заставит udev
выполнить script 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, я использовал его. Все работает, кроме уведомления: оно не появляется, я действительно не знаю почему. Если кто-то знает, как это исправить, скажите что-нибудь.
Примечание: имена правил script / udev могут быть изменены, но вам нужно использовать полный путь.
я взял ответ Салема и Даниеля [ 1113] и внесли некоторые необходимые изменения, их решение не сработало для меня из коробки:
(аналогично ответу Салема).
Создайте файл /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
, потому что в противном случае он вернулся с [ 117] - мое имя пользователя 3 раза.
Затем сделайте его исполняемым с помощью chmod 0755 /usr/local/bin/hdmi_sound_toggle
Не забудьте перезагрузить правила udev: sudo udevadm control --reload-rules
Важно Этот скрипт обновлен до 14.04. До этого вы использовали бы USER_NAME вместо USER_ID везде