我想在蓝牙耳机连接到电脑时启动音乐播放器 (Clementine)。如何检测连接的蓝牙设备,以便运行脚本来启动播放器?
答案1
我不喜欢轮询方法,所以我对 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()
答案2
为了发现成功建立的蓝牙连接,我们可以运行
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 播放音频。
然后我们就可以看看是否有一个蓝牙音频接收器
pacmd list-sinks | grep xx_xx_xx_xx_xx_xx
xx_xx_xx_xx_xx_xx
MAC 地址在哪里(:
需要替换为_
)。然后,输出将告诉您是否有可用的蓝牙音频接收器,如果没有,则什么也没有。
看这个答案如何将音频切换到该接收器。
Stream2ip
和流2ip我们可以定义一个 shell 命令或脚本,在建立连接后运行。还有一个选项可以在建立连接后自动启动支持的媒体播放器:
如果连接中断,Stream2ip 还会尝试将当前正在运行的播放流重新连接到蓝牙音频设备。
答案3
@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 对象的 GUI 工具。
答案4
你写“当你的耳机连接到你的电脑时”。它是如何自动做到这一点的?当你必须手动触发它时,你不妨将其制作成脚本,然后在建立连接后运行你的脚本。这是我将默认输出设备设置为我的蓝牙接收器所做的(这样我就可以用硬件键更改音量):
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它假设所有设备都已配对并准备好连接。您可以在 blueman 中找到 MAC 地址,或者pacmd list-sinks | grep -e 'name:' -e 'index'
在蓝牙设备连接时运行。您可能希望运行bluetooth-connect && your-script
。your-script
只有在成功建立连接后才会运行。