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


20

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

是否可以通过电缆的连接/断开来更改声音输出设备,所以当我连接显示器时,声音输出设置为HDMI,而当我断开连接时,声音返回到笔记本电脑扬声器吗?


这里同样的问题。
ThiagoPonte

这是我第一次来这里寻求任何帮助……我在12.10的同一条船上。它很烦人。根据我的经验,从10.10开始就是这种方式。必须在某个地方可以处理此配置。编辑:voices.canonical.com/david.henningsson/2012/04/14/…它是故意设置的。那太糟了。
user138216 2013年

检查我的答案是否对您有用。
塞勒姆2013年

Answers:


11

为了让那些偶然发现此问题的人受益-塞勒姆的解决方案在13.04中几乎对我有用,我最终从网络上收集了点点滴滴,我认为对我而言,最关键的是缺少环境变量PULSE_SERVER

这是我的完整解决方案,基本上是重复了Salem的解决方案,但缺少了一些内容。我也将其重命名为shell脚本(尽管我对Python情有独钟),因为起初我担心我的Python脚本会遇到导入路径问题:


(与Salem的答案相同)创建一个/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内容的根文件:

#!/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正在寻找env变量

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

更新此脚本已针对14.04更新。在此之前,您将在各处使用USER_NAME而不是USER_ID


1
请注意,我需要附加| uniq到USER_NAME命令。另请注意,Ubuntu中的声音设置可能会欺骗。我没有在声音设置面板中看到更改,但是一旦播放了某些内容,音频就会平稳地来回切换,我还注意到在插入和拔出HDMI几次后,脚本停止运行了(也许有些udev中的错误)。
FuegoFro 2014年

1
我添加| sort -u了用户名,因为它说的是额外的选项elemer elemer ---我的用户名。最终与FuegoFro的解决方案相同。
elemer82 2014年

我曾经用过| grep -v pts,因为我实际上是通过kate编辑脚本的,所以实际上我在那里也有一个“ root”用户,因为kate打开了root终端。
Auspex

运行pactl时,不断出现“连接失败:连接被拒绝pa_context_connect()失败:连接被拒绝”。:\
Tomislav Nakic-Alfirevic,

7

我终于设法使用来完成这项工作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,所以我使用了它。除通知外,其他所有方法都有效:它没有显示,我真的不知道为什么。如果有人知道如何解决,请说些什么。

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


3

基于塞勒姆的答案和丹尼尔的答案

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

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

创建一个包含/etc/udev/rules.d/hdmi_sound.rules内容的根文件:

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

注意 ACTION=="change", 丢失!

创建一个包含/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用户名返回了3次。

然后使用 chmod 0755 /usr/local/bin/hdmi_sound_toggle

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

重要的是,此脚本已针对14.04更新。在此之前,您将在各处使用USER_NAME而不是USER_ID

学分:塞勒姆丹尼尔


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


非常感谢!它也适用于Ubuntu 17.04!这已经困扰了我很长时间了,这是一个简单的解决方案:)
Georgi Koemdzhiev

1
不用客气。感谢您的评论,确认17.04也需要它。
WinEunuuchs2Unix
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.