Bluetooth Module (#761)
* Added very simple bluetooth device module. * Added a little bit more functionality, like hiding of blocked and non-paired devices, the option to hide disconnected but paired devices. Added colour change and connected_color option for connected devices. * fixing my imperfect style * more fixing of imprefect code style
This commit is contained in:
parent
2c7de0b88e
commit
0550d0ab37
154
i3pystatus/bluetooth.py
Normal file
154
i3pystatus/bluetooth.py
Normal file
@ -0,0 +1,154 @@
|
||||
from os.path import basename
|
||||
|
||||
import dbus
|
||||
|
||||
from i3pystatus import IntervalModule, formatp
|
||||
from i3pystatus.core.util import TimeWrapper
|
||||
|
||||
|
||||
def proxyobj(bus, path, interface):
|
||||
""" commodity to apply an interface to a proxy object """
|
||||
obj = bus.get_object('org.bluez', path)
|
||||
return dbus.Interface(obj, interface)
|
||||
|
||||
|
||||
def filter_by_interface(objects, interface_name):
|
||||
""" filters the objects based on their support
|
||||
for the specified interface """
|
||||
result = []
|
||||
for path in objects.keys():
|
||||
interfaces = objects[path]
|
||||
for interface in interfaces.keys():
|
||||
if interface == interface_name:
|
||||
result.append(path)
|
||||
return result
|
||||
|
||||
|
||||
def getprop(obj, prop, t):
|
||||
return t(obj.Get("org.bluez.Device1", prop))
|
||||
|
||||
|
||||
def get_bluetooth_device_list(show_disconnected):
|
||||
# shamelessly stolen from https://stackoverflow.com/questions/14262315/list-nearby-discoverable-bluetooth-devices-including-already-paired-in-python/14267310#14267310
|
||||
bus = dbus.SystemBus()
|
||||
|
||||
# we need a dbus object manager
|
||||
manager = proxyobj(bus, "/", "org.freedesktop.DBus.ObjectManager")
|
||||
objects = manager.GetManagedObjects()
|
||||
|
||||
# once we get the objects we have to pick the bluetooth devices.
|
||||
# They support the org.bluez.Device1 interface
|
||||
devices = filter_by_interface(objects, "org.bluez.Device1")
|
||||
|
||||
# now we are ready to get the informations we need
|
||||
bt_devices = []
|
||||
for device in devices:
|
||||
obj = proxyobj(bus, device, 'org.freedesktop.DBus.Properties')
|
||||
# skip blocked and unpaired devices.
|
||||
if getprop(obj, "Blocked", bool):
|
||||
continue
|
||||
if not getprop(obj, "Paired", bool):
|
||||
continue
|
||||
if not show_disconnected:
|
||||
if not getprop(obj, "Connected", bool):
|
||||
continue
|
||||
bt_devices.append({
|
||||
"name": getprop(obj, "Name", str),
|
||||
"dev_addr": getprop(obj, "Address", str),
|
||||
"connected": getprop(obj, "Connected", bool)
|
||||
})
|
||||
return bt_devices
|
||||
|
||||
|
||||
class Bluetooth(IntervalModule):
|
||||
"""
|
||||
Shows currently connected bluetooth devices.
|
||||
|
||||
* Requires ``python-dbus`` from your distro package manager, or \
|
||||
``dbus-python`` from PyPI.
|
||||
|
||||
Left click on the module to cycle forwards through devices, and right \
|
||||
click to cycle backwards.
|
||||
|
||||
.. rubric:: Available formatters (uses :ref:`formatp`)
|
||||
|
||||
* `{name}` — (the name of the device)
|
||||
* `{dev_addr}` — (the bluetooth device address)
|
||||
|
||||
.. rubric:: Available callbacks
|
||||
|
||||
* ``next_device`` — iterate forward through devices
|
||||
* ``prev_device`` — iterate backwards through devices
|
||||
|
||||
Example module registration with callbacks:
|
||||
|
||||
::
|
||||
status.register("now_playing",
|
||||
on_leftclick="next_device",
|
||||
on_rightclick="prev_device",
|
||||
on_upscroll="next_device",
|
||||
on_downscroll="prev_device")
|
||||
"""
|
||||
|
||||
interval = 1
|
||||
|
||||
settings = (
|
||||
("format", "formatp string"),
|
||||
("color", "Text color"),
|
||||
("connected_color", "Connected device color"),
|
||||
("show_disconnected", "Show disconnected but paired devices")
|
||||
)
|
||||
|
||||
format = "{name}: {dev_addr}"
|
||||
color = "#ffffff"
|
||||
connected_color = "#00ff00"
|
||||
|
||||
on_leftclick = "next_device"
|
||||
on_rightclick = "prev_device"
|
||||
on_upscroll = 'next_device'
|
||||
on_downscroll = 'prev_device'
|
||||
|
||||
num_devices = 0
|
||||
dev_index = 0
|
||||
devices = []
|
||||
show_disconnected = True
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self.devices = get_bluetooth_device_list(self.show_disconnected)
|
||||
if len(self.devices) < 1:
|
||||
if hasattr(self, "data"):
|
||||
del self.data
|
||||
self.output = None
|
||||
return
|
||||
self.dev_index = self.dev_index % len(self.devices)
|
||||
self.num_devices = len(self.devices)
|
||||
|
||||
fdict = {
|
||||
"name": self.devices[self.dev_index]['name'],
|
||||
"dev_addr": self.devices[self.dev_index]['dev_addr']
|
||||
}
|
||||
|
||||
self.data = fdict
|
||||
color = self.color
|
||||
if self.devices[self.dev_index]['connected']:
|
||||
color = self.connected_color
|
||||
self.output = {
|
||||
"full_text": formatp(self.format, **fdict).strip(),
|
||||
"color": color,
|
||||
}
|
||||
return
|
||||
except dbus.exceptions.DBusException as e:
|
||||
self.output = {
|
||||
"full_text": "DBus error: " + e.get_dbus_message(),
|
||||
"color": "#ff0000",
|
||||
}
|
||||
if hasattr(self, "data"):
|
||||
del self.data
|
||||
return
|
||||
|
||||
def next_device(self):
|
||||
self.dev_index = (self.dev_index + 1) % self.num_devices
|
||||
|
||||
def prev_device(self):
|
||||
self.dev_index = (self.dev_index - 1) % self.num_devices
|
Loading…
Reference in New Issue
Block a user