hif*_*ife 5 python pulseaudio udev
每当我连接到蓝牙耳机时,我都会尝试自动运行此脚本。
我已经用以下行创建了文件 /etc/udev/rules.d/80-bt-headset.rules
ACTION=="add", SUBSYSTEM=="input" ATTR{name}=="00:22:37:3D:DA:50" RUN+="/home/USER/.local/bin/a2dp.py 00:22:37:3D:DA:50"
Run Code Online (Sandbox Code Playgroud)
但它没有做任何事情。条件很好,当我输入时会触发一个简单的测试命令。手动运行时,脚本本身也能正常工作。
这里出了什么问题?
更新:运行脚本时出错sudo -u USER
(有关详细信息,请参见下文)。这可能是问题吗?对同一用户执行 sudo 操作会如何破坏事情?
更新 2:在替换pacmd
with pactl
in 的所有实例a2dp.py
(并替换list-sinks
withlist sinks
使其成为有效的 pactl 命令)后,sudo -u USER
工作,但是, udev 规则仍然没有。在/var/log/syslog
我只看到这条线
systemd-udevd[32629]: Process '/home/USER/.local/bin/a2dp_2.py 00:22:37:3D:DA:50' failed with exit code 1.
Run Code Online (Sandbox Code Playgroud)
更新 3(解决方案):使用环境变量修改后的 skript(pacmd -> pactl,请参阅更新 2)DISPLAY=:0
并XAUTHORITY=/home/USER/.Xauthority
成功。udev 规则:
ACTION=="add", SUBSYSTEM=="input" ATTR{name}=="00:22:37:3D:DA:50" ENV{DISPLAY}=":0" ENV{XAUTHORITY}="/home/USER/.Xauthority" RUN+="/home/USER/.local/bin/a2dp_2.py 00:22:37:3D:DA:50"
Run Code Online (Sandbox Code Playgroud)
正在按预期工作。
(现在唯一剩下的问题是,脚本本身会触发规则,因为它重新连接耳机,导致无限循环。但是,这是一个单独的问题,应该不难找到解决方法。在事实上,当我开始这个线程时,我期待这种行为。)
条件很好: 该行:
ACTION=="add", SUBSYSTEM=="input" ATTR{name}=="00:22:37:3D:DA:50" RUN+="/bin/mkdir /tmp/testme"
Run Code Online (Sandbox Code Playgroud)
当我连接到耳机时将创建一个新目录。
当通过终端从终端运行时,脚本 a2dp.py 本身工作正常
/home/USER/.local/bin/a2dp.py 00:22:37:3D:DA:50
Run Code Online (Sandbox Code Playgroud)通过 udev 运行一个简单的 Python 脚本:
ACTION=="add", SUBSYSTEM=="input" ATTR{name}=="00:22:37:3D:DA:50" RUN+="/home/USER/.local/bin/atestscript.py"
Run Code Online (Sandbox Code Playgroud)
其中 atestscript.py 包含:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import subprocess
def main():
subprocess.Popen(['mkdir', '/tmp/atestdir'])
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud)
连接设备后将再次创建一个文件夹。
从终端运行脚本,sudo -u USER
甚至sudo -u root
现在按预期工作(对于原始脚本,这导致:
USER@MACHINE:~$ sudo -u USER /usr/local/bin/a2dp.py 00:22:37:3D:DA:50
Connection MADE
Device MAC: 00:22:37:3D:DA:50
Command: pacmd list-sinks failed with status: 1
stderr: No PulseAudio daemon running, or not running as session daemon.
Exiting bluetoothctl
Run Code Online (Sandbox Code Playgroud)运行上述脚本或使用以下任一行作为RUN+=
部分:
/usr/bin/sudo -u USER /usr/bin/python3 /home/USER/.local/bin/a2dp.py 00:22:37:3D:DA:50
/usr/bin/sudo -u USER /home/USER/.local/bin/a2dp.py 00:22:37:3D:DA:50
/usr/bin/python3.5 /usr/local/bin/a2dp.py 00:22:37:3D:DA:50
ENV{DISPLAY}=":0" RUN+="/usr/local/bin/a2dp.py 00:22:37:3D:DA:50"
Run Code Online (Sandbox Code Playgroud)
即使修改后的脚本也不起作用:
ENV{DISPLAY}=":0" ENV{PULSE_RUNTIME_PATH}="/run/user/1000/pulse/" RUN+="sudo -u USER /home/USER/.local/bin/a2dp_2.py 00:22:37:3D:DA:50"
Run Code Online (Sandbox Code Playgroud)更多信息:连接到耳机的 udevadm 监视器输出:
KERNEL[104388.664737] add /devices/pci0000:00/0000:00:14.0/usb3/3-7/3-7:1.0/bluetooth/hci0/hci0:256 (bluetooth)
UDEV [104388.667185] add /devices/pci0000:00/0000:00:14.0/usb3/3-7/3-7:1.0/bluetooth/hci0/hci0:256 (bluetooth)
KERNEL[104390.848157] add /devices/virtual/input/input46 (input)
UDEV [104390.849150] add /devices/virtual/input/input46 (input)
KERNEL[104390.849471] add /devices/virtual/input/input46/event17 (input)
UDEV [104390.864692] add /devices/virtual/input/input46/event17 (input)
Run Code Online (Sandbox Code Playgroud)
a2dp.py
通过将 的所有实例替换为pacmd
调整pactl
来进行pacmd list-sinks
修改(pactl list sinks
在我的情况下另存为/usr/local/bin/a2dp_2.sh
)。
创建包装脚本/usr/local/bin/a2dp-wrapper.sh
#!/bin/bash
MAC=$1
MACMOD=$(echo $MAC | sed 's/:/_/g')
PID=$(pgrep pulseaudio)
USER=$(grep -z USER= /proc/$PID/environ | sed 's/.*=//')
export DISPLAY=:0
export XAUTHORITY=/home/$USER/.Xauthority
if pactl list sinks short | grep "bluez_sink\.$MACMOD.*SUSPENDED"
then
sudo -u $USER /usr/local/bin/a2dp_2.py $MAC
fi
Run Code Online (Sandbox Code Playgroud)将以下行添加到/etc/udev/rules.d/80-bt-headset.rules
:
ACTION=="add", SUBSYSTEM=="input" ATTR{name}=="00:22:37:3D:DA:50" RUN+="/usr/local/bin/a2dp-wrapper.sh $attr{name}"
Run Code Online (Sandbox Code Playgroud)该包装器脚本完成以下任务:
它找到$USER
正在运行的pulseaudio实例的拥有者,然后设置工作DISPLAY=:0
所需XAUTHORITY=/home/$USER/.Xauthority
的环境变量。pactl
这应该使它适用于计算机上的所有用户。(我没有测试多用户同时登录的效果。)
它检查相应的接收器是否挂起,然后才运行a2dp_2.py
。这对于防止因a2dp_2.py
重新连接设备而触发规则而导致无限循环是必要的。
它a2dp_2.py
以 $USER 身份运行。如果以 root 身份运行,a2dp_2.py
则在没有 root 权限的情况下将无法访问pulseaudio,因此任何音频设置都将无法访问。
可以在sript 开发人员页面上找到使用 dbus 循环的替代解决方案。
现在可以在此处修复原始错误,并且可以通过添加ppa:ubuntu-audio-dev/pulse-testing
和更新可用软件包轻松安装。
严格来说,这不是原始问题的一部分,但这可能对将来的参考有用。有多种方法可以查找设备的 MAC 地址。以下是我认为对 udev 规则最有帮助的一条:
udevadm monitor
通过运行然后连接您的设备来查找设备路径。你的输出应该是这样的:
USER@MACHINE:~$ udevadm monitor
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent
KERNEL[123043.617276] add /devices/pci0000:00/0000:00:14.0/usb3/3-7/3-7:1.0/bluetooth/hci0/hci0:256 (bluetooth)
UDEV [123043.647291] add /devices/pci0000:00/0000:00:14.0/usb3/3-7/3-7:1.0/bluetooth/hci0/hci0:256 (bluetooth)
KERNEL[123044.153776] add /devices/virtual/input/input68 (input)
KERNEL[123044.153911] add /devices/virtual/input/input68/event17 (input)
UDEV [123044.193415] add /devices/virtual/input/input68 (input)
UDEV [123044.213213] add /devices/virtual/input/input68/event17 (input)
Run Code Online (Sandbox Code Playgroud)
用 停止监视器Ctrl+C
。我们找到了三个设备路径。与我们相关的是/devices/virtual/input/input68
.
将获得的路径插入udevadm info
:
USER@MACHINE:~$ udevadm info -a -p /devices/virtual/input/input68
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
looking at device '/devices/virtual/input/input68':
KERNEL=="input68"
SUBSYSTEM=="input"
DRIVER==""
ATTR{name}=="00:22:37:3D:DA:50"
ATTR{phys}==""
ATTR{properties}=="0"
ATTR{uniq}==""
Run Code Online (Sandbox Code Playgroud)
我们了解到 MAC 地址是00:22:37:3D:DA:50
并且它存储为ATTR{name}
。
即使输出看起来完全不同,这两个命令也将是寻找 udev 规则的相关条件的良好开端。
规则:
ACTION=="add", SUBSYSTEM=="input" ATTR{name}=="??:??:??:??:??:??" RUN+="/usr/local/bin/a2dp-wrapper.sh $attr{name}"
Run Code Online (Sandbox Code Playgroud)
将触发任何具有类似于 MAC 地址的名称属性的输入设备,并且包装器脚本中的条件应确保不会采取意外的操作。
我没有任何其他蓝牙音频设备可供测试,但我发现了一些潜在的问题:
这仅适用于被识别为名称属性中包含 MAC 地址的输入设备的蓝牙设备。并非所有设备都可以被这样识别。
这个解决方案不是很优雅,因为任何输入设备都会触发该规则。然而,我一直无法找到明确的指标来识别蓝牙音频设备。(如上所示,输入设备没有其他属性,并且蓝牙设备没有显示出是音频设备的指示,也不包含 MAC 地址。也许 ACPI 对此会更好。)
您可能不希望对每个蓝牙音频设备都一视同仁:您可能希望对您的耳机使用 HSP 协议,或者您可能不希望自动切换到您室友的扬声器(无论何时,您在某个时刻已配对过)可用的。在这些情况下,最好为每个设备制定单独的规则。
随着我了解更多,我将继续更新这篇文章。
归档时间: |
|
查看次数: |
4098 次 |
最近记录: |