当前位置: 首页>>技术教程>>正文


连接/断开连接时自动设置 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 并在配置文件下查看来查看配置文件列表。

请注意,当我在设置 PULSE_SERVER 时删除关键字 “export” 时脚本对我来说失败了,我认为 pactl 正在寻找环境变量

不要忘记重新加载您的 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"

这将使 udev 在每次 HDMI 连接发生变化时执行脚本 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,所以我使用了它。除了通知,一切正常:它没有出现,我真的不知道为什么。如果有人知道如何修复它,请说些什么。

注意:脚本/udev 规则的名称可以更改,但您需要使用完整路径。

第三种思路

Ubuntu 16.04 – 20.04 答案

这适用于 Ubuntu 16.04 – 20.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” 更改为您的用户名。

为了在 hot-plug 事件期间从 udev 调用此脚本,创建文件 /etc/udev/rules.d/99-hotplugtv.rules,其中包含:

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

/home/rick/bin/ 更改为放置 hotplugtv 脚本的路径。

第四种思路

基于 Salem 的回答和 daniel 的回答

我接受了 Salem 的回答和 daniel 的回答并进行了一些必要的更改,他们的解决方案对我来说开箱即用:

(类似于塞勒姆的回答)。

以 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 我添加了 | 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

积分:Salemdaniel

参考资料

本文由Ubuntu问答整理, 博文地址: https://ubuntuqa.com/article/13569.html,未经允许,请勿转载。