是否可以设置动态更改的首选扬声器顺序,而无需编写脚本?

是否可以设置动态更改的首选扬声器顺序,而无需编写脚本?

我有一台带有自己的扬声器的笔记本电脑。然后我有一台显示器(DP 通过 USB-C,立体声 2.0),它有更好的扬声器,我更喜欢在连接时使用。我还有一个便携式扬声器(蓝牙、3.5 插孔和微型 USB 连接、立体声),我在做饭时观看/收听视频时使用。有时我还会通过 HDMI 转 AVR (5.1) 将笔记本电脑连接到家庭影院。所有这些都是动态变化的,并且可能会同时连接三个或四个。

我想设置设备的优先级,如下所示:

  1. 调压器
  2. 便携式扩音器
  3. 监视器
  4. 笔记本电脑

这样当我更改配置时它们会神奇地自动选择(一天可能会发生几次)

现在,PulseAudio 尝试选择最佳的一个,有时会成功,有时则不会。

  1. 如果我的谷歌搜索是正确的,我就无法通过配置文件或某些 GUI 设置默认值,我需要编写一个脚本。我对此感到有点惊讶 - 我认为这一定是一个常见的用例。所以我想在尝试编写这样的脚本之前问我的研究是否错误(或者如果有人有这样的脚本,请随意分享它,我发现的唯一的就是:https://askubuntu.com/questions/263248/set-hdmi-sound-output-automatically-on-connect-disconnect- 这并不像我的设置那么复杂)

  2. 另一件令我困惑的事情是,在 Gnome、KDE ​​或 pactl 中的所有工具中,诸如“DELL U4320Q”、“JieLi AC46”等设备的实际名称都被隐藏了(在 pactl 中的 card>properties>device.product 下) .name)并且未在 UI 中公开。这是为什么?它们肯定会更具人类可读性。对于显示器,我通常会得到类似“dmi-output-0: HDMI / DisplayPort”的信息 - 我如何知道我将显示器连接到哪个端口(哪个端口是 0,哪个端口是 1)?之所以会这样,是不是有什么原因呢?每次我更新安装时,我都很好奇是否有任何改进,但它基本上保持不变。 Pipewire 会帮忙解决这个问题吗?我认为 PulseAudio 应该使这种用法变得简单:-)。

答案1

所以最后我编写了以下脚本/usr/local/bin/hdmi_sound_toggle.py来自动为我进行切换。它使用此处提供的脚本:https://stackoverflow.com/a/24933353/1269040找出连接了哪些显示器。

#!/usr/bin/env python3
import subprocess
# find_monitors is the script from the internet to check EDID data - I put it into $PATH
# the following implements "find_monitors 2>/dev/null | grep '#' 2>/dev/null 1"
# my internal monitor is confusing the script, outputing some weird binary data, so I strip it on the second line
monitors_gibberish = subprocess.check_output(("find_monitors"), shell=True,  stderr=subprocess.DEVNULL)
monitors_one_line = monitors_gibberish.replace(b'# eDP-1-1 HDMI   \xff\xff\xff\xff\xff\xff\r\xae\x0c\x15', b'').decode("UTF-8")
monitors_lines = [i for i in monitors_one_line.split('\n') if i]
default_sink = ''
alsa_card = "pci-0000_01_00.1"
port_number = 0
profile_name = ''
if "H/K AV AMP" in monitors_one_line:
    # AVR is connected through HDMI port and that has always number three, so it has "-extra2" added the profile name
    profile_name = "hdmi-surround-extra2"
elif "DELL U4320Q" in monitors_one_line:
    for i in monitors_lines:
        if "DELL U4320Q" in i:
            # This is being split: '# DP-0 DisplayPort   DELL U4320Q'
            # DP numbering start at 0, HDMI numbering in Pipewire/alsa starts at 1
            port_number = int(i.split(" ")[1].split("-")[1]) + 1
            if port_number == 1:
                profile_name = "hdmi-stereo"
            elif port_number == 2:
                profile_name = "hdmi-stereo-extra1"
# first we need to set default profile for HDMI - it tells Pipewire to which device it should send audio streams over HDMI
if profile_name:
    default_sink = 'alsa_output.' + alsa_card + "." + profile_name
    subprocess.run(["pactl", "set-card-profile", "alsa_card." + alsa_card, "output:" + profile_name])
    # and now we switch the default sink, ie. device that should play all audio by default
    subprocess.run(["pactl", "set-default-sink", default_sink])
~                                                                 

为了自动运行它,我这样写:

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

就跑/etc/udev/rules.d/99-hdmi_sound.rulessudo udevadm control --reload-rules/usr/local/bin/run_hdmi_sound_toggle这是一个包装脚本,用于处理在 root 下运行的 udev 并无法连接到用户运行的 Pipewire/PulseAudio:

#!/bin/bash
systemctl [email protected] --user --now start hdmi_sound_toggle.service

相应的 systemd 服务文件~/.config/systemd/user/hdmi_sound_toggle.service是:

[Unit]
Description=Runs /usr/local/bin/hdmi_sound_toggle.py to switch to the correct sound output
  
[Service]
Type=oneshot
ExecStart=/usr/local/bin/hdmi_sound_toggle.py

然后它在 DHMI/USB-C/DP 插入/拔出上运行。

它只对通过 DP 或 HDMI 连接的设备起作用 - Pipewire 似乎可以很好地处理 USB/蓝牙设备。

相关内容