连接/断开时自动设置HDMI声音输出

我的笔记本电脑(使用12.04 LTS)使用HDMI连接显示器进行双屏设置。 一切正常,但每次连接/断开电缆我都必须转到声音首选项并手动更改声音输出设备。

有没有办法在连接/断开电缆时更改声音输出设备,所以当我连接我的显示器时,声音输出设置为HDMI,当我断开它时声音会回到笔记本电脑扬声器?

为了帮助那些偶然发现这个问题的人 – Salem的解决方案在13.04几乎对我有用,我最终收集了来自网络各处的点点滴滴,我认为对我而言,这个交易的缺点是缺少环境变量PULSE_SERVER

这是我的完整解决方案,它基本上重复了Salem的解决方案,其中包含一些缺失的部分。 我还把它作为shell脚本重新编写(尽管我喜欢Python)因为我起初害怕我的Python脚本遇到导入路径问题:


(与Salem的答案相同)以root身份创建文件/etc/udev/rules.d/hdmi_sound.rules ,内容如下:

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

使用以下内容以root身份创建文件/usr/local/bin/hdmi_sound_toggle

 #!/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并查看“个人档案”来查看个人档案pactl list cards

请注意,当我在设置PULSE_SERVER时删除关键字“export”时脚本失败,我认为pactl正在查找env变量

不要忘记重新加载你的udev规则: sudo udevadm control --reload-rules

更新此脚本的更新时间为14.04。 在此之前,您将在任何地方使用USER_NAME而不是USER_ID

我终于使用udev设法完成了这项工作。 因此,如果有人想要相同的行为,请执行以下步骤:

首先,我们需要创建一个文件/etc/udev/rules.d/hdmi_sound.rules其中包含以下内容:

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

每次HDMI连接发生变化时,这将使udev执行脚本hdmi_sound_toggle 。 该脚本必须具有执行权限,内容如下:

 #!/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规则的名称,但您需要使用完整路径。

根据塞勒姆的回答和丹尼尔的回答

我接受了Salem的回答和daniel的回答并进行了一些必要的修改,他们的解决方案对我来说不起作用:

(与Salem的答案类似)。

使用以下内容以root身份创建文件/etc/udev/rules.d/hdmi_sound.rules

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

注意 ACTION=="change",缺少!

使用以下内容以root身份创建文件/usr/local/bin/hdmi_sound_toggle

 #!/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 who | grep "(:0)" | cut -f 1 -d ' '| sort -u who | grep "(:0)" | cut -f 1 -d ' '| sort -u我添加了| sort -u | sort -u因为否则它回来了elemer elemer elemer我的用户名3次。

然后使用chmod 0755 /usr/local/bin/hdmi_sound_toggle使其可执行

不要忘记重新加载你的udev规则: sudo udevadm control --reload-rules

重要此脚本已更新为14.04。 在此之前,您将在任何地方使用USER_NAME而不是USER_ID

致谢: 塞勒姆和丹尼尔 。

这是我第一次来这里寻求帮助…我在12.10的同一条船上。 它很烦人。 根据我的经验,这是10.10以来的方式。 必须有一个可以处理这个问题的配置。

编辑: http : //voices.canonical.com/david.henningsson/2012/04/14/audio-over-hdmi-and-displayport-in-ubuntu-12-04/

它是故意设定的。 那太糟了。

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脚本的路径。