スクリプトを書かずに動的に変更されるデフォルトのスピーカーシーケンスを設定できますか?

スクリプトを書かずに動的に変更されるデフォルトのスピーカーシーケンスを設定できますか?

私は独自のスピーカー付きのラップトップを持っています。その後、接続すると、より良いスピーカーを備えたモニター(USB-C経由のDP、ステレオ2.0)があります。調理中にビデオを見たり聞いたりするときに使用するポータブルスピーカー(ブル​​ートゥース、3.5ジャック、マイクロUSB接続、ステレオ)もあります。時には、HDMI-AVR(5.1)を介してノートブックをホームシアターに接続することもあります。これらはすべて動的に変更され、3つまたは4つが同時に接続できます。

次のようにデバイスの優先順位を設定したいと思います。

  1. レギュレータ
  2. ポータブルアンプ
  3. 監視装置
  4. ラップトップ

これにより、設定を変更したときに魔法のように自動的に選択されます(1日に複数回発生する可能性があります)。

今PulseAudioは最高のものを選択しようとし、時には成功し、時にはそうではありません。

  1. 私のインターネット検索が正しい場合は、設定ファイルまたは一部のGUIでデフォルトを設定できないため、スクリプトを作成する必要があります。私はこれに少し驚きました。私はこれが一般的なユースケースであるに違いないと思いました。だから私はそのようなスクリプトを書く前に私の研究が間違っているかどうか尋ねたかったのです(または誰かがそのようなスクリプトを持っている場合は自由に共有してください。私が見つけた唯一のものは次のとおりです)。https://askubuntu.com/questions/263248/set-hdmi-sound-output-automatically-on-connect-disconnect- 私の設定ほど複雑ではありません)

  2. 私を混乱させるもう一つのことは、「DELL U4320Q」、「JieLi AC46」などのデバイスの実際の名前がGnome、KDE、またはpactl(pactl属性のカード> 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.rulesましたsudo udevadm control --reload-rules/usr/local/bin/run_hdmi_sound_toggle以下は、root で実行され、ユーザーとして実行される Pipewire/PulseAudio に接続できない udev を処理するラッパースクリプトです。

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

対応するシステムサービスファイル~/.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/Bluetoothデバイスをうまく処理しているようです。

関連情報