Как заставить udev проверять аудиоустройства
Я пытаюсь написать правило udev для моего приемника Bluetooth, которое при подключении запускает сценарий, который проверяет, было ли также добавлено соответствующее аудиоустройство, и повторно подключается, если это не так. По какой-то причине, когда я включаю ресивер и он автоматически подключается, сначала аудиоустройство не добавляется. Я использую Pipewire-Pulse.
Проблема в том, что я не знаю, как заставить udev проверять аудиоустройства.pactl list
не работает с правами root, но это нормально, потому что теоретическиpw-cli list-objects
должно сработать. Итак, мой сценарий выглядит так:
#!/bin/bash
sleep 3
# JR-CB1 connected but not available as audio device
if bluetoothctl devices Connected | grep "25:4E:4A:C7:43:C4" && ! pw-cli list-objects | grep "25_4E_4A_C7_43_C4"; then
# Reconnect
bluetoothctl disconnect 25:4E:4A:C7:43:C4
bluetoothctl connect 25:4E:4A:C7:43:C4
fi
Сsu
в терминале это работает нормально. Он переподключается, если аудиоустройство отсутствует, и ничего не делает, если оно есть. Вывод после добавления аудиоустройства:
object.path = "bluez_output.25_4E_4A_C7_43_C4.1:monitor_0"
object.path = "bluez_output.25_4E_4A_C7_43_C4.1:monitor_1"
node.name = "bluez_output.25_4E_4A_C7_43_C4.1"
device.name = "bluez_card.25_4E_4A_C7_43_C4"
object.path = "bluez_output.25_4E_4A_C7_43_C4.1:playback_1"
object.path = "bluez_output.25_4E_4A_C7_43_C4.1:playback_0"
а возвращаемое значение grep равно 0, поэтому оператор if не должен выполняться. Однако, хотя в терминале это работает, в udev по какой-то причине это не работает. При протоколировании вывода сценария, запущенного udev, выводpw-cli list-objects | grep "25_4E_4A_C7_43_C4"
пусто, а возвращаемое значение равно 1, что означает, что переподключение выполнено, и я получаю бесконечный цикл переподключения.
Почему udev не может перечислить аудиоустройства Pipewire? Есть ли другой способ?
1 ответ
Думаю, я нашел решение. Как было предложено в комментарии, я рассмотрел возможность использования службы для запуска сценария. Чтобы сообщить systemd о событии устройства, я использовал следующее правило udev:
/etc/udev/rules.d/60-bluetooth-add-event.rules
CTION=="add", SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_WANTS}="bluetooth-add-event.service"
(Я пытался определить атрибут, специфичный для моего устройства Bluetooth, но без устройства Pipewire, похоже, для udev не доступны никакие уникальные атрибуты, поэтому я запускаю службу всякий раз, когда подключается какое-либо устройство bt, и позволяю сценарию обрабатывать идентификацию.)
Сервис выглядит следующим образом:
/etc/systemd/system/bluetooth-add-event.service
[Unit]
Description=Runs when bluetooth connection is added
Requires=bluetooth.target
After=bluetooth.target
[Service]
ExecStart=/usr/bin/bluetooth-add-event.sh
Type=exec
Restart=no
[Install]
WantedBy=multi-user.target
Это не пользовательская служба, потому чтоpw-cli
может использоваться пользователем root, но не при запуске udev.
(Мое понимание опций системного модуля находится в зачаточном состоянии, поэтому любые предложения по улучшению приветствуются.)
Скрипт тот же, что и раньше:
/usr/bin/bluetooth-add-event.sh
#!/bin/bash
sleep 3
# JR-CB1 connected but not available as audio device
if bluetoothctl devices Connected | grep "25:4E:4A:C7:43:C4" && ! pw-cli list-objects | grep "25_4E_4A_C7_43_C4"; then
# Reconnect
bluetoothctl disconnect 25:4E:4A:C7:43:C4
bluetoothctl connect 25:4E:4A:C7:43:C4
fi
Теперь, когда я подключаю устройство, сценарий запускается один раз, не находит аудиоустройство, повторно подключает устройство Bluetooth, затем запускается снова, но ничего не делает, потому что находит аудиоустройство вpw-cli list-objects
.