~ubuntu-branches/ubuntu/maverick/hal/maverick

« back to all changes in this revision

Viewing changes to tools/device-manager/DeviceManager.py

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2007-10-23 12:33:58 UTC
  • mto: (1.5.1 sid)
  • mto: This revision was merged to the branch mainline in revision 90.
  • Revision ID: james.westby@ubuntu.com-20071023123358-xaf8mjc5n84d5gtz
Tags: upstream-0.5.10
ImportĀ upstreamĀ versionĀ 0.5.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
"""This file contains the DeviceManager class."""
2
 
 
3
 
import sys
4
 
import gobject
5
 
import gtk
6
 
import dbus
7
 
if getattr(dbus, "version", (0,0,0)) >= (0,41,0):
8
 
    import dbus.glib
9
 
 
10
 
 
11
 
 
12
 
try:
13
 
    import gnome.ui
14
 
 
15
 
except ImportError:
16
 
    gnome_imported = 0
17
 
else:
18
 
    gnome_imported = 1
19
 
 
20
 
import Const
21
 
from Representation import Representation
22
 
from Device import Device
23
 
 
24
 
from LibGladeApplication import LibGladeApplication
25
 
 
26
 
class DeviceManager(LibGladeApplication):
27
 
    """This is the main window for the application."""
28
 
 
29
 
 
30
 
    def on_about_activate(self, w):
31
 
        """Show the about dialog."""
32
 
        try:
33
 
            self.about.destroy()
34
 
        finally:
35
 
            self.about = gnome.ui.About(Const.NAME_LONG, Const.VERSION, Const.COPYRIGHT,
36
 
                                        Const.INFO, Const.AUTHORS).show()
37
 
            self.about.show()
38
 
 
39
 
    def on_virtual_devices_activate(self, obj):
40
 
        self.dont_show_virtual = 1 - self.dont_show_virtual
41
 
        self.update_device_list()
42
 
 
43
 
    def __init__(self):
44
 
        """Init the GUI and connect to the HAL daemon."""
45
 
        LibGladeApplication.__init__(self, Const.DATADIR + "/hal-device-manager.glade")
46
 
 
47
 
        ver = getattr(dbus, 'version', (0, 0, 0))
48
 
        if ver < (0, 40, 0):
49
 
            dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, 
50
 
                                       gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE,
51
 
                                       "The DBus Python Bindings you are using are too old. "
52
 
                                       "Make sure you have the latest version!")
53
 
            dialog.run()
54
 
            sys.exit(1)
55
 
 
56
 
        if not gnome_imported:
57
 
            self.xml.get_widget("about1").set_sensitive(0)
58
 
 
59
 
        self.representation = Representation()
60
 
 
61
 
        self.bus = dbus.SystemBus()
62
 
        self.hal_manager_obj = self.bus.get_object("org.freedesktop.Hal", 
63
 
                                                   "/org/freedesktop/Hal/Manager")
64
 
        self.hal_manager = dbus.Interface(self.hal_manager_obj,
65
 
                                          "org.freedesktop.Hal.Manager")
66
 
 
67
 
        # gdl_changed will be invoked when the Global Device List is changed
68
 
        # per the hal spec
69
 
        self.hal_manager.connect_to_signal("DeviceAdded", 
70
 
                         lambda *args: self.gdl_changed("DeviceAdded", *args))
71
 
        self.hal_manager.connect_to_signal("DeviceRemoved", 
72
 
                         lambda *args: self.gdl_changed("DeviceRemoved", *args))
73
 
        self.hal_manager.connect_to_signal("NewCapability", 
74
 
                         lambda *args: self.gdl_changed("NewCapability", *args))
75
 
 
76
 
        # Add listeners for all devices
77
 
        try:
78
 
            device_names = self.hal_manager.GetAllDevices()
79
 
        except:
80
 
            dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, 
81
 
                                       gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE,
82
 
                                       "Could not get device list. "
83
 
                                       "Make sure hald is running!")
84
 
            dialog.run()
85
 
            sys.exit(1)
86
 
 
87
 
        for name in device_names:
88
 
            self.add_device_signal_recv (name);
89
 
 
90
 
        self.dont_show_virtual = 1
91
 
        self.update_device_list()
92
 
        self.main_window.show()
93
 
 
94
 
    def add_device_signal_recv (self, udi):
95
 
        self.bus.add_signal_receiver(lambda *args: self.property_modified(udi, *args),
96
 
                                     "PropertyModified",
97
 
                                     "org.freedesktop.Hal.Device",
98
 
                                     "org.freedesktop.Hal",
99
 
                                     udi)
100
 
 
101
 
    def remove_device_signal_recv (self, udi):
102
 
        try:
103
 
            self.bus.remove_signal_receiver(None,
104
 
                                            "PropertyModified",
105
 
                                            "org.freedesktop.Hal.Device",
106
 
                                            "org.freedesktop.Hal",
107
 
                                            udi)
108
 
        except Exception, e:
109
 
            print "Older versions of the D-BUS bindings have an error when removing signals. Please upgrade."
110
 
            print e
111
 
 
112
 
    def get_current_focus_udi(self):
113
 
        """Get the UDI of the currently focused device"""
114
 
        (tree_model, tree_iter) = self.tree_selection.get_selected()
115
 
        if tree_iter:
116
 
            device_udi = tree_model.get_value(tree_iter, Const.UDI_COLUMN)
117
 
            return device_udi
118
 
        return None
119
 
 
120
 
    def on_device_tree_selection_changed(self, tree_selection):
121
 
        """This method is called when the selection has changed in the
122
 
        device tree"""
123
 
        device_udi = self.get_current_focus_udi()
124
 
        if device_udi != None:
125
 
            device = self.udi_to_device(device_udi)
126
 
            self.update_device_notebook(device)
127
 
 
128
 
 
129
 
    def device_condition(self, device_udi, condition_name, condition_details):
130
 
        """This method is called when signals on the Device interface is
131
 
        received"""
132
 
 
133
 
        print "\nCondition device=%s"%device_udi
134
 
        print "  (condition_name, condition_details) = ('%s', '%s')"%(condition_name, condition_details)
135
 
 
136
 
    def property_modified(self, device_udi, num_changes, change_list):
137
 
        """This method is called when signals on the Device interface is
138
 
        received"""
139
 
 
140
 
        print "\nPropertyModified, device=%s"%device_udi
141
 
        for i in change_list:
142
 
            property_name = i[0]
143
 
            removed = i[1]
144
 
            added = i[2]
145
 
 
146
 
            print "  key=%s, rem=%d, add=%d"%(property_name, removed, added)
147
 
            if property_name=="info.parent":
148
 
                self.update_device_list()        
149
 
            else:
150
 
                device_udi_obj = self.bus.get_object("org.freedesktop.Hal", device_udi)
151
 
                device_obj = self.udi_to_device(device_udi)
152
 
 
153
 
                if device_udi_obj.PropertyExists(property_name, dbus_interface="org.freedesktop.Hal.Device"):
154
 
                    device_obj.properties[property_name] = device_udi_obj.GetProperty(property_name, 
155
 
                                                                                      dbus_interface="org.freedesktop.Hal.Device")
156
 
                    print "  value=%s"%(device_obj.properties[property_name])
157
 
                else:
158
 
                    if device_obj != None:
159
 
                        try:
160
 
                            del device_obj.properties[property_name]
161
 
                        except:
162
 
                            pass
163
 
 
164
 
                device_focus_udi = self.get_current_focus_udi()
165
 
                if device_focus_udi != None:
166
 
                    device = self.udi_to_device(device_udi)
167
 
                    if device_focus_udi==device_udi:
168
 
                        self.update_device_notebook(device)
169
 
                        
170
 
    def gdl_changed(self, signal_name, device_udi, *args):
171
 
        """This method is called when a HAL device is added or removed."""
172
 
 
173
 
        if signal_name=="DeviceAdded":
174
 
            print "\nDeviceAdded, udi=%s"%(device_udi)
175
 
            self.add_device_signal_recv (device_udi)
176
 
            self.update_device_list()
177
 
        elif signal_name=="DeviceRemoved":
178
 
            print "\nDeviceRemoved, udi=%s"%(device_udi)
179
 
            self.remove_device_signal_recv (device_udi)
180
 
            self.update_device_list()
181
 
        elif signal_name=="NewCapability":
182
 
            [cap] = args 
183
 
            print "\nNewCapability, cap=%s, udi=%s"%(cap, device_udi)
184
 
        else:
185
 
            print "*** Unknown signal %s"% signal_name
186
 
 
187
 
 
188
 
    def update_device_list(self):
189
 
        """Builds, or rebuilds, the device tree"""
190
 
        # We use a virtual root device so we have a single tree
191
 
        self.virtual_root = self.build_device_tree()
192
 
 
193
 
        # (Name to display, device UDI)
194
 
        try:
195
 
            if self.tree_model:
196
 
                pass
197
 
        except:
198
 
            self.tree_model = gtk.TreeStore(gtk.gdk.Pixbuf,
199
 
                                            gobject.TYPE_STRING, gobject.TYPE_STRING)
200
 
        while 1:
201
 
            it = self.tree_model.get_iter_first()
202
 
            if not it:
203
 
                break
204
 
            self.tree_model.remove(it)
205
 
 
206
 
        self.virtual_root.populate_gtk_tree(self.tree_model,
207
 
                                            self.dont_show_virtual,
208
 
                                            self.representation)
209
 
 
210
 
        tree_view = self.xml.get_widget("device_tree")
211
 
        try:
212
 
            if self.tree_selection:
213
 
                pass
214
 
        except:
215
 
            self.tree_selection = tree_view.get_selection()
216
 
            self.tree_selection.connect("changed",
217
 
                                        self.on_device_tree_selection_changed)
218
 
 
219
 
        # add new columns only first time
220
 
        try:
221
 
            if self.column_dt:
222
 
                pass
223
 
        except:
224
 
            self.column_dt = gtk.TreeViewColumn()
225
 
            self.column_dt.set_title("Devices")
226
 
            render_pixbuf = gtk.CellRendererPixbuf()
227
 
            self.column_dt.pack_start(render_pixbuf, expand=False)
228
 
            self.column_dt.add_attribute(render_pixbuf, "pixbuf",
229
 
                                         Const.PIXBUF_COLUMN)
230
 
            render_text = gtk.CellRendererText()
231
 
            self.column_dt.pack_start(render_text, expand=True)
232
 
            self.column_dt.add_attribute(render_text, "text",
233
 
                                         Const.TITLE_COLUMN)
234
 
            tree_view.append_column(self.column_dt)
235
 
 
236
 
        tree_view.set_model(self.tree_model)
237
 
        tree_view.expand_all()
238
 
 
239
 
        # Set focus to first element
240
 
        tree_view.grab_focus()
241
 
        self.update_device_notebook(self.virtual_root.children[0])
242
 
 
243
 
 
244
 
    def udi_to_device(self, device_udi):
245
 
        """Given a HAL UDI (Unique Device Identifier) this method returns
246
 
        the corresponding HAL device"""
247
 
        return self.virtual_root.find_by_udi(device_udi)
248
 
 
249
 
    def build_device_tree(self):
250
 
        """Retrieves the device list from the HAL daemon and builds
251
 
        a tree of Device (Python) objects. The root is a virtual
252
 
        device"""
253
 
        device_names = self.hal_manager.GetAllDevices()
254
 
        device_names.sort()
255
 
 
256
 
        virtual_root = Device("virtual_root", None, {})
257
 
        self.device_list = [virtual_root]
258
 
        
259
 
        # first build list of Device objects
260
 
        for name in device_names:
261
 
            device_dbus_obj = self.bus.get_object("org.freedesktop.Hal" ,name)
262
 
            properties = device_dbus_obj.GetAllProperties(dbus_interface="org.freedesktop.Hal.Device")
263
 
            try:
264
 
                parent_name = properties["info.parent"]
265
 
            except KeyError:
266
 
                # no parent, must be parent of virtual_root
267
 
                parent_name = "/"
268
 
            except TypeError:
269
 
                print "Error: no properties for device %s"%name
270
 
                continue
271
 
            device = Device(name, parent_name, properties)
272
 
            self.device_list.append(device)
273
 
 
274
 
        # set parent_device and children for each Device object
275
 
        for device in self.device_list:
276
 
            parent_name = device.parent_name
277
 
            device.parent_device = virtual_root
278
 
            if parent_name!="/":
279
 
                for p in self.device_list:
280
 
                    if p.device_name==parent_name:
281
 
                        device.parent_device = p
282
 
                        p.children.append(device)
283
 
            if device!=virtual_root and device.parent_device==virtual_root:
284
 
                virtual_root.children.append(device)
285
 
            if device==virtual_root:
286
 
                device.parent_device=None
287
 
        return virtual_root
288
 
 
289
 
 
290
 
    def update_tab_device(self, device):
291
 
        """Updates the 'Device' tab given a Device object"""
292
 
        bus = self.xml.get_widget("ns_device_bus")
293
 
        #state = self.xml.get_widget("ns_device_status")
294
 
        vendor = self.xml.get_widget("ns_device_vendor")
295
 
        product = self.xml.get_widget("ns_device_name")
296
 
        category = self.xml.get_widget("ns_device_category")
297
 
        capabilities = self.xml.get_widget("ns_device_capabilities")
298
 
 
299
 
        product.set_label("Unknown")
300
 
        vendor.set_label("Unknown")
301
 
        #state.set_label(Const.STATE_NAMES[device.properties["State"]])
302
 
 
303
 
        # walk up the device tree to find the bus type
304
 
        bus.set_label("Unknown")
305
 
        d = device
306
 
        while d:
307
 
            if d.properties.has_key("info.subsystem"):
308
 
                bus.set_label(Const.BUS_NAMES[d.properties["info.subsystem"]])
309
 
                break
310
 
            d = self.udi_to_device(d.properties["info.parent"])
311
 
 
312
 
        # guestimate product and vendor if we have no device information file
313
 
        if device.properties.has_key("info.subsystem") and device.properties["info.subsystem"]=="usb":
314
 
            if device.properties.has_key("info.product"):
315
 
                product.set_label("%s"%device.properties["info.product"])
316
 
            elif device.properties.has_key("usb.product"):
317
 
                product.set_label("%s"%device.properties["usb.product"])
318
 
            elif device.properties.has_key("usb.product_id"):
319
 
                product.set_label("Unknown (0x%x)"%device.properties["usb.product_id"])
320
 
            else:
321
 
                product.set_label("Unknown")
322
 
 
323
 
            if device.properties.has_key("info.vendor"):
324
 
                vendor.set_label("%s"%device.properties["info.vendor"])
325
 
            elif device.properties.has_key("usb.vendor"):
326
 
                vendor.set_label("%s"%device.properties["usb.vendor"])
327
 
            elif device.properties.has_key("usb.vendor_id"):
328
 
                vendor.set_label("Unknown (0x%x)"%device.properties["usb.vendor_id"])
329
 
            else:
330
 
                vendor.set_label("Unknown")
331
 
 
332
 
 
333
 
        elif device.properties.has_key("info.subsystem") and device.properties["info.subsystem"]=="pci":
334
 
            if device.properties.has_key("info.product"):
335
 
                product.set_label("%s"%device.properties["info.product"])
336
 
            elif device.properties.has_key("pci.product"):
337
 
                product.set_label("%s"%device.properties["pci.product"])
338
 
            elif device.properties.has_key("pci.product_id"):
339
 
                product.set_label("Unknown (0x%x)"%device.properties["pci.product_id"])
340
 
            else:
341
 
                product.set_label("Unknown")
342
 
 
343
 
            if device.properties.has_key("info.vendor"):
344
 
                vendor.set_label("%s"%device.properties["info.vendor"])
345
 
            elif device.properties.has_key("pci.vendor"):
346
 
                vendor.set_label("%s"%device.properties["pci.vendor"])
347
 
            elif device.properties.has_key("pci.vendor_id"):
348
 
                vendor.set_label("Unknown (0x%x)"%device.properties["pci.vendor_id"])
349
 
            else:
350
 
                vendor.set_label("Unknown")
351
 
        elif device.properties.has_key("info.subsystem") and device.properties["info.subsystem"]=="block":
352
 
            if device.properties.has_key("info.product"):
353
 
                product.set_label("%s"%device.properties["info.product"])
354
 
            else:
355
 
                product.set_label("Unknown")
356
 
 
357
 
            if device.properties.has_key("info.vendor"):
358
 
                vendor.set_label("%s"%device.properties["info.vendor"])
359
 
            else:
360
 
                vendor.set_label("Unknown")
361
 
        else:
362
 
            product.set_label("Unknown")
363
 
            vendor.set_label("Unknown")
364
 
 
365
 
        # clear category, capabilities
366
 
        # set category, capabilities
367
 
        if device.properties.has_key("info.category"):
368
 
            category.set_label("%s"%device.properties["info.category"])
369
 
        else:
370
 
            category.set_label("Unknown")
371
 
 
372
 
        if device.properties.has_key("info.capabilities"):
373
 
            capabilities.set_label(", ".join(device.properties["info.capabilities"]))
374
 
        else:
375
 
            capabilities.set_label("Unknown")
376
 
 
377
 
    def update_tab_usb(self, device):
378
 
        """Updates the 'USB' tab given a Device object; may hide it"""
379
 
        page = self.xml.get_widget("device_notebook").get_nth_page(1)
380
 
        if not device.properties.has_key("info.subsystem") or device.properties["info.subsystem"]!="usb":
381
 
            page.hide_all()
382
 
            return
383
 
 
384
 
        page.show_all()
385
 
 
386
 
        version = self.xml.get_widget("ns_usb_version")
387
 
        bandwidth = self.xml.get_widget("ns_usb_bandwidth")
388
 
        maxpower = self.xml.get_widget("ns_usb_maxpower")
389
 
        man_id = self.xml.get_widget("ns_usb_man_id")
390
 
        prod_id = self.xml.get_widget("ns_usb_prod_id")
391
 
        revision = self.xml.get_widget("ns_usb_rev")
392
 
 
393
 
        bcdVersion = device.properties["usb.version_bcd"]
394
 
        version.set_label("%x.%x"%(bcdVersion>>8, bcdVersion&0xff))
395
 
 
396
 
        bcdSpeed = device.properties["usb.speed_bcd"]
397
 
        bandwidth.set_label("%x.%x Mbit/s"%(bcdSpeed>>8, bcdSpeed&0xff))
398
 
        maxpower.set_label("%d mA"%(device.properties["usb.max_power"]))
399
 
        if not device.properties.has_key("usb.vendor"):
400
 
            man_id.set_label("0x%04x"%(device.properties["usb.vendor_id"]))
401
 
        else:
402
 
            man_id.set_label("%s"%(device.properties["usb.vendor"]))
403
 
        if not device.properties.has_key("usb.product"):
404
 
            prod_id.set_label("0x%04x"%(device.properties["usb.product_id"]))
405
 
        else:
406
 
            prod_id.set_label("%s"%(device.properties["usb.product"]))
407
 
        bcdDevice = device.properties["usb.device_revision_bcd"]
408
 
        revision.set_label("%x.%x"%((bcdDevice>>8), bcdDevice&0xff))
409
 
 
410
 
 
411
 
    def update_tab_pci(self, device):
412
 
        """Updates the 'PCI' tab given a Device object; may hide it"""
413
 
        page = self.xml.get_widget("device_notebook").get_nth_page(2)
414
 
        if not device.properties.has_key("info.subsystem") or device.properties["info.subsystem"]!="pci":
415
 
            page.hide_all()
416
 
            return
417
 
 
418
 
        page.show_all()
419
 
 
420
 
        man_id = self.xml.get_widget("ns_pci_man_id")
421
 
        prod_id = self.xml.get_widget("ns_pci_prod_id")
422
 
        subsys_man_id = self.xml.get_widget("ns_pci_subsys_man_id")
423
 
        subsys_prod_id = self.xml.get_widget("ns_pci_subsys_prod_id")
424
 
 
425
 
        if not device.properties.has_key("pci.vendor"):
426
 
            man_id.set_label("Unknown (0x%04x)"%(device.properties["pci.vendor_id"]))
427
 
        else:
428
 
            man_id.set_label("%s"%(device.properties["pci.vendor"]))
429
 
        if not device.properties.has_key("pci.product"):
430
 
            prod_id.set_label("Unknown (0x%04x)"%(device.properties["pci.product_id"]))
431
 
        else:
432
 
            prod_id.set_label("%s"%(device.properties["pci.product"]))
433
 
 
434
 
        if not device.properties.has_key("pci.subsys_vendor"):
435
 
            subsys_man_id.set_label("Unknown (0x%04x)"%(device.properties["pci.subsys_vendor_id"]))
436
 
        else:
437
 
            subsys_man_id.set_label("%s"%(device.properties["pci.subsys_vendor"]))
438
 
        if not device.properties.has_key("pci.subsys_product"):
439
 
            subsys_prod_id.set_label("Unknown (0x%04x)"%(device.properties["pci.subsys_product_id"]))
440
 
        else:
441
 
            subsys_prod_id.set_label("%s"%(device.properties["pci.subsys_product"]))
442
 
 
443
 
    def update_tab_advanced(self, device):
444
 
        """Updates the 'Advanced' tab given a Device object"""
445
 
        store = gtk.ListStore(gobject.TYPE_STRING,
446
 
                              gobject.TYPE_STRING,
447
 
                              gobject.TYPE_STRING)
448
 
        keys = device.properties.keys()
449
 
        keys.sort()
450
 
        for p in keys:
451
 
            iter = store.append()
452
 
            val = device.properties[p]
453
 
            ptype = type(val)
454
 
            if ptype==str:
455
 
                store.set(iter, 0, p, 1, "string", 2, "%s"%val)
456
 
            elif ptype==int:
457
 
                store.set(iter, 0, p, 1, "int", 2, "%d (0x%x)"%(val, val))
458
 
            elif ptype==long:
459
 
                store.set(iter, 0, p, 1, "long", 2, "%d (0x%x)"%(val, val))
460
 
            elif ptype==bool:
461
 
                if val:
462
 
                    store.set(iter, 0, p, 1, "bool", 2, "true")
463
 
                else:
464
 
                    store.set(iter, 0, p, 1, "bool", 2, "false")
465
 
            elif ptype==float:
466
 
                store.set(iter, 0, p, 1, "float", 2, "%f"%val)
467
 
            elif ptype==list:
468
 
                store.set(iter, 0, p, 1, "list", 2, ", ".join(val))
469
 
            else:
470
 
                # assume strlist
471
 
                store.set(iter, 0, p, 1, "strlist", 2, val)
472
 
 
473
 
 
474
 
        prop_tree_view = self.xml.get_widget("ns_adv_properties")
475
 
 
476
 
        # remove old columns, if any
477
 
        cols = prop_tree_view.get_columns()
478
 
        for cr in cols:
479
 
            prop_tree_view.remove_column(cr)
480
 
        
481
 
        cell_renderer = gtk.CellRendererText()
482
 
        cell_renderer.set_property("editable", True)
483
 
        
484
 
        column0 = gtk.TreeViewColumn("Key", cell_renderer, text=0)
485
 
        column1 = gtk.TreeViewColumn("Type", cell_renderer, text=1)
486
 
        column2 = gtk.TreeViewColumn("Value", cell_renderer, text=2)
487
 
        prop_tree_view.append_column(column0)
488
 
        prop_tree_view.append_column(column1)
489
 
        prop_tree_view.append_column(column2)
490
 
 
491
 
        prop_tree_view.set_model(store)
492
 
 
493
 
 
494
 
    def update_device_notebook(self, device):
495
 
        """Updates the entire notebook of tabs given a Device object"""
496
 
        self.update_tab_device(device)
497
 
        self.update_tab_advanced(device)
498
 
        self.update_tab_usb(device)
499
 
        self.update_tab_pci(device)