連接/斷開連接時自動設定 HDMI 聲音輸出

連接/斷開連接時自動設定 HDMI 聲音輸出

我的筆記型電腦(使用 12.04 LTS)上有一個雙螢幕設置,使用 HDMI 連接顯示器。一切正常,但每次連接/斷開電纜時,我都必須進入聲音首選項並手動更改聲音輸出設備。

有什麼方法可以在連接/斷開電纜時更改聲音輸出設備,以便當我連接顯示器時,聲音輸出設置為 HDMI,當我斷開連接時,聲音會返回到筆記型電腦揚聲器?

答案1

為了偶然發現這個問題的人的利益 - Salem 的解決方案幾乎在 13.04 中為我工作,我最終從網絡上收集了一些零碎的東西,我認為對我來說最大的問題是缺少環境變量 PULSE_SERVER

這是我的完整解決方案,基本上是重複塞勒姆的解決方案,但缺少一些內容。我還將它重新編寫為 shell 腳本(儘管我很喜歡 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 時刪除關鍵字“export”時,腳本對我來說失敗了,我認為 pactl 正在尋找 env 變量

不要忘記重新載入您的 udev 規則:sudo udevadm control --reload-rules

更新該腳本已更新至 14.04。在此之前,您將在任何地方使用 USER_NAME 而不是 USER_ID

答案2

Ubuntu 16.04 - 20.04 答案

hotplugtv這適用於 Ubuntu 16.04 - 20.04,它引入了 Pulse Audio 8 的錯誤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

答案3

我終於成功地使用了這項工作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 規則的名稱可以更改,但需要使用完整路徑。

答案4

有一個更簡單的方法:

在 中定義 default-sink 和 default-source /etc/pulse/default.pa,如下所述:https://rastating.github.io/setting-default-audio-device-in-ubuntu-18-04/

grep default- /etc/pulse/default.pa
load-module module-default-device-restore
set-default-sink alsa_output.pci-0000_00_1f.3.analog-stereo
set-default-source alsa_input.pci-0000_00_1f.3.analog-stereo

重試之前不要忘記重新啟動pulseaudio:

pulseaudio -k

相關內容