예제 #1
0
class DiscvManager(AppletPlugin):
    __depends__ = ["Menu"]
    __author__ = "Walmis"
    __icon__ = "gtk-find"
    __description__ = _(
        "Provides a menu item for making the default adapter temporarily visible when it is set to hidden by default"
    )

    __options__ = {
        "time": {
            "type": int,
            "default": 60,
            "name": _("Discoverable timeout"),
            "desc": _("Amount of time in seconds discoverable mode will last"),
            "range": (60, 600)
        }
    }

    def on_load(self, applet):
        self.Signals = SignalTracker()

        self.item = create_menuitem(_("_Make Discoverable"),
                                    get_icon("gtk-find", 16))
        applet.Plugins.Menu.Register(self, self.item, 20, False)

        self.Applet = applet
        self.adapter = None
        self.time_left = -1

        self.Signals.Handle(self.item, "activate", self.on_set_discoverable)
        self.item.props.tooltip_text = _(
            "Make the default adapter temporarily visible")

        self.timeout = None

    def on_unload(self):
        self.Applet.Plugins.Menu.Unregister(self)
        del self.item

        if self.timeout:
            GObject.source_remove(self.timeout)

        self.Signals.DisconnectAll()

    def on_manager_state_changed(self, state):
        if state:
            self.init_adapter()
            self.update_menuitems()
        else:
            self.Signals.Disconnect(0)

            self.adapter = None
            self.update_menuitems()

    def on_update(self):
        self.time_left -= 1
        self.item.get_child(
        ).props.label = _("Discoverable... %ss") % self.time_left
        self.item.props.sensitive = False

        return True

    def on_set_discoverable(self, item):
        if self.adapter:
            self.adapter.set("Discoverable", True)
            self.adapter.set("DiscoverableTimeout", self.get_option("time"))

    def init_adapter(self):
        try:
            self.adapter = self.Applet.Manager.get_adapter()
        except:
            self.adapter = None

    def on_adapter_removed(self, path):
        dprint(path)
        if path == self.adapter.get_object_path():
            self.init_adapter()
            self.update_menuitems()

    def on_adapter_property_changed(self, path, key, value):
        if self.adapter and path == self.adapter.get_object_path():
            dprint("prop", key, value)
            if key == "DiscoverableTimeout":
                if value == 0:  #always visible
                    if self.timeout != None:
                        GObject.source_remove(self.timeout)
                    self.time_left = -1
                    self.timeout = None
                else:
                    if self.time_left > -1:
                        if self.timeout != None:
                            GObject.source_remove(self.timeout)
                    self.time_left = value

                    self.timeout = GObject.timeout_add(1000, self.on_update)
                    return

            elif (key == "Discoverable" and not value) or (key == "Powered"
                                                           and not value):
                dprint("Stop")
                if self.timeout != None:
                    GObject.source_remove(self.timeout)
                self.time_left = -1
                self.timeout = None

            self.update_menuitems()

    def update_menuitems(self):
        try:
            props = self.adapter.get_properties()
        except Exception as e:
            dprint("warning: Adapter is None")
            self.item.props.visible = False
        else:
            if (not props["Discoverable"]
                    or props["DiscoverableTimeout"] > 0) and props["Powered"]:

                self.item.props.visible = True
                self.item.get_child().props.label = _("_Make Discoverable")
                self.item.props.sensitive = True

            else:
                self.item.props.visible = False
예제 #2
0
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__ = {
        'monitor-added':
        (GObject.SignalFlags.NO_HOOKS, None, (GObject.TYPE_PYOBJECT, )),
        'monitor-removed':
        (GObject.SignalFlags.NO_HOOKS, None, (GObject.TYPE_PYOBJECT, )),
        #monitor, tx, rx
        '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)
예제 #3
0
class DeviceList(GenericList):
    __gsignals__ = {
        #@param: device TreeIter
        #note: None None is given when there ar no more rows, or when selected device is removed
        str('device-selected'): (GObject.SignalFlags.RUN_LAST, 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
        str('device-property-changed'): (GObject.SignalFlags.RUN_LAST, None, (
            GObject.TYPE_PYOBJECT,
            GObject.TYPE_PYOBJECT,
            GObject.TYPE_PYOBJECT,
        )),
        #@param: adapter, (key, value)
        str('adapter-property-changed'): (GObject.SignalFlags.RUN_LAST, None, (
            GObject.TYPE_PYOBJECT,
            GObject.TYPE_PYOBJECT,
        )),
        #@param: progress (0 to 1)
        str('discovery-progress'):
        (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_FLOAT, )),

        #@param: new adapter path, None if there are no more adapters
        str('adapter-changed'):
        (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_PYOBJECT, )),

        #@param: adapter path
        str('adapter-added'):
        (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_PYOBJECT, )),
        str('adapter-removed'):
        (GObject.SignalFlags.RUN_LAST, 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.signals = SignalTracker()

        self.manager = Bluez.Manager()
        self.signals.Handle(self.manager, on_adapter_removed, "AdapterRemoved")
        self.signals.Handle(self.manager, on_adapter_added, "AdapterAdded")

        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)

            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.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.new(
                        self.get_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.get_model():
                self.monitored_devices.remove(props["Address"])
                return False

            iter = self.get_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.get_properties()

        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.get_object_path())
            try:
                cinfo = conn_info(props["Address"], hci)
            except:
                dprint("Failed to get power levels")
            else:
                r = Gtk.TreeRowReference.new(self.get_model(),
                                             self.get_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 adapter != "" 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.get_adapter(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.get_object_path()
            self.emit("adapter-changed", self.__adapter_path)
        except Bluez.errors.DBusNoSuchAdapterError as e:
            dprint(e)
            #try loading default adapter
            if len(self.manager.list_adapters()) > 0 and adapter is not None:
                self.SetAdapter()
            else:
                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.get_object_path()):
                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.get_properties()
            try:
                self.set(iter, dbus_path=device.get_object_path())
            except:
                pass

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

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

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

            #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.get_object_path())
            #existing_dev.Destroy()

            if ("Fake" in props and not "Fake" in props_new) or n:
                self.set(iter,
                         device=device,
                         dbus_path=device.get_object_path())
                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.get_object_path(),
                                           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.list_devices()
        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
            if self.Adapter is not None:
                self.Adapter.start_discovery()
                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.stop_discovery()

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

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

    def RemoveDevice(self, device, iter=None):
        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.get_properties()
        except:
            self.device_signals.Disconnect(device.get_object_path())
        else:
            if not "Fake" in props:
                self.device_signals.Disconnect(device.get_object_path())

        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)
            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.get_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.get_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.new(
                        self.get_model(),
                        self.get_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.new(
                        self.get_model(),
                        self.get_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)