Я хотел бы запустить музыкальный проигрыватель (Clementine), когда моя Bluetooth-гарнитура подключается к моему компьютеру. Как определить подключение устройства Bluetooth, чтобы можно было запустить скрипт для запуска проигрывателя?
Мне не понравился подход к опросу, поэтому я немного покопался в bluez и DBus. В итоге я написал следующий сценарий:
#!/usr/bin/python
import dbus
from dbus.mainloop.glib import DBusGMainLoop
import gobject
import subprocess
# ID of the device we care about
DEV_ID = '00_1D_54_AB_DC_72'
dbus_loop = DBusGMainLoop()
bus = dbus.SystemBus(mainloop=dbus_loop)
# Figure out the path to the headset
man = bus.get_object('org.bluez', '/')
iface = dbus.Interface(man, 'org.bluez.Manager')
adapterPath = iface.DefaultAdapter()
headset = bus.get_object('org.bluez', adapterPath + '/dev_' + DEV_ID)
# ^^^ I'm not sure if that's kosher. But it works.
def cb(iface=None, mbr=None, path=None):
if ("org.bluez.Headset" == iface and path.find(DEV_ID) > -1):
print 'iface: %s' % iface
print 'mbr: %s' % mbr
print 'path: %s' % path
print "\n"
print "matched"
if mbr == "Connected":
subprocess.call(["clementine", "--play"])
print 'conn'
elif mbr == "Disconnected":
subprocess.call(["clementine", "--stop"])
print 'dconn'
headset.connect_to_signal("Connected", cb, interface_keyword='iface', member_keyword='mbr', path_keyword='path')
headset.connect_to_signal("Disconnected", cb, interface_keyword='iface', member_keyword='mbr', path_keyword='path')
loop = gobject.MainLoop()
loop.run()
Чтобы обнаружить успешно установленное соединение Bluetooth, мы можем запустить
sdptool browse xx:xx:xx:xx:xx:xx
. Таким образом, соединение SDB будет проверено на соединение с данным MAC-адресом. Это может занять значительное время, пока время просмотра не закончится с ошибкой, подобной
Failed to connect to SDP server on 00:0C:78:4F:B6:B5: Host is down
Мы не знаем точного назначения вашего скрипта, но, скорее всего, вы хотите воспроизводить звук через Clementine, когда подключена гарнитура.
Тогда мы могли бы просто посмотреть, есть ли аудио-приемник Bluetooth с
pacmd list-sinks | grep xx_xx_xx_xx_xx_xx
, где xx_xx_xx_xx_xx_xx
- MAC-адрес (:
необходимо заменить на _
). Затем на выходе будет указано, доступен ли приемник звука Bluetooth, или ничего, если нет.
См. этот ответ о том, как переключить аудио на этот приемник.
С помощью stream2ip мы можем определить команду оболочки или скрипт для запуска после установления соединения. Существует также возможность автоматического запуска поддерживаемого медиаплеера после установления соединения:
Stream2ip также попытается повторно подключить текущий запущенный поток воспроизведения к Bluetooth аудиоустройство на случай, если соединение было прервано.
Вы пишете «когда ваша гарнитура подключается к вашему компьютеру». Как это происходит автоматически? Когда вам нужно запустить его вручную, вы можете также сделать его сценарием, а затем запустить свой сценарий после установления соединения. Это то, что я сделал, чтобы установить устройство вывода по умолчанию для моего Bluetooth-приемника (чтобы я мог изменить громкость с помощью аппаратных клавиш):
bluetooth-connect && pactl set-default-sink bluez_sink.0C_A6_94_9A_37_4D
Где bluetooth-connect
выглядит так: https: //github.com/sblask/dotfiles/blob/c39d37ad67947b358b4a079cb41ae6f9e4a081d8/.bin/bluetooth-connect.symlink Предполагается, что все сопряжено и готово для подключения. Вы найдете MAC-адрес в blueman или запустите pacmd list-sinks | grep -e 'name:' -e 'index'
, когда подключено устройство Bluetooth. Вы бы хотели запустить bluetooth-connect && your-script
. your-script
будет выполняться только после успешного установления соединения.
Вот еще один пример для мониторинга всех устройств Bluetooth. Не нужно указывать конкретный MAC-адрес. Этот подход делает настройки xinput постоянными даже при входе / выходе, приостановке / пробуждении и подключении / отключении устройства Bluetooth.
У меня компактная Bluetooth-клавиатура Thinkpad, и я хочу запускать команду xinput при подключении клавиатуры для регулировки скорости трекпойнта. Вот шаги.
Загрузите код с Github bluetooth-ruunner . Кредиты даны здесь , который впервые написал это для Raspberry Pi. Измените следующий раздел кода для запуска ваших пользовательских команд.
subprocess.call(['xinput', 'set-prop',
'ThinkPad Compact Bluetooth Keyboard with TrackPoint',
'Device Accel Constant Deceleration', '0.6'])
В моем случае это эквивалентно звонку с терминала.
$ xinput set-prop 'ThinkPad Compact Bluetooth Keyboard with TrackPoint' 'Device Accel Constant Deceleration' 0.6
Сохраните модификацию. Попробуйте запустить свои сценарии с помощью
$ python bluetooth-runner.py
Подключите и отключите устройство Bluethooth. На экране должно появиться соответствующее сообщение.
Теперь, сделайте ваш файл исполняемым и скопируйте его в один из каталогов в вашем $PATH
, скажем, ~/bin/
.
$ chmod +x bluetooth-runner.py
$ mkdir ~/bin # if you dont have it yet
$ cp bluetooth-runner.py ~/bin
Теперь убедитесь, что вы можете запустить скрипт из любой точки терминала (убедитесь, что он находится в вашем пути поиска).
Запустите Startup Applications
из меню Ubuntu. Добавьте ваши скрипты в автозагрузку.
Теперь осталась только одна проблема, в то время, когда вы входите в систему, скрипты могут не перехватить самую первую ] событие Bluetooth. Это связано с тем, что ваше устройство Bluetooth может быть подключено до инициализации сценария в фоновом режиме.
Чтобы решить эту проблему, добавьте свою собственную команду прямо в Startup Applications
. В моем случае это следующая команда:
xinput set-prop 'ThinkPad Compact Bluetooth Keyboard with TrackPoint' 'Device Accel Constant Deceleration' 0.6
И теперь вы сможете наслаждаться своим устройством Bluetooth с Ubuntu.
@Erigami. Твой ответ очень помог, но чтобы это сработало, я бы внес некоторые изменения. Я использую Ubuntu 14.04.
#!/usr/bin/python
import dbus
from dbus.mainloop.glib import DBusGMainLoop
import gobject
import subprocess
# ID of the device we care about
DEV_ID = 'CC:C3:EA:A5:16:90'.replace(":", "_")
dbus_loop = DBusGMainLoop()
bus = dbus.SystemBus(mainloop=dbus_loop)
# Figure out the path to the headset
man = bus.get_object('org.bluez', '/')
iface = dbus.Interface(man, 'org.bluez.Manager')
adapterPath = iface.DefaultAdapter()
print(adapterPath + '/dev_' + DEV_ID)
headset = bus.get_object('org.bluez', adapterPath + '/dev_' + DEV_ID)
# ^^^ I'm not sure if that's kosher. But it works.
def cb(*args, **kwargs):
is_connected = args[-1]
if isinstance(is_connected, dbus.Boolean) and is_connected:
print("Connected")
elif isinstance(is_connected, dbus.Boolean) and not is_connected:
print("Disconnected")
headset.connect_to_signal("PropertyChanged", cb, interface_keyword='iface', member_keyword='mbr', path_keyword='path')
loop = gobject.MainLoop()
loop.run()
Тем не менее, если это не работает, используйте и контролируйте систему dbus.
dbus-monitor --system
d-feet
могут быть использованы в дальнейшем. Это графический инструмент для наблюдения за объектами dbus.