The parent nodes could be showed/hided on the fly
[udev-discover:udev-discover.git] / udevdiscover / udevicefinder.py
1 # -*- coding: utf-8 -*-
2 # vim: ts=4 
3 ###
4 #
5 # Copyright (c) 2010 J. Félix Ontañón
6 #
7 # Almost based on arista.inputs module:
8 # Copyright 2008 - 2010 Daniel G. Taylor <dan@programmer-art.org>
9
10 # This program is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License version 3 as
12 # published by the Free Software Foundation
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 #
22 # Authors : J. Félix Ontañón <fontanon@emergya.es>
23
24
25 import gobject
26 import gudev
27 from usb import USBDevice
28 from pci import PCIDevice
29 from device import Device
30
31 class DeviceFinder(gobject.GObject):
32     '''
33     An object that will find and monitor Wiimote devices on your 
34     machine and emit signals when are connected / disconnected
35     '''
36     
37     __gsignals__ = {
38         'connected': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, 
39             (gobject.TYPE_PYOBJECT,)),
40         'disconnected': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, 
41             (gobject.TYPE_PYOBJECT,)),
42     }
43     
44     def __init__(self, subsystems=['*'], parent_tree=False):
45         '''
46         Create a new DeviceFinder and attach to the udev system to 
47         listen for events.
48         '''
49         self.__gobject_init__()
50
51         self.client = gudev.Client(subsystems)
52         self.subsystems = subsystems
53         self.devices_tree = {}
54         self.devices_list = []
55
56         def explore_parent(device, devices_tree, devices_list):
57             path = device.get_sysfs_path()        
58             parent = device.get_parent()
59
60             if parent:
61                 explore_parent(parent, devices_tree, devices_list)
62                 devices_tree[path] = self.get_device_object(device)
63             else:
64                 devices_tree[path] = self.get_device_object(device)
65                 
66             dev = self.get_device_object(device)
67             if not dev in devices_list:
68                 devices_list.append(dev)
69
70         for subsystem in subsystems:
71             for device in self.client.query_by_subsystem(subsystem):
72                 if parent_tree: 
73                     explore_parent(device, self.devices_tree, self.devices_list)
74                 else:
75                     self.devices_list.append(self.get_device_object(device))
76                     self.devices_tree[device.get_sysfs_path()] = \
77                         self.get_device_object(device)
78
79         self.client.connect('uevent', self.event)
80
81     def get_device_object(self, device):
82         #FIXME: Devices needs a creation factory pattern
83         subsys = device.get_subsystem()
84         if subsys == 'usb':
85             dev = USBDevice(device)
86         elif subsys == 'pci':
87             dev = PCIDevice(device)
88         else:
89             dev = Device(device)
90         
91         return dev
92
93     def get_devices_tree(self):
94         return self.devices_tree
95         
96     def get_devices(self):
97         return self.devices_list
98         #return [device_tuple[0] for sysfs_path, device_tuple in self.devices.items()]
99
100     def event(self, client, action, device):
101         '''Handle a udev event'''
102         
103         return {
104             'add': self.device_added,
105 #            'change': self.device_changed,
106 #            'remove': self.device_removed,
107         }.get(action, lambda x,y: None)(device, device.get_subsystem())
108
109     def device_added(self, device, subsystem):
110         '''Called when a device has been added to the system'''
111         
112         print device, subsystem
113         
114         path = device.get_sysfs_path()
115         self.devices_tree[path] = Device(device)
116         self.devices_list.append(Device(device))
117         self.emit('connected', device)
118
119 gobject.type_register(DeviceFinder)
120
121 if __name__ == '__main__':
122     import gobject
123     
124     def found(finder, device):
125         print device.path + ': ' + device.nice_label
126     
127     def lost(finder, device):
128         print device.path + ': ' + device.nice_label
129     
130     finder = DeviceFinder()
131     finder.connect('connected', found)
132     finder.connect('disconnected', lost)
133     
134     import pprint
135     pprint.pprint(finder.devices_tree)
136     
137     loop = gobject.MainLoop()
138     loop.run()