예제 #1
0
 def Handle(self, signame, handler):
     SignalTracker.Handle(self,
                          "dbus",
                          self.bus,
                          handler,
                          signame,
                          self.dbus_interface,
                          path=self.object_path)
예제 #2
0
class GameControllerWakelock(AppletPlugin):
    __description__ = _("Temporarily suspends the screensaver when a bluetooth game controller is connected.")
    __author__ = "bwRavencl"
    __icon__ = "input-gaming"

    def on_load(self, applet):
        self.wake_lock = 0
        self.root_window_id = "0x%x" % Gdk.Screen.get_default().get_root_window().get_xid()

        self.signals = SignalTracker()
        self.signals.Handle("bluez", bluez.Device(), self.on_device_property_changed, "PropertyChanged", path_keyword="path")

    def on_unload(self):
        if self.wake_lock:
            self.wake_lock = 1
            self.suspend_screensaver("resume")
        self.signals.DisconnectAll()

    def on_device_property_changed(self, key, value, path):
        if key == "Connected":
            klass = Device(path).get_properties()["Class"] & 0x1fff

            if klass == 0x504 or klass == 0x508:
                if value:
                    self.xdg_screensaver("suspend")
                else:
                    self.xdg_screensaver("resume")

    def xdg_screensaver(self, action):
        if action == "resume":
            if self.wake_lock == 0:
                pass
            elif self.wake_lock > 1:
                self.wake_lock -= 1
                pass
        elif action == "suspend" and self.wake_lock >= 1:
             self.wake_lock += 1
             pass

        command = ["xdg-screensaver", action, self.root_window_id]

        try:
            process = subprocess.Popen(command, stderr=subprocess.PIPE)
            _, stderr = process.communicate()

            if process.returncode != 0:
                dprint(" ".join(command) + " failed with: " + stderr)
                pass

            if action == "suspend":
                self.wake_lock += 1
            elif action == "resume":
                self.wake_lock = 0
        except:
            dprint(traceback.format_exc())
예제 #3
0
class NMMonitor(MonitorBase):
    def __init__(self, device, nm_dev_path):
        MonitorBase.__init__(self, device, "NM")
        dprint("created nm monitor for path", nm_dev_path)
        self.signals = SignalTracker()
        self.signals.Handle("dbus",
                            dbus.SystemBus(),
                            self.on_ppp_stats,
                            "PppStats",
                            "org.freedesktop.NetworkManager.Device.Serial",
                            path=nm_dev_path)

        self.signals.Handle(device, "property-changed", self.on_device_property_changed)

    def on_ppp_stats(self, rx, tx):
        self.update_stats(tx, rx)

    def on_device_property_changed(self, device, key, value):
        if key == "Connected" and not value:
            self.signals.DisconnectAll()
            self.Disconnect()
예제 #4
0
class NewConnectionBuilder:
    DEVICE_STATE_DISCONNECTED = 30
    DEVICE_STATE_ACTIVATED = 100
    DEVICE_STATE_DEACTIVATING = 110
    DEVICE_STATE_FAILED = 120

    def __init__(self, parent, service, ok_cb, err_cb):
        self.parent = parent
        self.ok_cb = ok_cb
        self.err_cb = err_cb

        self.signals = SignalTracker()

        self.device = None
        self.connection = None

        self.signals.Handle("dbus", parent.bus, self.on_nm_device_added,
                            "DeviceAdded", "org.freedesktop.NetworkManager")
        self.signals.Handle("dbus", parent.bus, self.on_nma_new_connection,
                            "NewConnection", self.parent.settings_interface)

        self.device = self.parent.find_device(service.device.Address)

        self.connection = self.parent.find_connection(service.device.Address,
                                                      "panu")
        if not self.connection:
            # This is for compatibility with network-manager < 0.9.8.6. Newer versions that support BlueZ 5 add a
            # default connection automatically
            addr_bytes = bytearray.fromhex(
                str.replace(str(service.device.Address), ':', ' '))
            parent.nma.AddConnection({
                'connection': {
                    'id': '%s on %s' % (service.name, service.device.Alias),
                    'uuid': str(uuid1()),
                    'autoconnect': False,
                    'type': 'bluetooth'
                },
                'bluetooth': {
                    'bdaddr': dbus.ByteArray(addr_bytes),
                    'type': 'panu'
                },
                'ipv4': {
                    'method': 'auto'
                },
                'ipv6': {
                    'method': 'auto'
                }
            })
            GObject.timeout_add(1000, self.signal_wait_timeout)
        else:
            self.init_connection()

    def cleanup(self):
        self.signals.DisconnectAll()

    def signal_wait_timeout(self):
        if not self.device or not self.connection:
            self.err_cb(
                dbus.DBusException(
                    "Network Manager did not support the connection"))
            if self.connection:
                self.remove_connection()
            self.cleanup()

    def on_nm_device_added(self, path):
        dprint(path)
        self.device = path
        if self.device and self.connection:
            self.init_connection()

    def on_nma_new_connection(self, path):
        dprint(path)
        self.connection = path
        if self.device and self.connection:
            self.init_connection()

    def init_connection(self):
        self.cleanup()
        dprint("activating", self.connection, self.device)
        if not self.device or not self.connection:
            self.err_cb(
                dbus.DBusException(
                    "Network Manager did not support the connection"))
            if self.connection:
                self.remove_connection()
            self.cleanup()
        else:
            self.signals.Handle("dbus",
                                self.parent.bus,
                                self.on_device_state,
                                "StateChanged",
                                "org.freedesktop.NetworkManager.Device",
                                path=self.device)

            args = [self.connection, self.device, self.connection]

            if self.parent.legacy:
                args.insert(0, self.parent.settings_bus)

            self.parent.nm.ActivateConnection(*args)

    def remove_connection(self):
        self.parent.remove_connection(self.connection)

    def on_device_state(self, state, oldstate, reason):
        dprint("state=", state, "oldstate=", oldstate, "reason=", reason)
        if (state <= self.DEVICE_STATE_DISCONNECTED or state == self.DEVICE_STATE_DEACTIVATING) and \
                                self.DEVICE_STATE_DISCONNECTED < oldstate <= self.DEVICE_STATE_ACTIVATED:
            if self.err_cb:
                self.err_cb(dbus.DBusException("Connection was interrupted"))

            self.remove_connection()
            self.cleanup()

        elif state == self.DEVICE_STATE_FAILED:
            self.err_cb(
                dbus.DBusException(
                    "Network Manager Failed to activate the connection"))
            self.remove_connection()
            self.cleanup()

        elif state == self.DEVICE_STATE_ACTIVATED:
            self.ok_cb()
            self.err_cb = None
            self.ok_cb = None
예제 #5
0
class SerialManager(AppletPlugin):
    __icon__ = "blueman-serial"
    __author__ = "Walmis"
    __description__ = _(
        "Standard SPP profile connection handler, allows executing custom actions"
    )
    __author__ = "walmis"
    __options__ = {
        "script": {
            "type":
            str,
            "default":
            "",
            "name":
            _("Script to execute on connection"),
            "desc":
            _("<span size=\"small\">The following arguments will be passed:\n"
              "Address, Name, service name, uuid16s, rfcomm node\n"
              "For example:\n"
              "AA:BB:CC:DD:EE:FF, Phone, DUN service, 0x1103, /dev/rfcomm0\n"
              "uuid16s are returned as a comma seperated list\n\n"
              "Upon device disconnection the script will be sent a HUP signal</span>"
              )
        },
    }

    def on_load(self, applet):
        self.signals = SignalTracker()
        self.signals.Handle("dbus",
                            dbus.SystemBus(),
                            self.on_device_property_changed,
                            "PropertyChanged",
                            "org.bluez.Device",
                            path_keyword="path")

        self.scripts = {}

    def on_unload(self):
        self.signals.DisconnectAll()
        for k in self.scripts.iterkeys():
            self.terminate_all_scripts(k)

    def on_device_property_changed(self, key, value, path):
        if key == "Connected" and not value:
            d = Device(path)
            self.terminate_all_scripts(d.Address)

    def on_rfcomm_connected(self, device, port, uuid):
        uuid16 = sdp_get_serial_type(device.Address, uuid)
        if SERIAL_PORT_SVCLASS_ID in uuid16:
            Notification(
                _("Serial port connected"),
                _("Serial port service on device <b>%s</b> now will be available via <b>%s</b>"
                  ) % (device.Alias, port),
                pixbuf=get_icon("blueman-serial", 48),
                status_icon=self.Applet.Plugins.StatusIcon)

            self.call_script(device.Address, device.Alias,
                             sdp_get_serial_name(device.Address, uuid), uuid16,
                             port)

    def terminate_all_scripts(self, address):
        try:
            for p in self.scripts[address].itervalues():
                dprint("Sending HUP to", p.pid)
                os.killpg(p.pid, signal.SIGHUP)
        except:
            pass

    def on_script_closed(self, pid, cond, (address, node)):
        del self.scripts[address][node]
        dprint("Script with PID", pid, "closed")
예제 #6
0
class PowerManager(AppletPlugin):
    __depends__ = ["StatusIcon", "Menu"]
    __unloadable__ = True
    __description__ = _("Controls Bluetooth adapter power states")
    __author__ = "Walmis"
    __icon__ = "gnome-power-manager"

    def on_load(self, applet):
        AppletPlugin.add_method(self.on_power_state_query)
        AppletPlugin.add_method(self.on_power_state_change_requested)
        AppletPlugin.add_method(self.on_power_state_changed)

        self.add_dbus_method(self.SetBluetoothStatus,
                             in_signature="b",
                             out_signature="")

        self.add_dbus_method(self.GetBluetoothStatus,
                             in_signature="",
                             out_signature="b")

        self.BluetoothStatusChanged = self.add_dbus_signal(
            "BluetoothStatusChanged", signature="b")

        self.Applet = applet

        self.item = create_menuitem(_("<b>Bluetooth Off</b>"),
                                    get_icon("gtk-stop", 16))
        self.item.get_child().set_markup(_("<b>Turn Bluetooth Off</b>"))

        self.item.props.tooltip_text = _("Turn off all adapters")

        self.signals = SignalTracker()
        self.signals.Handle("dbus",
                            dbus.SystemBus(),
                            self.adapter_property_changed,
                            "PropertyChanged",
                            "org.bluez.Adapter",
                            "org.bluez",
                            path_keyword="path")

        self.signals.Handle(self.item, "activate",
                            lambda x: self.on_bluetooth_toggled())

        self.Applet.Plugins.Menu.Register(self, self.item, 0)

        self.adapter_state = True
        self.current_state = True
        self.power_changeable = True

        self.request_in_progress = False

        self.STATE_ON = 2
        self.STATE_OFF = 1
        self.STATE_OFF_FORCED = 0

    def on_unload(self):
        self.signals.DisconnectAll()
        self.Applet.Plugins.Menu.Unregister(self)

    @property
    def CurrentState(self):
        return self.current_state

    def on_manager_state_changed(self, state):
        if state:

            def timeout():
                self.adapter_state = self.get_adapter_state()
                self.RequestPowerState(self.adapter_state)

            gobject.timeout_add(1000, timeout)

    def get_adapter_state(self):
        adapters = self.Applet.Manager.ListAdapters()
        for adapter in adapters:
            props = adapter.GetProperties()
            if not props["Powered"]:
                return False
        return bool(adapters)

    def set_adapter_state(self, state):
        try:
            dprint(state)
            adapters = self.Applet.Manager.ListAdapters()
            for adapter in adapters:
                adapter.SetProperty("Powered", state)

            self.adapter_state = state
        except Exception as e:
            dprint("Exception occurred", e)

    class Callback(object):
        def __init__(self, parent, state):
            self.parent = parent
            self.num_cb = 0
            self.called = 0
            self.state = state
            self.success = False
            self.timer = gobject.timeout_add(5000, self.timeout)

        def __call__(self, result):
            self.called += 1

            if result:
                self.success = True

            self.check()

        def check(self):
            if self.called == self.num_cb:
                dprint("callbacks done")
                self.parent.set_adapter_state(self.state)
                gobject.source_remove(self.timer)
                self.parent.request_in_progress = False

        def timeout(self):
            dprint("Timeout reached while setting power state")
            self.parent.UpdatePowerState()
            self.parent.request_in_progress = False

    def RequestPowerState(self, state):
        if self.current_state != state:
            if not self.request_in_progress:
                self.request_in_progress = True
                dprint("Requesting", state)
                cb = PowerManager.Callback(self, state)

                rets = self.Applet.Plugins.Run(
                    "on_power_state_change_requested", self, state, cb)
                cb.num_cb = len(rets)
                cb.check()
                self.UpdatePowerState()
            else:
                dprint("Another request in progress")

    def on_power_state_change_requested(self, pm, state, cb):
        cb(None)

    def on_power_state_query(self, pm):
        if self.adapter_state:
            return self.STATE_ON
        else:
            return self.STATE_OFF

    def on_power_state_changed(self, manager, state):
        pass

    #queries other plugins to determine the current power state
    def UpdatePowerState(self):
        rets = self.Applet.Plugins.Run("on_power_state_query", self)

        off = True in map(lambda x: x < self.STATE_ON, rets)
        foff = self.STATE_OFF_FORCED in rets
        on = self.STATE_ON in rets

        new_state = True
        if foff or off:

            self.item.get_child().set_markup(_("<b>Turn Bluetooth On</b>"))
            self.item.props.tooltip_text = _("Turn on all adapters")
            self.item.set_image(
                gtk.image_new_from_pixbuf(get_icon("gtk-yes", 16)))

            if foff:
                self.item.props.sensitive = False
            else:
                self.item.props.sensitive = True

            new_state = False

        elif on and self.current_state != True:
            self.item.get_child().set_markup(_("<b>Turn Bluetooth Off</b>"))
            self.item.props.tooltip_text = _("Turn off all adapters")
            self.item.set_image(
                gtk.image_new_from_pixbuf(get_icon("gtk-stop", 16)))
            self.item.props.sensitive = True

            new_state = True

        dprint("off", off, "\nfoff", foff, "\non", on, "\ncurrent state",
               self.current_state, "\nnew state", new_state)

        if self.current_state != new_state:
            dprint("Signalling", new_state)
            self.current_state = new_state

            self.BluetoothStatusChanged(new_state)
            self.Applet.Plugins.Run("on_power_state_changed", self, new_state)
            self.Applet.Plugins.StatusIcon.IconShouldChange()

    #dbus method
    def SetBluetoothStatus(self, status):
        self.RequestPowerState(status)

    #dbus method
    def GetBluetoothStatus(self):
        return self.CurrentState

    def adapter_property_changed(self, key, value, path):
        if key == "Powered":
            if value and not self.CurrentState:
                dprint(
                    "adapter powered on while in off state, turning bluetooth on"
                )
                self.RequestPowerState(True)

            self.UpdatePowerState()

    def on_bluetooth_toggled(self):
        self.RequestPowerState(not self.CurrentState)

    def on_status_icon_query_icon(self):
        #opacity = 255 if self.GetBluetoothStatus() else 100
        #pixbuf = opacify_pixbuf(pixbuf, opacity)

        #if opacity < 255:
        #	x_size = int(pixbuf.props.height)
        #	x = get_icon("blueman-x", x_size)
        #	pixbuf = composite_icon(pixbuf, [(x, pixbuf.props.height - x_size, pixbuf.props.height - x_size, 255)])

        #return pixbuf
        if not self.GetBluetoothStatus():
            return ("blueman-tray-disabled", "bluetooth-disabled")

    def on_adapter_added(self, path):
        adapter = Bluez.Adapter(path)

        def on_ready():
            if not self.adapter_state:
                adapter.SetProperty("Powered", False)
            else:
                adapter.SetProperty("Powered", True)

        wait_for_adapter(adapter, on_ready)
예제 #7
0
class DeviceList(GenericList):
    __gsignals__ = {
        #@param: device
        'device-found': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)),
        #@param: device TreeIter
        #note: None None is given when there ar no more rows, or when selected device is removed
        'device-selected': (
            gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT,)
        ),
        #@param: device, TreeIter, (key, value)
        #note: there is a special property "Fake", it's not a real property,
        #but it is used to notify when device changes state from "Fake" to a real BlueZ object
        #the callback would be called with Fake=False
        'device-property-changed': (
            gobject.SIGNAL_RUN_LAST,
            gobject.TYPE_NONE,
            (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT,)
        ),
        #@param: adapter, (key, value)
        'adapter-property-changed': (
        gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT,)),
        #@param: progress (0 to 1)
        'discovery-progress': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_FLOAT,)),

        #@param: new adapter path, None if there are no more adapters
        'adapter-changed': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)),

        #@param: adapter path
        'adapter-added': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)),
        'adapter-removed': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)),
    }

    def __del__(self):
        dprint("deleting mainlist")

    def __init__(self, adapter=None, tabledata=None):
        if not tabledata:
            tabledata = []

        def on_adapter_removed(path):
            self.emit("adapter-removed", path)
            if path == self.__adapter_path:
                self.clear()
                self.Adapter = None
                self.SetAdapter()

        def on_adapter_added(path):
            def on_activate():
                dprint("adapter powered", path)

                if self.Adapter is None:
                    self.SetAdapter(path)

                self.emit("adapter-added", path)

            a = Bluez.Adapter(path)
            wait_for_adapter(a, on_activate)

        #cache for fast lookup in the list
        self.address_to_row = {}
        self.path_to_row = {}

        self.monitored_devices = []
        self.discovered_devices = []

        self.signals = SignalTracker()

        try:
            self.Manager = Bluez.Manager("gobject")
            self.signals.Handle(self.Manager, on_adapter_removed, "AdapterRemoved")
            self.signals.Handle(self.Manager, on_adapter_added, "AdapterAdded")
        except:
            self.Manager = None

        self.__discovery_time = 0
        self.__adapter_path = None
        self.Adapter = None
        self.discovering = False

        data = []
        data = data + tabledata

        data = data + [
            ["device", object],
            ["dbus_path", str]
        ]

        GenericList.__init__(self, data)
        self.adapter_signals = SignalTracker()
        self.device_signals = SignalTracker()

        self.SetAdapter(adapter)

        self.signals.Handle(self.selection, "changed", self.on_selection_changed)

    def destroy(self):
        dprint("destroying")
        self.adapter_signals.DisconnectAll()
        self.device_signals.DisconnectAll()
        self.signals.DisconnectAll()
        self.device_signals = None
        #self.clear()
        if len(self.liststore):
            for i in self.liststore:
                iter = i.iter
                device = self.get(iter, "device")["device"]
            #device.Destroy()
        GenericList.destroy(self)

    def on_selection_changed(self, selection):
        iter = self.selected()
        if iter:
            row = self.get(iter, "device")
            dev = row["device"]
            self.emit("device-selected", dev, iter)


    def on_device_found(self, address, props):
        if self.discovering:
            dprint("Device discovered", address)

            props["Address"] = address
            props["Fake"] = True
            dev = FakeDevice(props)
            device = Device(dev)

            if not address in self.discovered_devices:
                self.emit("device-found", device)
                self.discovered_devices.append(address)

            iter = self.find_device(dev)
            if not iter:
                self.device_add_event(device)
                iter = self.find_device(device)
                self.row_update_event(iter, "RSSI", props["RSSI"])
            else:
                self.row_update_event(iter, "Alias", props["Alias"])

            print "RSSI:", props["RSSI"]


    def on_property_changed(self, key, value):
        dprint("adapter propery changed", key, value)
        if key == "Discovering":
            if not value and self.discovering:
                self.StopDiscovery()

            self.discovered_devices = []

        self.emit("adapter-property-changed", self.Adapter, (key, value))

    def on_device_property_changed(self, key, value, path, *args, **kwargs):
        dprint("list: device_prop_ch", key, value, path, args, kwargs)

        iter = self.find_device_by_path(path)

        if iter != None:
            dev = self.get(iter, "device")["device"]
            self.row_update_event(iter, key, value)

            self.emit("device-property-changed", dev, iter, (key, value))

            if key == "Connected":
                if value:
                    self.monitor_power_levels(dev)
                else:
                    r = gtk.TreeRowReference(self.props.model, self.props.model.get_path(iter))
                    self.level_setup_event(r, dev, None)

            elif key == "Paired":
                if value and dev.Temp:
                    dev.Temp = False

    def monitor_power_levels(self, device):
        def update(row_ref, cinfo, address):
            if not row_ref.valid():
                dprint("stopping monitor (row does not exist)")
                cinfo.deinit()
                self.monitored_devices.remove(props["Address"])
                return False

            if not self.props.model:
                self.monitored_devices.remove(props["Address"])
                return False

            iter = self.props.model.get_iter(row_ref.get_path())
            device = self.get(iter, "device")["device"]
            if not device.Valid or not device.Connected:
                dprint("stopping monitor (not connected)")
                cinfo.deinit()
                self.level_setup_event(row_ref, device, None)
                self.monitored_devices.remove(props["Address"])
                return False
            else:
                self.level_setup_event(row_ref, device, cinfo)
                return True


        props = device.GetProperties()

        if "Connected" in props and props["Connected"] and props["Address"] not in self.monitored_devices:
            dprint("starting monitor")
            iter = self.find_device(device)

            hci = os.path.basename(self.Adapter.GetObjectPath())
            try:
                cinfo = conn_info(props["Address"], hci)
            except:
                dprint("Failed to get power levels")
            else:
                r = gtk.TreeRowReference(self.props.model, self.props.model.get_path(iter))
                self.level_setup_event(r, device, cinfo)
                gobject.timeout_add(1000, update, r, cinfo, props["Address"])
                self.monitored_devices.append(props["Address"])

    ##### virtual funcs #####

    #called when power levels need updating
    #if cinfo is None then info icons need to be removed
    def level_setup_event(self, iter, device, cinfo):
        pass

    #called when row needs to be initialized
    def row_setup_event(self, iter, device):
        pass

    #called when a property for a device changes
    def row_update_event(self, iter, key, value):
        pass

    #called when device needs to be added to the list
    #default action: append
    def device_add_event(self, device):
        self.AppendDevice(device)

    def device_remove_event(self, device, iter):
        self.RemoveDevice(device, iter)


    #########################

    def on_device_created(self, path):
        dprint("created", path)
        iter = self.find_device_by_path(path)
        if iter == None:
            dev = Bluez.Device(path)
            dev = Device(dev)
            dev.Temp = True
            self.device_add_event(dev)


    def on_device_removed(self, path):
        iter = self.find_device_by_path(path)
        if iter:
            row = self.get(iter, "device")
            dev = row["device"]

            self.device_remove_event(dev, iter)

    def SetAdapter(self, adapter=None):
        self.clear()
        if self.discovering:
            self.emit("adapter-property-changed", self.Adapter, ("Discovering", False))
            self.StopDiscovery()

        if adapter is not None and not re.match("hci[0-9]*", adapter):
            adapter = adapter_path_to_name(adapter)

        dprint(adapter)
        if self.Adapter is not None:
            self.adapter_signals.DisconnectAll()

        try:
            self.Adapter = self.Manager.GetAdapter(adapter)
            self.adapter_signals.Handle(self.Adapter, self.on_device_found, "DeviceFound")
            self.adapter_signals.Handle(self.Adapter, self.on_property_changed, "PropertyChanged")
            self.adapter_signals.Handle(self.Adapter, self.on_device_created, "DeviceCreated")
            self.adapter_signals.Handle(self.Adapter, self.on_device_removed, "DeviceRemoved")
            self.__adapter_path = self.Adapter.GetObjectPath()

            self.emit("adapter-changed", self.__adapter_path)
        except Bluez.errors.DBusNoSuchAdapterError as e:
            dprint(e)
            #try loading default adapter
            if len(self.Manager.ListAdapters()) > 0 and adapter != None:
                self.SetAdapter()
            else:
                self.Adapter = None
                self.emit("adapter-changed", None)

        except dbus.DBusServiceUnknownError:
            dprint("Dbus error while trying to get adapter.")
            self.Adapter = None
            self.emit("adapter-changed", None)


    def update_progress(self, time, totaltime):
        if not self.discovering:
            return False

        self.__discovery_time += time

        progress = self.__discovery_time / totaltime
        if progress >= 1.0:
            progress = 1.0
        #if self.__discovery_time >= totaltime:
        #self.StopDiscovery()
        #return False

        self.emit("discovery-progress", progress)
        return True


    def add_device(self, device, append=True):
        iter = self.find_device(device)
        #device belongs to another adapter
        if not device.Fake:
            if not device.get_object_path().startswith(self.Adapter.GetObjectPath()):
                return

        if iter == None:
            dprint("adding new device")
            if append:
                iter = self.liststore.append()
            else:
                iter = self.liststore.prepend()

            self.set(iter, device=device)
            self.row_setup_event(iter, device)

            props = device.GetProperties()
            try:
                self.set(iter, dbus_path=device.GetObjectPath())
            except:
                pass

            if not "Fake" in props:
                self.device_signals.Handle("bluez", device,
                                           self.on_device_property_changed,
                                           "PropertyChanged",
                                           sigid=device.GetObjectPath(),
                                           path_keyword="path")
                if props["Connected"]:
                    self.monitor_power_levels(device)


        else:
            row = self.get(iter, "device")
            existing_dev = row["device"]

            props = existing_dev.GetProperties()
            props_new = device.GetProperties()

            #turn a Fake device to a Real device
            n = not "Fake" in props and not "Fake" in props_new
            if n:
                dprint("Updating existing dev")
                self.device_signals.Disconnect(existing_dev.GetObjectPath())
            #existing_dev.Destroy()

            if ("Fake" in props and not "Fake" in props_new) or n:
                self.set(iter, device=device, dbus_path=device.GetObjectPath())
                self.row_setup_event(iter, device)

                if not n:
                    self.emit("device-property-changed", device, iter, ("Fake", False))
                    self.row_update_event(iter, "Fake", False)

                self.device_signals.Handle("bluez", device,
                                           self.on_device_property_changed,
                                           "PropertyChanged",
                                           sigid=device.GetObjectPath(),
                                           path_keyword="path")

                if props_new["Connected"]:
                    self.monitor_power_levels(device)

            #turn a Real device to a Fake device
            elif not "Fake" in props and "Fake" in props_new:
                dprint("converting: real to discovered")
                self.set(iter, device=device, dbus_path=None)
                self.row_setup_event(iter, device)
                self.emit("device-property-changed", device, iter, ("Fake", True))
                self.row_update_event(iter, "Fake", True)


    def DisplayKnownDevices(self, autoselect=False):
        self.clear()
        devices = self.Adapter.ListDevices()
        for device in devices:
            self.device_add_event(Device(device))

        if autoselect:
            self.selection.select_path(0)

    def DiscoverDevices(self, time=10.24):
        if not self.discovering:
            self.__discovery_time = 0
            self.Adapter.StartDiscovery()
            self.discovering = True
            T = 1.0 / 15 * 1000
            gobject.timeout_add(int(T), self.update_progress, T / 1000, time)

    def IsValidAdapter(self):
        if self.Adapter == None:
            return False
        else:
            return True

    def GetAdapterPath(self):
        if self.IsValidAdapter():
            return self.__adapter_path

    def StopDiscovery(self):
        self.discovering = False
        if self.Adapter != None:
            self.Adapter.StopDiscovery()

    def PrependDevice(self, device):
        self.add_device(device, False)

    def AppendDevice(self, device):
        self.add_device(device, True)

    def RemoveDevice(self, device, iter=None, force=False):
        dprint(device)
        if iter == None:
            iter = self.find_device(device)

        if not device.Temp and self.compare(self.selected(), iter):
            self.emit("device-selected", None, None)

        try:
            props = device.GetProperties()
        except:
            self.device_signals.Disconnect(device.get_object_path())
        else:
            if not "Fake" in props:
                self.device_signals.Disconnect(device.GetObjectPath())

        if device.Temp and not force:
            dprint("converting to fake")

            props = copy.deepcopy(props)
            props["Fake"] = True
            dev = FakeDevice(props)

            device = Device(dev)
            self.device_add_event(device)

        else:
            #device.Destroy()
            self.delete(iter)

    def GetSelectedDevice(self):
        selected = self.selected()
        if selected != None:
            row = self.get(selected, "device")
            device = row["device"]
            return device

    def clear(self):
        if len(self.liststore):
            for i in self.liststore:
                iter = i.iter
                device = self.get(iter, "device")["device"]
                self.RemoveDevice(device, iter, True)
            self.liststore.clear()
            self.emit("device-selected", None, None)

        self.address_to_row = {}
        self.path_to_row = {}

    def find_device(self, device):
        if type(device) == str:
            address = device
        else:
            address = device.Address

        try:
            row = self.address_to_row[address]
            if row.valid():
                path = row.get_path()
                iter = self.props.model.get_iter(path)
                return iter
            else:
                del self.address_to_row[address]
                return None

        except KeyError:
            return None

    def find_device_by_path(self, path):
        try:
            row = self.path_to_row[path]
            if row.valid():
                path = row.get_path()
                iter = self.props.model.get_iter(path)
                return iter
            else:
                del self.path_to_row[path]
                return None
        except KeyError:
            return None

    def do_cache(self, iter, kwargs):
        if "device" in kwargs:
            if kwargs["device"]:
                self.address_to_row[kwargs["device"].Address] = gtk.TreeRowReference(self.props.model,
                                                                                     self.props.model.get_path(iter))
                dprint("Caching new device %s" % kwargs["device"].Address)

        if "dbus_path" in kwargs:
            if kwargs["dbus_path"] != None:
                self.path_to_row[kwargs["dbus_path"]] = gtk.TreeRowReference(self.props.model,
                                                                             self.props.model.get_path(iter))
            else:
                existing = self.get(iter, "dbus_path")["dbus_path"]
                if existing != None:
                    del self.path_to_row[existing]

    def append(self, **columns):
        iter = GenericList.append(self, **columns)
        self.do_cache(iter, columns)

    def prepend(self, **columns):
        iter = GenericList.prepend(self, **columns)
        self.do_cache(iter, columns)

    def set(self, iter, **kwargs):
        self.do_cache(iter, kwargs)
        GenericList.set(self, iter, **kwargs)
예제 #8
0
파일: NetUsage.py 프로젝트: vis-ram/blueman
class NetUsage(AppletPlugin, GObject.GObject):
    __depends__ = ["Menu"]
    __icon__ = "network-wireless"
    __description__ = _(
        "Allows you to monitor your (mobile broadband) network traffic usage. Useful for limited data access plans. This plugin tracks every device seperately."
    )
    __author__ = "Walmis"
    __autoload__ = False
    __gsignals__ = {
        str('monitor-added'):
        (GObject.SignalFlags.NO_HOOKS, None, (GObject.TYPE_PYOBJECT, )),
        str('monitor-removed'):
        (GObject.SignalFlags.NO_HOOKS, None, (GObject.TYPE_PYOBJECT, )),
        #monitor, tx, rx
        str('stats'): (GObject.SignalFlags.NO_HOOKS, None, (
            GObject.TYPE_PYOBJECT,
            GObject.TYPE_PYOBJECT,
            GObject.TYPE_PYOBJECT,
        )),
    }

    def on_load(self, applet):
        GObject.GObject.__init__(self)
        self.monitors = []
        self.devices = weakref.WeakValueDictionary()
        self.signals = SignalTracker()

        bus = self.bus = dbus.SystemBus()
        self.signals.Handle('bluez',
                            Network(),
                            self.on_network_property_changed,
                            'PropertyChanged',
                            path_keyword="path")

        item = create_menuitem(_("Network _Usage"),
                               get_icon("network-wireless", 16))
        item.props.tooltip_text = _("Shows network traffic usage")
        self.signals.Handle(item, "activate", self.activate_ui)
        self.Applet.Plugins.Menu.Register(self, item, 84, True)

        self.signals.Handle("dbus",
                            bus,
                            self.on_nm_ppp_stats,
                            "PppStats",
                            "org.freedesktop.NetworkManager.Device.Serial",
                            path_keyword="path")
        self.nm_paths = {}

    def on_nm_ppp_stats(self, down, up, path):
        if not path in self.nm_paths:
            props = self.bus.call_blocking(
                "org.freedesktop.NetworkManager", path,
                "org.freedesktop.DBus.Properties", "GetAll", "s",
                ["org.freedesktop.NetworkManager.Device"])

            if props["Driver"] == "bluetooth" and "rfcomm" in props[
                    "Interface"]:
                self.nm_paths[path] = True

                portid = int(props["Interface"].strip("rfcomm"))

                ls = rfcomm_list()
                for dev in ls:
                    if dev["id"] == portid:
                        adapter = self.Applet.Manager.get_adapter(dev["src"])
                        device = adapter.find_device(dev["dst"])
                        device = Device(device)

                        self.monitor_interface(NMMonitor, device, path)

                        return
            else:
                self.nm_paths[path] = False

    def on_network_property_changed(self, key, value, path):
        dprint(key, value, path)
        if key == "Interface" and value != "":
            d = BluezDevice(path)
            d = Device(d)
            self.monitor_interface(Monitor, d, value)

    def activate_ui(self, item):
        Dialog(self)

    def on_unload(self):
        self.signals.DisconnectAll()
        self.Applet.Plugins.Menu.Unregister(self)

    def monitor_interface(self, montype, *args):
        m = montype(*args)
        self.monitors.append(m)
        self.signals.Handle(m, "stats", self.on_stats, sigid=m)
        self.signals.Handle(m,
                            "disconnected",
                            self.on_monitor_disconnected,
                            sigid=m)
        self.emit("monitor-added", m)

    def on_ppp_connected(self, device, rfcomm, ppp_port):
        self.monitor_interface(Monitor, device, ppp_port)

    def on_monitor_disconnected(self, monitor):
        self.monitors.remove(monitor)
        self.signals.Disconnect(monitor)
        self.emit("monitor-removed", monitor)

    def on_stats(self, monitor, tx, rx):
        self.emit("stats", monitor, tx, rx)
예제 #9
0
파일: NetUsage.py 프로젝트: vis-ram/blueman
class Dialog:
    running = False

    def __init__(self, parent):
        if not Dialog.running:
            Dialog.running = True
        else:
            return
        self.config = None
        self.parent = parent
        builder = Gtk.Builder()
        builder.add_from_file(UI_PATH + "/net-usage.ui")
        builder.set_translation_domain("blueman")

        self.dialog = builder.get_object("dialog")
        self.dialog.connect("response", self.on_response)
        cr1 = Gtk.CellRendererText()
        cr1.props.ellipsize = Pango.EllipsizeMode.END

        self.devices = {}
        self.signals = SignalTracker()

        self.signals.Handle(parent, "monitor-added", self.monitor_added)
        self.signals.Handle(parent, "monitor-removed", self.monitor_removed)
        self.signals.Handle(parent, "stats", self.on_stats)

        cr2 = Gtk.CellRendererText()
        cr2.props.sensitive = False
        cr2.props.style = Pango.Style.ITALIC

        self.liststore = Gtk.ListStore(str, str, str, object)

        self.e_ul = builder.get_object("e_ul")
        self.e_dl = builder.get_object("e_dl")
        self.e_total = builder.get_object("e_total")

        self.l_started = builder.get_object("l_started")
        self.l_duration = builder.get_object("l_duration")

        self.b_reset = builder.get_object("b_reset")
        self.b_reset.connect("clicked", self.on_reset)

        self.cb_device = builder.get_object("cb_device")
        self.cb_device.props.model = self.liststore
        self.cb_device.connect("changed", self.on_selection_changed)

        self.cb_device.pack_start(cr1, True)
        self.cb_device.add_attribute(cr1, 'markup', 1)

        self.cb_device.pack_start(cr2, False)
        self.cb_device.add_attribute(cr2, 'markup', 2)

        general_config = Config("org.blueman.general")

        added = False
        for d in general_config["netusage-dev-list"]:
            for m in parent.monitors:
                if d == m.device.Address:
                    iter = self.liststore.append([
                        d,
                        self.get_caption(m.device.Alias, m.device.Address),
                        _("Connected:") + " " + m.interface, m
                    ])
                    if self.cb_device.get_active() == -1:
                        self.cb_device.set_active_iter(iter)
                    added = True
                    break
            if not added:
                name = d
                if self.parent.Applet.Manager:
                    for a in self.parent.Applet.Manager.list_adapters():
                        try:
                            device = a.find_device(d)
                            device = Device(device)
                            name = self.get_caption(device.Alias,
                                                    device.Address)
                        except:
                            pass

                self.liststore.append([d, name, _("Not Connected"), None])
            added = False
        if len(self.liststore) > 0:
            if self.cb_device.get_active() == -1:
                self.cb_device.set_active(0)
        else:
            d = Gtk.MessageDialog(
                parent=self.dialog,
                flags=Gtk.DialogFlags.MODAL,
                type=Gtk.MessageType.INFO,
                buttons=Gtk.ButtonsType.CLOSE,
                message_format=
                _("No usage statistics are available yet. Try establishing a connection first and then check this page."
                  ))
            d.props.icon_name = "blueman"
            d.run()
            d.destroy()
            self.on_response(None, None)
            return

        self.dialog.show()

    def on_response(self, dialog, response):
        self.signals.DisconnectAll()
        Dialog.running = False
        self.dialog.destroy()

    def update_time(self):
        time = self.config["time"]
        if time:
            self.datetime = datetime.datetime.fromtimestamp(time)

            self.l_started.props.label = str(self.datetime)

            delta = datetime.datetime.now() - self.datetime

            d = gettext.ngettext("day", "days", delta.days)
            h = gettext.ngettext("hour", "hours", delta.seconds / 3600)
            m = gettext.ngettext("minute", "minutes",
                                 delta.seconds % 3600 / 60)

            self.l_duration.props.label = _("%d %s %d %s and %d %s") % (
                delta.days, d, delta.seconds / 3600, h,
                delta.seconds % 3600 / 60, m)
        else:
            self.l_started.props.label = _("Unknown")
            self.l_duration.props.label = _("Unknown")

    def on_selection_changed(self, cb):
        iter = cb.get_active_iter()
        (addr, ) = self.liststore.get(iter, 0)
        self.config = Config("org.blueman.plugins.netusage",
                             "/org/blueman/plugins/netusages/%s/" % addr)
        self.update_counts(self.config["tx"], self.config["rx"])
        self.update_time()

    def get_caption(self, name, address):
        return "%s\n<small>%s</small>" % (cgi.escape(name), address)

    def update_counts(self, tx, rx):
        tx = int(tx)
        rx = int(rx)

        (num, suffix) = format_bytes(tx)
        self.e_ul.props.text = "%.2f %s" % (num, suffix)

        (num, suffix) = format_bytes(rx)
        self.e_dl.props.text = "%.2f %s" % (num, suffix)

        (num, suffix) = format_bytes(int(tx) + int(rx))
        self.e_total.props.text = "%.2f %s" % (num, suffix)

        self.update_time()

    def on_reset(self, button):
        d = Gtk.MessageDialog(
            parent=self.dialog,
            flags=Gtk.DialogFlags.MODAL,
            type=Gtk.MessageType.QUESTION,
            buttons=Gtk.ButtonsType.YES_NO,
            message_format=_("Are you sure you want to reset the counter?"))
        res = d.run()
        d.destroy()
        if res == Gtk.ResponseType.YES:
            self.config["rx"] = 0
            self.config["tx"] = 0
            self.config["time"] = int(time.time())

            self.update_counts(0, 0)

    def on_stats(self, parent, monitor, tx, rx):
        iter = self.cb_device.get_active_iter()
        (mon, ) = self.liststore.get(iter, 3)
        if mon == monitor:
            self.update_counts(tx, rx)

    def monitor_added(self, parent, monitor):
        for row in self.liststore:
            iter = row.iter
            (val, ) = self.liststore.get(iter, 0)

            if val == monitor.device.Address:
                self.liststore.set(
                    iter, 1,
                    self.get_caption(monitor.device.Alias,
                                     monitor.device.Address), 2,
                    _("Connected:") + " " + monitor.interface, 3, monitor)
                return

        self.liststore.append([
            monitor.device.Address,
            self.get_caption(monitor.device.Alias, monitor.device.Address),
            _("Connected:") + " " + monitor.interface, monitor
        ])

    def monitor_removed(self, parent, monitor):
        for row in self.liststore:
            iter = row.iter
            (val, ) = self.liststore.get(iter, 0)

            if val == monitor.device.Address:
                self.liststore.set(
                    iter, 1,
                    self.get_caption(monitor.device.Alias,
                                     monitor.device.Address), 2,
                    _("Not Connected"), 3, None)
                return
예제 #10
0
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.Fake = True
        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.Device.Appearance = 0

        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")

    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):
        if self.Fake:
            return []
        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):
        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 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
        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
예제 #11
0
class PowerManager(AppletPlugin):
    __depends__ = ["StatusIcon", "Menu"]
    __unloadable__ = True
    __description__ = _("Controls Bluetooth adapter power states")
    __author__ = "Walmis"
    __icon__ = "gnome-power-manager"

    __gsettings__ = {
        "schema": "org.blueman.plugins.powermanager",
        "path": None
    }

    __options__ = {
        "auto-power-on": {
            "type": bool,
            "default": True,
            "name": _("Auto power-on"),
            "desc": _("Automatically power on adapters")
        }
    }

    def on_load(self, applet):
        AppletPlugin.add_method(self.on_power_state_query)
        AppletPlugin.add_method(self.on_power_state_change_requested)
        AppletPlugin.add_method(self.on_power_state_changed)

        self.Applet = applet

        self.item = create_menuitem("Should be overwritten", get_icon("blueman-disabled", 16))
        self.item.get_child().get_children()[1].set_markup_with_mnemonic(_("<b>Bluetooth _Off</b>"))

        self.item.props.tooltip_text = _("Turn off all adapters")

        self.signals = SignalTracker()
        self.signals.Handle('bluez', Bluez.Adapter(), self.adapter_property_changed, "PropertyChanged",
                            path_keyword="path")

        self.signals.Handle(self.item, "activate", lambda x: self.on_bluetooth_toggled())

        self.Applet.Plugins.Menu.Register(self, self.item, 0)

        self.adapter_state = True
        self.current_state = True

        self.request_in_progress = False

        self.STATE_ON = 2
        self.STATE_OFF = 1
        self.STATE_OFF_FORCED = 0

    def on_unload(self):
        self.signals.DisconnectAll()
        self.Applet.Plugins.Menu.Unregister(self)

    @property
    def CurrentState(self):
        return self.current_state

    def on_manager_state_changed(self, state):
        if state:
            def timeout():
                self.adapter_state = self.get_adapter_state()
                if self.get_option("auto-power-on"):
                    self.RequestPowerState(True, force=True)
                else:
                    self.RequestPowerState(self.adapter_state)

            GObject.timeout_add(1000, timeout)

    def get_adapter_state(self):
        adapters = self.Applet.Manager.list_adapters()
        for adapter in adapters:
            props = adapter.get_properties()
            if not props["Powered"]:
                return False
        return bool(adapters)

    def set_adapter_state(self, state):
        try:
            dprint(state)
            adapters = self.Applet.Manager.list_adapters()
            for adapter in adapters:
                adapter.set("Powered", state)

            self.adapter_state = state
        except Exception as e:
            dprint("Exception occurred", e)


    class Callback(object):
        def __init__(self, parent, state):
            self.parent = parent
            self.num_cb = 0
            self.called = 0
            self.state = state
            self.success = False
            self.timer = GObject.timeout_add(5000, self.timeout)

        def __call__(self, result):
            self.called += 1

            if result:
                self.success = True

            self.check()

        def check(self):
            if self.called == self.num_cb:
                dprint("callbacks done")
                self.parent.set_adapter_state(self.state)
                GObject.source_remove(self.timer)
                self.parent.request_in_progress = False

        def timeout(self):
            dprint("Timeout reached while setting power state")
            self.parent.UpdatePowerState()
            self.parent.request_in_progress = False

    def RequestPowerState(self, state, force=False):
        if self.current_state != state or force:
            if not self.request_in_progress:
                self.request_in_progress = True
                dprint("Requesting", state)
                cb = PowerManager.Callback(self, state)

                rets = self.Applet.Plugins.Run("on_power_state_change_requested", self, state, cb)
                cb.num_cb = len(rets)
                cb.check()
                self.UpdatePowerState()
            else:
                dprint("Another request in progress")

    def on_power_state_change_requested(self, pm, state, cb):
        cb(None)

    def on_power_state_query(self, pm):
        if self.adapter_state:
            return self.STATE_ON
        else:
            return self.STATE_OFF

    def on_power_state_changed(self, manager, state):
        pass


    #queries other plugins to determine the current power state
    def UpdatePowerState(self):
        rets = self.Applet.Plugins.Run("on_power_state_query", self)

        off = True in map(lambda x: x < self.STATE_ON, rets)
        foff = self.STATE_OFF_FORCED in rets
        on = self.STATE_ON in rets

        icon, label = self.item.get_child().get_children()

        new_state = True
        if foff or off:

            label.set_markup_with_mnemonic(_("<b>Turn Bluetooth _On</b>"))
            icon.set_from_pixbuf(get_icon("blueman", 16))
            self.item.props.tooltip_text = _("Turn on all adapters")

            if foff:
                self.item.props.sensitive = False
            else:
                self.item.props.sensitive = True

            new_state = False

        elif on and self.current_state != True:

            label.set_markup_with_mnemonic(_("<b>Turn Bluetooth _Off</b>"))
            icon.set_from_pixbuf(get_icon("blueman-disabled", 16))
            self.item.props.tooltip_text = _("Turn off all adapters")
            self.item.props.sensitive = True

            new_state = True

        dprint("off", off, "\nfoff", foff, "\non", on, "\ncurrent state", self.current_state, "\nnew state", new_state)

        if self.current_state != new_state:
            dprint("Signalling", new_state)
            self.current_state = new_state

            self.BluetoothStatusChanged(new_state)
            self.Applet.Plugins.Run("on_power_state_changed", self, new_state)
            self.Applet.Plugins.StatusIcon.IconShouldChange()

    @dbus.service.signal('org.blueman.Applet', signature="b")
    def BluetoothStatusChanged(self, status):
        pass

    @dbus.service.method('org.blueman.Applet', in_signature="b", out_signature="")
    def SetBluetoothStatus(self, status):
        self.RequestPowerState(status)

    @dbus.service.method('org.blueman.Applet', in_signature="", out_signature="b")
    def GetBluetoothStatus(self):
        return self.CurrentState

    def adapter_property_changed(self, key, value, path):
        if key == "Powered":
            if value and not self.CurrentState:
                dprint("adapter powered on while in off state, turning bluetooth on")
                self.RequestPowerState(True)

            self.UpdatePowerState()

    def on_bluetooth_toggled(self):
        self.RequestPowerState(not self.CurrentState)

    def on_status_icon_query_icon(self):
        if not self.GetBluetoothStatus():
            return "blueman-disabled", "blueman-disabled"

    def on_adapter_added(self, path):
        adapter = Bluez.Adapter(path)

        def on_ready():
            if not self.adapter_state:
                adapter.set("Powered", False)
            else:
                adapter.set("Powered", True)

        wait_for_adapter(adapter, on_ready)