def bond(device: Device) -> None: def error_handler(e: Exception) -> None: logging.exception(e) message = f"Pairing failed for:\n{device['Alias']} ({device['Address']})" Notification('Bluetooth', message, icon_name="blueman").show() device.pair(error_handler=error_handler)
def _disconnect_service( self, object_path: str, uuid: str, port: int, ok: Callable[[], None], err: Callable[ [Union[BluezDBusException, "NMConnectionError", GLib.Error, str]], None] ) -> None: if uuid == '00000000-0000-0000-0000-000000000000': device = Device(obj_path=object_path) device.disconnect(reply_handler=ok, error_handler=err) else: service = get_service(Device(obj_path=object_path), uuid) assert service is not None if any( plugin.service_disconnect_handler(service, ok, err) for plugin in self.parent.Plugins.get_loaded_plugins( ServiceConnectHandler)): pass elif isinstance(service, SerialService): service.disconnect(port, reply_handler=ok, error_handler=err) for plugin in self.parent.Plugins.get_loaded_plugins( RFCOMMConnectedListener): plugin.on_rfcomm_disconnect(port) logging.info("Disconnecting rfcomm device") elif isinstance(service, NetworkService): service.disconnect(reply_handler=ok, error_handler=err)
def _disconnect_service( self, object_path: str, uuid: str, port: int, ok: Callable[[], None], err: Callable[ [Union[BluezDBusException, NMConnectionError, GLib.Error, str]], None] ) -> None: if uuid == '00000000-0000-0000-0000-000000000000': device = Device(obj_path=object_path) device.disconnect(reply_handler=ok, error_handler=err) else: def cb(_inst, ret): if ret: raise StopException service = get_service(Device(obj_path=object_path), uuid) assert service is not None if isinstance( service, SerialService ) and 'NMDUNSupport' in self.parent.Plugins.get_loaded(): self.parent.Plugins.run_ex("service_disconnect_handler", cb, service, ok, err) elif isinstance( service, SerialService ) and 'PPPSupport' in self.parent.Plugins.get_loaded(): service.disconnect(port, reply_handler=ok, error_handler=err) self.parent.Plugins.run("on_rfcomm_disconnect", port) logging.info("Disconnecting rfcomm device") else: if not self.parent.Plugins.run_ex("service_disconnect_handler", cb, service, ok, err) \ and isinstance(service, NetworkService): service.disconnect(reply_handler=ok, error_handler=err)
def connect_service(self, object_path, uuid, ok, err): try: self.parent.Plugins.RecentConns except KeyError: logging.warning("RecentConns plugin is unavailable") else: self.parent.Plugins.RecentConns.notify(object_path, uuid) if uuid == '00000000-0000-0000-0000-000000000000': device = Device(object_path) device.connect(reply_handler=ok, error_handler=err) else: service = get_service(Device(object_path), uuid) if service.group == 'serial': def reply(rfcomm): self.parent.Plugins.run("on_rfcomm_connected", service, rfcomm) ok(rfcomm) rets = self.parent.Plugins.run("rfcomm_connect_handler", service, reply, err) if True in rets: pass else: logging.info("No handler registered") err(dbus.DBusException( "Service not supported\nPossibly the plugin that handles this service is not loaded")) else: def cb(_inst, ret): if ret: raise StopException if not self.parent.Plugins.run_ex("service_connect_handler", cb, service, ok, err): service.connect(reply_handler=ok, error_handler=err)
def connect_service(self, object_path: str, uuid: str, ok: Callable[[], None], err: Callable[[Union[BluezDBusException, NMConnectionError, RFCOMMError, GLib.Error, str]], None]) -> None: try: self.parent.Plugins.RecentConns except KeyError: logging.warning("RecentConns plugin is unavailable") else: self.parent.Plugins.RecentConns.notify(object_path, uuid) if uuid == '00000000-0000-0000-0000-000000000000': device = Device(obj_path=object_path) device.connect(reply_handler=ok, error_handler=err) else: service = get_service(Device(obj_path=object_path), uuid) assert service is not None if any(plugin.service_connect_handler(service, ok, err) for plugin in self.parent.Plugins.get_loaded_plugins(ServiceConnectHandler)): pass elif isinstance(service, SerialService): def reply(rfcomm: str) -> None: assert isinstance(service, SerialService) # https://github.com/python/mypy/issues/2608 for plugin in self.parent.Plugins.get_loaded_plugins(RFCOMMConnectedListener): plugin.on_rfcomm_connected(service, rfcomm) ok() if not any(plugin.rfcomm_connect_handler(service, reply, err) for plugin in self.parent.Plugins.get_loaded_plugins(RFCOMMConnectHandler)): service.connect(reply_handler=lambda port: ok(), error_handler=err) elif isinstance(service, NetworkService): service.connect(reply_handler=lambda interface: ok(), error_handler=err) else: logging.info("No handler registered") err("Service not supported\nPossibly the plugin that handles this service is not loaded")
def connect_service(self, object_path, uuid, ok, err): try: self.Applet.Plugins.RecentConns except KeyError: logging.warning("RecentConns plugin is unavailable") else: self.Applet.Plugins.RecentConns.notify(object_path, uuid) if uuid == '00000000-0000-0000-0000-000000000000': device = Device(object_path) device.connect(reply_handler=ok, error_handler=err) else: service = get_service(Device(object_path), uuid) if service.group == 'serial': def reply(rfcomm): self.Applet.Plugins.Run("on_rfcomm_connected", service, rfcomm) ok(rfcomm) rets = self.Applet.Plugins.Run("rfcomm_connect_handler", service, reply, err) if True in rets: pass else: logging.info("No handler registered") err(dbus.DBusException( "Service not supported\nPossibly the plugin that handles this service is not loaded")) else: def cb(_inst, ret): if ret: raise StopException if not self.Applet.Plugins.RunEx("service_connect_handler", cb, service, ok, err): service.connect(reply_handler=ok, error_handler=err)
def _disconnect_service(self, object_path, uuid, port, ok, err): if uuid == '00000000-0000-0000-0000-000000000000': device = Device(object_path) device.disconnect(reply_handler=ok, error_handler=err) else: def cb(_inst, ret): if ret: raise StopException service = get_service(Device(object_path), uuid) if service.group == 'serial' and 'NMDUNSupport' in self.parent.Plugins.get_loaded( ): self.parent.Plugins.run_ex("service_disconnect_handler", cb, service, ok, err) elif service.group == 'serial' and 'PPPSupport' in self.parent.Plugins.get_loaded( ): service.disconnect(port, reply_handler=ok, error_handler=err) self.parent.Plugins.run("on_rfcomm_disconnect", port) logging.info("Disconnecting rfcomm device") else: if not self.parent.Plugins.run_ex("service_disconnect_handler", cb, service, ok, err): service.disconnect(reply_handler=ok, error_handler=err)
def _on_display_pin_code(self, device: str, pin_code: str) -> None: logging.info(f'DisplayPinCode ({device}, {pin_code})') dev = Device(obj_path=device) self._devhandlerids[device] = dev.connect_signal("property-changed", self._on_device_property_changed) notify_message = _("Pairing PIN code for") + f" {self.get_device_string(device)}: {pin_code}" self._notification = Notification("Bluetooth", notify_message, 0, icon_name="blueman") self._notification.show()
def _on_display_pin_code(self, device, pin_code): logging.info('DisplayPinCode (%s, %s)' % (device, pin_code)) dev = Device(obj_path=device) self._devhandlerids[device] = dev.connect_signal("property-changed", self._on_device_property_changed) notify_message = _("Pairing PIN code for") + " %s: %s" % (self.get_device_string(device), pin_code) self.n = Notification("Bluetooth", notify_message, 0, icon_name="blueman") self.n.show()
def on_auth_action(action): logging.info(action) if action == "always": device = Device(obj_path=n._device) device.set("Trusted", True) if action == "always" or action == "accept": ok() else: err(BluezErrorRejected("Rejected"))
def _on_display_passkey(self, device: str, passkey: int, entered: int) -> None: logging.info(f"DisplayPasskey ({device}, {passkey:d} {entered:d})") dev = Device(obj_path=device) self._devhandlerids[device] = dev.connect_signal("property-changed", self._on_device_property_changed) key = f"{passkey:06}" notify_message = _("Pairing passkey for") + f" {self.get_device_string(device)}: " \ f"{key[:entered]}<b>{key[entered]}</b>{key[entered+1:]}" self._close() self._notification = Notification("Bluetooth", notify_message, 0, icon_name="blueman") self._notification.show()
def list_devices(self): if self.__class__.get_interface_version()[0] < 5: devices = self.get_interface().ListDevices() return [Device(device) for device in devices] else: objects = self.manager_interface.GetManagedObjects() devices = [] for path, interfaces in objects.items(): if 'org.bluez.Device1' in interfaces: devices.append(path) return [Device(device) for device in devices]
def connect_service( self, object_path: str, uuid: str, ok: Callable[[], None], err: Callable[[ Union[BluezDBusException, NMConnectionError, RFCOMMError, GLib.Error, str] ], None] ) -> None: try: self.parent.Plugins.RecentConns except KeyError: logging.warning("RecentConns plugin is unavailable") else: self.parent.Plugins.RecentConns.notify(object_path, uuid) if uuid == '00000000-0000-0000-0000-000000000000': device = Device(obj_path=object_path) device.connect(reply_handler=ok, error_handler=err) else: def cb(_inst, ret): if ret: raise StopException service = get_service(Device(obj_path=object_path), uuid) assert service is not None if isinstance( service, SerialService ) and 'NMDUNSupport' in self.parent.Plugins.get_loaded(): self.parent.Plugins.run_ex("service_connect_handler", cb, service, ok, err) elif isinstance( service, SerialService ) and 'PPPSupport' in self.parent.Plugins.get_loaded(): def reply(rfcomm): self.parent.Plugins.run("on_rfcomm_connected", service, rfcomm) ok() rets = self.parent.Plugins.run("rfcomm_connect_handler", service, reply, err) if True in rets: pass else: logging.info("No handler registered") err("Service not supported\nPossibly the plugin that handles this service is not loaded" ) else: if not self.parent.Plugins.run_ex("service_connect_handler", cb, service, ok, err) \ and isinstance(service, (SerialService, NetworkService)): service.connect(reply_handler=lambda *args: ok(), error_handler=err)
def _on_display_passkey(self, device, passkey, _entered): logging.info('DisplayPasskey (%s, %d)' % (device, passkey)) dev = Device(device) dev.connect_signal("property-changed", self._on_device_property_changed) notify_message = _("Pairing passkey for") + " %s: %s" % ( self.get_device_string(device), passkey) self.n = Notification("Bluetooth", notify_message, 0, icon_name="blueman") self.n.show()
def _on_display_passkey(self, device, passkey, _entered): logging.info(f"DisplayPasskey ({device}, {passkey:d})") dev = Device(obj_path=device) self._devhandlerids[device] = dev.connect_signal( "property-changed", self._on_device_property_changed) notify_message = _("Pairing passkey for" ) + f" {self.get_device_string(device)}: {passkey}" self.n = Notification("Bluetooth", notify_message, 0, icon_name="blueman") self.n.show()
def create_paired_device(self, address, agent_path, capability, error_handler=None, reply_handler=None, timeout=120): # BlueZ 4 only! def reply_handler_wrapper(obj_path): if not callable(reply_handler): return reply_handler(Device(obj_path)) def error_handler_wrapper(exception): exception = parse_dbus_error(exception) if not callable(error_handler): raise exception error_handler(exception) if reply_handler is None and error_handler is None: obj_path = self.get_interface().CreatePairedDevice( address, agent_path, capability) return Device(obj_path) else: self.get_interface().CreatePairedDevice( address, agent_path, capability, reply_handler=reply_handler_wrapper, error_handler=error_handler_wrapper, timeout=timeout)
def notify(self, object_path: str, uuid: str) -> None: device = Device(obj_path=object_path) logging.info(f"{device} {uuid}") try: adapter = self.parent.Manager.get_adapter(device['Adapter']) except DBusNoSuchAdapterError: logging.warning("adapter not found") return item: "Item" = { "adapter": adapter["Address"], "address": device['Address'], "alias": device['Alias'], "icon": device['Icon'], "name": ServiceUUID(uuid).name, "uuid": uuid, "time": time.time(), "device": object_path, "mitem": None } for i in self.items: if i["adapter"] == item["adapter"] and \ i["address"] == item["address"] and \ i["uuid"] == item["uuid"]: i["time"] = item["time"] i["device"] = item["device"] self.initialize() return self.items.append(item) self.initialize() self._store_state()
def notify(self, object_path, uuid): device = Device(obj_path=object_path) logging.info(f"{device} {uuid}") item = {} try: adapter = self.parent.Manager.get_adapter(device['Adapter']) except DBusNoSuchAdapterError: logging.warning("adapter not found") return item["adapter"] = adapter["Address"] item["address"] = device['Address'] item["alias"] = device['Alias'] item["icon"] = device['Icon'] item["name"] = ServiceUUID(uuid).name item["uuid"] = uuid item["time"] = time.time() item["device"] = object_path item["mitem"] = None # menu item object for i in self.items: if i["adapter"] == item["adapter"] and \ i["address"] == item["address"] and \ i["uuid"] == item["uuid"]: i["time"] = item["time"] i["device"] = item["device"] self.initialize() return self.items.append(item) self.initialize() self.store_state()
def notify(self, object_path, uuid): device = Device(object_path) logging.info("%s %s" % (device, uuid)) item = {} try: adapter = Adapter(device['Adapter']) except: logging.warning("adapter not found") return item["adapter"] = adapter["Address"] item["address"] = device['Address'] item["alias"] = device['Alias'] item["icon"] = device['Icon'] item["name"] = ServiceUUID(uuid).name item["uuid"] = uuid item["time"] = time.time() item["device"] = object_path item["mitem"] = None #menu item object for i in self.items: if i["adapter"] == item["adapter"] and \ i["address"] == item["address"] and \ i["uuid"] == item["uuid"]: i["time"] = item["time"] i["device"] = item["device"] self.initialize() return self.items.append(item) self.initialize() self.store_state()
def disconnect_service(self, device: Device, uuid: str = GENERIC_CONNECT, port: int = 0) -> None: def ok(_obj: AppletService, _result: None, _user_date: None) -> None: logging.info("disconnect success") self.generate() def err(_obj: Optional[AppletService], result: GLib.Error, _user_date: None) -> None: logging.warning(f"disconnect failed {result}") msg, tb = e_(result.message) MessageArea.show_message(_("Disconnection Failed: ") + msg, tb) self.generate() if self._appl is None: err(None, GLib.Error('Applet DBus Service not available'), None) return self._appl.DisconnectService('(osd)', device.get_object_path(), uuid, port, result_handler=ok, error_handler=err, timeout=GLib.MAXINT)
def list_devices(self): objects = self.manager_interface.GetManagedObjects() devices = [] for path, interfaces in objects.items(): if 'org.bluez.Device1' in interfaces: devices.append(path) return [Device(device) for device in devices]
def __init__(self, instance): GObject.GObject.__init__(self) self.Properties = {} self.Temp = False if hasattr(instance, "format") and hasattr(instance, "upper"): self.Device = BluezDevice(instance) else: self.Device = instance #set fallback icon, fixes lp:#327718 self.Device.Icon = "blueman" self.Device.Class = "unknown" self.Valid = True dprint("caching initial properties") self.Properties = self.Device.get_properties() w = weakref.ref(self) self._obj_path = self.Device.get_object_path() self.Device.connect_signal('property-changed', lambda _device, key, value: w() and w().property_changed(key, value)) self._any_adapter = Adapter() self._any_adapter.connect_signal('device-removed', lambda _adapter, path: w() and w().on_device_removed(path))
def notify(self, object_path: str, uuid: str) -> None: device = Device(obj_path=object_path) logging.info(f"{device} {uuid}") try: adapter = self.parent.Manager.get_adapter(device['Adapter']) except DBusNoSuchAdapterError: logging.warning("adapter not found") return item = { "adapter": adapter["Address"], "address": device['Address'], "alias": device['Alias'], "icon": device['Icon'], "name": ServiceUUID(uuid).name, "uuid": uuid, "time": str(time.time()), } stored_items = self.get_option("recent-connections") for i in stored_items: if i["adapter"] == item["adapter"] and \ i["address"] == item["address"] and \ i["uuid"] == item["uuid"]: i["time"] = item["time"] i["device"] = object_path break else: stored_items.append(item) self.set_option("recent-connections", stored_items) self._rebuild()
def __on_manager_signal(self, manager, path, signal_name): if signal_name == 'adapter-removed': self.emit("adapter-removed", path) if path == self.__adapter_path: self.clear() self.Adapter = None self.set_adapter() if signal_name == 'adapter-added': if self.Adapter is None: self.set_adapter(path) self.emit("adapter-added", path) if signal_name == 'device-created': tree_iter = self.find_device_by_path(path) if tree_iter is None: dev = Device(obj_path=path) self.device_add_event(dev) if signal_name == 'device-removed': tree_iter = self.find_device_by_path(path) if tree_iter: row = self.get(tree_iter, "device") dev = row["device"] self.device_remove_event(dev)
def on_device_property_changed(self, path: str, key: str, value: Any) -> None: if key == "ServicesResolved" and value: device = Device(obj_path=path) if self.applicable(device): text = "%d%%" % BluezBattery(obj_path=path)["Percentage"] Notification(device["Alias"], text, icon_name="battery").show()
def set_op(self, device: Device, message: str) -> None: ManagerDeviceMenu.__ops__[device.get_object_path()] = message for inst in ManagerDeviceMenu.__instances__: logging.info(f"op: regenerating instance {inst}") if inst.SelectedDevice == self.SelectedDevice and not ( inst.is_popup and not inst.props.visible): inst.generate()
def generic_connect(self, _item: Optional[Gtk.MenuItem], device: Device, connect: bool) -> None: def fail(_obj: AppletService, result: GLib.Error, _user_data: None) -> None: logging.info(f"fail: {result}") prog.message(_("Failed")) self.unset_op(device) self._handle_error_message(result.message) def success(_obj: AppletService, _result: None, _user_data: None) -> None: logging.info("success") prog.message(_("Success!")) MessageArea.close() self.unset_op(device) assert self._appl if connect: self.set_op(self.SelectedDevice, _("Connecting…")) self._appl.ConnectService("(os)", device.get_object_path(), '00000000-0000-0000-0000-000000000000', result_handler=success, error_handler=fail, timeout=GLib.MAXINT) else: self.set_op(self.SelectedDevice, _("Disconnecting…")) self._appl.DisconnectService( "(osd)", device.get_object_path(), '00000000-0000-0000-0000-000000000000', 0, result_handler=success, error_handler=fail, timeout=GLib.MAXINT) prog = ManagerProgressbar(self.Blueman) def abort() -> None: assert self._appl is not None # https://github.com/python/mypy/issues/2608 self._appl.DisconnectService( "(osd)", device.get_object_path(), '00000000-0000-0000-0000-000000000000', 0) prog.connect("cancelled", lambda x: abort()) prog.start()
def on_device_property_changed(self, path: str, key: str, value: Any) -> None: if key == "Connected": device = Device(obj_path=path) if value and "Battery" in self.parent.Plugins.get_loaded() and Battery.applicable(device): return Notification(device["Alias"], _("Connected") if value else _("Disconnected"), icon_name=device["Icon"]).show()
def list_devices(self): objects = self._call('GetManagedObjects', interface=self.manager_interface) devices = [] for path, interfaces in objects.items(): if 'org.bluez.Device1' in interfaces: if path.startswith(self.get_object_path()): devices.append(path) return [Device(device) for device in devices]
def on_device_property_changed(self, path, key, value): if key == "Connected": klass = Device(path)["Class"] & 0x1fff if klass == 0x504 or klass == 0x508: if value: self.xdg_screensaver("suspend") else: self.xdg_screensaver("resume")
def DisconnectDevice(self, obj_path, ok, err): dev = Device(BluezDevice(obj_path)) self.Applet.Plugins.Run("on_device_disconnect", dev) def on_timeout(): dev.Device.disconnect(reply_handler=ok, error_handler=err) GLib.timeout_add(1000, on_timeout)
def disconnect_service(self, object_path, uuid, port, ok, err): if uuid == '00000000-0000-0000-0000-000000000000': device = Device(object_path) device.disconnect(reply_handler=ok, error_handler=err) else: service = get_service(Device(object_path), uuid) if service.group == 'serial': service.disconnect(port) self.Applet.Plugins.Run("on_rfcomm_disconnect", port) logging.info("Disonnecting rfcomm device") else: def cb(_inst, ret): if ret: raise StopException if not self.Applet.Plugins.RunEx("service_disconnect_handler", cb, service, ok, err): service.disconnect(reply_handler=ok, error_handler=err)
def __init__(self, blueman): GObject.GObject.__init__(self) self.Blueman = blueman self.SelectedDevice = None self.is_popup = False self._device_property_changed_signal = self.Blueman.List.connect("device-property-changed", self.on_device_property_changed) self._selection_done_signal = None ManagerDeviceMenu.__instances__.append(self) self._any_network = Network() self._any_network.connect_signal('property-changed', self._on_service_property_changed) self._any_device = Device() self._any_device.connect_signal('property-changed', self._on_service_property_changed) self.Generate()
def __init__(self, instance): GObject.GObject.__init__(self) self.Properties = {} self.Fake = True self.Temp = False if isinstance(instance, str) or isinstance(instance, unicode): self.Device = BluezDevice(instance) else: self.Device = instance #set fallback icon, fixes lp:#327718 self.Device.Icon = "blueman" self.Device.Class = "unknown" self.__services = {} self.Valid = True self.Signals = SignalTracker() dprint("caching initial properties") self.Properties = self.Device.get_properties() if not "Fake" in self.Properties: self.Fake = False w = weakref.ref(self) if not self.Fake: self._obj_path = self.Device.get_object_path() self.Signals.Handle("bluez", self.Device, lambda key, value: w() and w().property_changed(key, value), "PropertyChanged") object_path = self.Device.get_object_path() adapter = Adapter(object_path.replace("/" + os.path.basename(object_path), "")) self.Signals.Handle("bluez", adapter, lambda path: w() and w().on_device_removed(path), "DeviceRemoved")
class ManagerDeviceMenu(Gtk.Menu): __ops__ = {} __instances__ = [] def __init__(self, blueman): Gtk.Menu.__init__(self) self.set_name("ManagerDeviceMenu") self.Blueman = blueman self.SelectedDevice = None self.is_popup = False self._device_property_changed_signal = self.Blueman.List.connect("device-property-changed", self.on_device_property_changed) self._selection_done_signal = None ManagerDeviceMenu.__instances__.append(self) self._any_network = Network() self._any_network.connect_signal('property-changed', self._on_service_property_changed) self._any_device = Device() self._any_device.connect_signal('property-changed', self._on_service_property_changed) self.Generate() def __del__(self): dprint("deleting devicemenu") def popup(self, *args): self.is_popup = True if not self._device_property_changed_signal: self._device_property_changed_signal = self.Blueman.List.connect("device-property-changed", self.on_device_property_changed) if not self._selection_done_signal: def disconnectall(x): self.disconnect(self._device_property_changed_signal) self.disconnect(self._selection_done_signal) self._selection_done_signal = self.connect("selection-done", disconnectall) self.Generate() Gtk.Menu.popup(self, *args) def clear(self): def each(child, data): self.remove(child) child.destroy() self.foreach(each, None) def set_op(self, device, message): ManagerDeviceMenu.__ops__[device.get_object_path()] = message for inst in ManagerDeviceMenu.__instances__: dprint("op: regenerating instance", inst) if inst.SelectedDevice == self.SelectedDevice and not (inst.is_popup and not inst.props.visible): inst.Generate() def get_op(self, device): try: return ManagerDeviceMenu.__ops__[device.get_object_path()] except: return None def unset_op(self, device): del ManagerDeviceMenu.__ops__[device.get_object_path()] for inst in ManagerDeviceMenu.__instances__: dprint("op: regenerating instance", inst) if inst.SelectedDevice == self.SelectedDevice and not (inst.is_popup and not inst.props.visible): inst.Generate() def _on_service_property_changed(self, _service, key, _value, _path): if key == "Connected": self.Generate() def on_connect(self, _item, service): device = service.device def success(*args2): dprint("success", " ".join(args2)) prog.message(_("Success!")) if isinstance(service, SerialPort) and SERIAL_PORT_SVCLASS_ID == uuid128_to_uuid16(service.uuid): MessageArea.show_message(_("Serial port connected to %s") % args2[0], "dialog-information") else: MessageArea.close() self.unset_op(device) def fail(*args): prog.message(_("Failed")) self.unset_op(device) dprint("fail", args) MessageArea.show_message(_("Connection Failed: ") + e_(str(args[0]))) self.set_op(device, _("Connecting...")) prog = ManagerProgressbar(self.Blueman, False) try: appl = AppletService() except: dprint("** Failed to connect to applet") fail() return try: appl.SetTimeHint(Gtk.get_current_event_time()) except: pass appl.connect_service(device.get_object_path(), service.uuid, reply_handler=success, error_handler=fail, timeout=200) prog.start() def on_disconnect(self, item, service, port=0): try: appl = AppletService() except: dprint("** Failed to connect to applet") return appl.disconnect_service(service.device.get_object_path(), service.uuid, port) self.Generate() def on_device_property_changed(self, List, device, iter, key_value): key, value = key_value # print "menu:", key, value if List.compare(iter, List.selected()): if key == "Connected" \ or key == "UUIDs" \ or key == "Trusted" \ or key == "Paired": self.Generate() def Generate(self): self.clear() appl = AppletService() items = [] if not self.is_popup or self.props.visible: selected = self.Blueman.List.selected() if not selected: return device = self.Blueman.List.get(selected, "device")["device"] else: (x, y) = self.Blueman.List.get_pointer() path = self.Blueman.List.get_path_at_pos(x, y) if path != None: device = self.Blueman.List.get(path[0], "device")["device"] else: return if not device.Valid: return self.SelectedDevice = device op = self.get_op(device) if op != None: item = create_menuitem(op, get_icon("network-transmit-recieve", 16)) item.props.sensitive = False item.show() self.append(item) return rets = self.Blueman.Plugins.Run("on_request_menu_items", self, device) for ret in rets: if ret: for (item, pos) in ret: items.append((pos, item)) dprint(device.Alias) have_disconnectables = False have_connectables = False if True in map(lambda x: x[0] >= 100 and x[0] < 200, items): have_disconnectables = True if True in map(lambda x: x[0] < 100, items): have_connectables = True if True in map(lambda x: x[0] >= 200, items) and (have_connectables or have_disconnectables): item = Gtk.SeparatorMenuItem() item.show() items.append((199, item)) if have_connectables: item = Gtk.MenuItem() label = Gtk.Label() label.set_markup(_("<b>Connect To:</b>")) label.props.xalign = 0.0 label.show() item.add(label) item.props.sensitive = False item.show() items.append((0, item)) if have_disconnectables: item = Gtk.MenuItem() label = Gtk.Label() label.set_markup(_("<b>Disconnect:</b>")) label.props.xalign = 0.0 label.show() item.add(label) item.props.sensitive = False item.show() items.append((99, item)) items.sort(key=itemgetter(0)) for priority, item in items: self.append(item) if items != []: item = Gtk.SeparatorMenuItem() item.show() self.append(item) del items send_item = create_menuitem(_("Send a _File..."), get_icon("edit-copy", 16)) send_item.props.sensitive = False self.append(send_item) send_item.show() uuids = device.UUIDs for uuid in uuids: uuid16 = uuid128_to_uuid16(uuid) if uuid16 == OBEX_OBJPUSH_SVCLASS_ID: send_item.connect("activate", lambda x: self.Blueman.send(device)) send_item.props.sensitive = True item = Gtk.SeparatorMenuItem() item.show() self.append(item) item = create_menuitem(_("_Pair"), get_icon("dialog-password", 16)) item.props.tooltip_text = _("Create pairing with the device") self.append(item) item.show() if not device.Paired: item.connect("activate", lambda x: self.Blueman.bond(device)) else: item.props.sensitive = False if not device.Trusted: item = create_menuitem(_("_Trust"), get_icon("blueman-trust", 16)) item.connect("activate", lambda x: self.Blueman.toggle_trust(device)) self.append(item) item.show() else: item = create_menuitem(_("_Untrust"), get_icon("blueman-untrust", 16)) self.append(item) item.connect("activate", lambda x: self.Blueman.toggle_trust(device)) item.show() item.props.tooltip_text = _("Mark/Unmark this device as trusted") item = create_menuitem(_("_Setup..."), get_icon("document-properties", 16)) self.append(item) item.connect("activate", lambda x: self.Blueman.setup(device)) item.show() item.props.tooltip_text = _("Run the setup assistant for this device") def on_rename(_item, device): def on_response(dialog, response_id): if response_id == Gtk.ResponseType.ACCEPT: device.set('Alias', alias_entry.get_text()) elif response_id == 1: device.set('Alias', '') dialog.destroy() builder = Gtk.Builder() builder.set_translation_domain("blueman") bind_textdomain_codeset("blueman", "UTF-8") builder.add_from_file(UI_PATH + "/rename-device.ui") dialog = builder.get_object("dialog") dialog.set_transient_for(self.Blueman.window) dialog.props.icon_name = "blueman" alias_entry = builder.get_object("alias_entry") alias_entry.set_text(device.Alias) dialog.connect("response", on_response) dialog.present() item = Gtk.MenuItem.new_with_label("Rename device...") item.connect('activate', on_rename, device) self.append(item) item.show() item = Gtk.SeparatorMenuItem() item.show() self.append(item) item = create_menuitem(_("_Remove..."), get_icon("edit-delete", 16)) item.connect("activate", lambda x: self.Blueman.remove(device)) self.append(item) item.show() item.props.tooltip_text = _("Remove this device from the known devices list") item = Gtk.SeparatorMenuItem() item.show() self.append(item) item = create_menuitem(_("_Disconnect"), get_icon("network-offline", 16)) item.props.tooltip_text = _("Forcefully disconnect the device") self.append(item) item.show() def on_disconnect(item): def finished(*args): self.unset_op(device) self.set_op(device, _("Disconnecting...")) self.Blueman.disconnect(device, reply_handler=finished, error_handler=finished) if device.Connected: item.connect("activate", on_disconnect) else: item.props.sensitive = False
class Device(GObject.GObject): __gsignals__ = { str('invalidated'): (GObject.SignalFlags.NO_HOOKS, None, ()), str('property-changed'): (GObject.SignalFlags.NO_HOOKS, None, (GObject.TYPE_PYOBJECT, GObject.TYPE_PYOBJECT,)), } def __init__(self, instance): GObject.GObject.__init__(self) self.Properties = {} self.Temp = False if hasattr(instance, "format") and hasattr(instance, "upper"): self.Device = BluezDevice(instance) else: self.Device = instance #set fallback icon, fixes lp:#327718 self.Device.Icon = "blueman" self.Device.Class = "unknown" self.Valid = True dprint("caching initial properties") self.Properties = self.Device.get_properties() w = weakref.ref(self) self._obj_path = self.Device.get_object_path() self.Device.connect_signal('property-changed', lambda _device, key, value: w() and w().property_changed(key, value)) self._any_adapter = Adapter() self._any_adapter.connect_signal('device-removed', lambda _adapter, path: w() and w().on_device_removed(path)) def get_service(self, uuid): for name, cls in inspect.getmembers(blueman.services, inspect.isclass): if uuid128_to_uuid16(uuid) == cls.__svclass_id__: return cls(self, uuid) def get_services(self): services = (self.get_service(uuid) for uuid in self.UUIDs) return [service for service in services if service] def __del__(self): dprint("deleting device", self.get_object_path()) self.Destroy() def get_object_path(self): return self._obj_path def on_device_removed(self, path): if path == self._obj_path: self.emit("invalidated") self.Destroy() def Copy(self): if not self.Valid: raise Exception("Attempted to copy an invalidated device") return Device(self.Device) def property_changed(self, key, value): self.emit("property-changed", key, value) self.Properties[key] = value def Destroy(self): dprint("invalidating device", self.get_object_path()) self.Valid = False #self.Device = None #def __del__(self): # dprint("DEBUG: deleting Device instance") def get_properties(self): #print "Properties requested" if not self.Valid: raise Exception("Attempted to get properties for an invalidated device") return self.Properties def __getattr__(self, name): if name in self.__dict__["Properties"]: if not self.Valid: #traceback.print_stack() dprint("Warning: Attempted to get %s property for an invalidated device" % name) return self.__dict__["Properties"][name] else: return getattr(self.Device, name) def __setattr__(self, key, value): if not key in self.__dict__ and "Properties" in self.__dict__ and key in self.__dict__["Properties"]: if not self.Valid: raise Exception("Attempted to set properties for an invalidated device") dprint("Setting property", key, value) self.__dict__["Device"].set(key, value) else: self.__dict__[key] = value
class Device(GObject.GObject): __gsignals__ = { 'invalidated': (GObject.SignalFlags.NO_HOOKS, None, ()), 'property-changed': (GObject.SignalFlags.NO_HOOKS, None, (GObject.TYPE_PYOBJECT, GObject.TYPE_PYOBJECT,)), } def __init__(self, instance): GObject.GObject.__init__(self) self.Properties = {} self.Fake = True self.Temp = False if isinstance(instance, str) or isinstance(instance, unicode): self.Device = BluezDevice(instance) else: self.Device = instance #set fallback icon, fixes lp:#327718 self.Device.Icon = "blueman" self.Device.Class = "unknown" self.__services = {} self.Valid = True self.Signals = SignalTracker() dprint("caching initial properties") self.Properties = self.Device.get_properties() if not "Fake" in self.Properties: self.Fake = False w = weakref.ref(self) if not self.Fake: self._obj_path = self.Device.get_object_path() self.Signals.Handle("bluez", self.Device, lambda key, value: w() and w().property_changed(key, value), "PropertyChanged") object_path = self.Device.get_object_path() adapter = Adapter(object_path.replace("/" + os.path.basename(object_path), "")) self.Signals.Handle("bluez", adapter, lambda path: w() and w().on_device_removed(path), "DeviceRemoved") @property def Services(self): if len(self.__services) == 0: self.init_services() return self.__services def __del__(self): dprint("deleting device", self.get_object_path()) self.Destroy() def get_object_path(self): if not self.Fake: return self._obj_path def on_device_removed(self, path): if path == self._obj_path: self.emit("invalidated") self.Destroy() def init_services(self): dprint("Loading services") if not self.Fake: services = self.Device.list_services() self.__services = {} for service in services: name = service.get_interface_name().split(".") if name[0] == 'org' and name[1] == 'bluez': name = name[2].lower() if name.endswith('1'): name = name[:-1] self.__services[name] = service def Copy(self): if not self.Valid: raise Exception("Attempted to copy an invalidated device") return Device(self.Device) def property_changed(self, key, value): self.emit("property-changed", key, value) self.Properties[key] = value if key == "UUIDs": self.init_services() def Destroy(self): dprint("invalidating device", self.get_object_path()) self.Valid = False #self.Device = None self.Signals.DisconnectAll() #def __del__(self): # dprint("DEBUG: deleting Device instance") def get_properties(self): #print "Properties requested" if not self.Valid: raise Exception("Attempted to get properties for an invalidated device") return self.Properties def __getattr__(self, name): if name in self.__dict__["Properties"]: if not self.Valid: #traceback.print_stack() dprint("Warning: Attempted to get %s property for an invalidated device" % name) return self.__dict__["Properties"][name] else: return getattr(self.Device, name) def __setattr__(self, key, value): if not key in self.__dict__ and "Properties" in self.__dict__ and key in self.__dict__["Properties"]: if not self.Valid: raise Exception("Attempted to set properties for an invalidated device") dprint("Setting property", key, value) self.__dict__["Device"].set(key, value) else: self.__dict__[key] = value