We’ve seen how to connect to DBus and UDisks, then how to check some UDisks daemon settings and informations and how to query for devices. All of this isn’t so "usable" if you don’t know when a new device is connected to your PC. Of course that you could periodically poll for new devices, but this isn’t a nice solution. For a "real time" device detection, we can use signals.
There are many signals in this UDisks specifications but the most useful (in our case) are:
- The DeviceAdded Signal - Emitted when a device is added.
- The DeviceRemoved Signal - Emitted when a device is removed.
- The DeviceChanged Signal - Emitted when a device property has changed.
These descriptions were taken from UDisks Reference Manual (not on-line anymore).
Now lets see a little python snippet that shows how to work with signals.
>>> import dbus #Import necessary modules >>> import gobject >>> from dbus.mainloop.glib import DBusGMainLoop >>> >>> DBusGMainLoop(set_as_default=True) #Inform that a main loop will be used >>> >>> bus = dbus.SystemBus() #Start Dbus >>> proxy = bus.get_object("org.freedesktop.UDisks", "/org/freedesktop/UDisks") >>> iface = dbus.Interface(proxy, "org.freedesktop.UDisks") >>> >>> def on_device_add(dev_path): ... print 'Added',dev_path ... >>> def on_device_changed(dev_path): ... print 'Changed',dev_path ... >>> def on_device_removed(dev_path): ... print 'Removed',dev_path ... >>> >>> iface.connect_to_signal('DeviceAdded', on_device_add) < at 9cb8b0c "type='signal',sender=':1.38',path='/org/freedesktop/UDisks',interface='org.freedesktop.UDisks',member='DeviceAdded'" on conn > >>> iface.connect_to_signal('DeviceChanged', on_device_changed) < at 9cb8c2c "type='signal',sender=':1.38',path='/org/freedesktop/UDisks',interface='org.freedesktop.UDisks',member='DeviceChanged'" on conn > >>> iface.connect_to_signal('DeviceRemoved', on_device_removed) < at 9cb8cec "type='signal',sender=':1.38',path='/org/freedesktop/UDisks',interface='org.freedesktop.UDisks',member='DeviceRemoved'" on conn > >>> >>> loop = gobject.MainLoop() >>> loop.run() Added /org/freedesktop/UDisks/devices/sdc Added /org/freedesktop/UDisks/devices/sdc1 Changed /org/freedesktop/UDisks/devices/sdc1 Changed /org/freedesktop/UDisks/devices/sdc1 Changed /org/freedesktop/UDisks/devices/sdc Removed /org/freedesktop/UDisks/devices/sdc1 Removed /org/freedesktop/UDisks/devices/sdc
After the loop.run() statement the program appears to be "suspended", but it’s only watching for some signal. After that, I inserted a flash drive and it was automatically mounted. Then I unmounted it and removed. At first look (at least if you’re only looking at the static output above) this output seems to be duplicated. But it has a reason…
- The first two lines, notifies that a new "root device" (partition table) was detected (sdc), then a "new partition" (sdc1) was detected. If your flash drive has more then one partition, would be presented more notifications.
- The third output line notifies that the partition sdc1 was mounted.
- The fourth, fifth and sixth lines notifies that the device was unmounted (both partitions) and the partition "removed".
- And the last notifies that the device was truly removed.
Now thats seems a lot more clear, doesn’t it? So, when checking for new or removed devices is interesting to filter those notifications and use only the relevant ones. This can be done querying some information about the device. I’ll show how to do this in the next post.