The last part started with the basic structure of the dbus part of the CD file listing utility and then showed the particular problems with the HAL implementation.
DeviceKit.Disks has to overcome similar problems, but due to the different concepts behind DeviceKit they have to be solved slightly differently.
DeviceKit.Disks
Like HAL, DeviceKit.Disks is another daemon handling devices and is offering similar services under different names. HAL is a jack of all trades, providing information about nearly everything in your system. This lead to its downfall, because the code base became huge and unmaintainable. DeviceKit on the other hand is split into individual more specialised daemons. DeviceKit.Disks is strictly focussed on disks and drives.
Differences to HAL from a programmers point of view:
(See part 2)
import gobject
import dbus
...
gobject.threads_init()
dbus.glib.threads_init()
Adding the callback
(See part 1)
bus = dbus.SystemBus()
devkit_object = bus.get_object("org.freedesktop.DeviceKit.Disks",
"/org/freedesktop/DeviceKit/Disks")
devkit_disks = dbus.Interface(devkit_object, 'org.freedesktop.DeviceKit.Disks')
devkit_disks.connect_to_signal('DeviceChanged', device_changed_callback)
...
def device_changed_callback(device):
print 'Device %s was changed' % (device)
Device properties in Devicekit.Disks
DeviceKit.Disks devices implement an interface named Properties which gives access to the device properties:
device_object = bus.get_object("org.freedesktop.DeviceKit.Disks", udi)
device_prop = dbus.Interface(device_object, "org.freedesktop.DBus.Properties")
property = device_prop.Get("org.freedesktop.DeviceKit.Disks.Device","name_of_property")
# or
all_properties = device_prop.GetAll("org.freedesktop.DeviceKit.Disks.Device")
Interesting properties are:
You can get a quick overview with human readable property names with
devkit-disks --dump | more
How to filter out events that are not CD related
The most promising way is to check DriveMediaCompatibility for the value optical_cd or optical_dvd.
device_object = bus.get_object("org.freedesktop.DeviceKit.Disks", udi)
device_prop = dbus.Interface(device_object, "org.freedesktop.DBus.Properties")
md = device_prop.Get("org.freedesktop.DeviceKit.Disks.Device","DriveMediaCompatibility")
print "is CD-ROM:", (u"optical_cd" in md) or (u"optical_dvd" in md)
If you observe the events (using the dbus-monitor) when inserting or ejecting a CD, the following patterns emerge:
(I haven't found any authoritative documentation yet, but the steps seem logical):
As DeviceKit.Disks does not provide the information which property was modified, we have to track the state of DeviceIsMounted ourselves and read the files below the mount point(s) when DeviceIsMounted changes from 0 to 1.
Eject via software
This function is located in the interface org.freedesktop.DeviceKit.Disks.Device. Note that a volume must be unmounted first before it can be ejected (see property DeviceIsMounted).
system_bus = dbus.SystemBus()
device_object = system_bus.get_object("org.freedesktop.DeviceKit.Disks", udi)
# get properties
device_prop = dbus.Interface(device_object, "org.freedesktop.DBus.Properties")
all_properties = device_prop.GetAll("org.freedesktop.DeviceKit.Disks.Device")
# call unmount/eject depending on the device state
disk_dev_func = dbus.Interface(device_object, "org.freedesktop.DeviceKit.Disks.Device")
if all_properties['DeviceIsMounted'] == 1:
disk_dev_func.FilesystemUnmount('')
if all_properties['DeviceIsOpticalDisc'] == 1:
disk_dev_func.DriveEject('')
With this, we have all the building blocks for DeviceKit.disks implementation of the CD file listing utility
DeviceKit.Disks has to overcome similar problems, but due to the different concepts behind DeviceKit they have to be solved slightly differently.
DeviceKit.Disks
Like HAL, DeviceKit.Disks is another daemon handling devices and is offering similar services under different names. HAL is a jack of all trades, providing information about nearly everything in your system. This lead to its downfall, because the code base became huge and unmaintainable. DeviceKit on the other hand is split into individual more specialised daemons. DeviceKit.Disks is strictly focussed on disks and drives.
Differences to HAL from a programmers point of view:
- As already seen: A different function is used to install the callbacks.
- The string given to the callback function (e.g. /org/freedesktop/DeviceKit/Disks/devices/sr0) is the name of a Devkit device. It points to a hardware device (e.g. the CDROM drive) not a volume (the inserted medium). And because the string already points to the hardware device we don't have to check for any parent object.
- Being a fixed drive, we also don't need the device_added_callback or device_removed_callback, because the physical CDROM device is not likely to be removed during the lifetime of the program and only changing the medium does not trigger these callbacks. (Note: A USB stick where the physical device itself is being unplugged does trigger these callbacks.).
- Which leaves the device_changed_callback. However, unlike HAL, there is no indication which property has changed when it is being triggered. We have to track the appropriate properties ourselves.
(See part 2)
import gobject
import dbus
...
gobject.threads_init()
dbus.glib.threads_init()
Adding the callback
(See part 1)
bus = dbus.SystemBus()
devkit_object = bus.get_object("org.freedesktop.DeviceKit.Disks",
"/org/freedesktop/DeviceKit/Disks")
devkit_disks = dbus.Interface(devkit_object, 'org.freedesktop.DeviceKit.Disks')
devkit_disks.connect_to_signal('DeviceChanged', device_changed_callback)
...
def device_changed_callback(device):
print 'Device %s was changed' % (device)
Device properties in Devicekit.Disks
DeviceKit.Disks devices implement an interface named Properties which gives access to the device properties:
device_object = bus.get_object("org.freedesktop.DeviceKit.Disks", udi)
device_prop = dbus.Interface(device_object, "org.freedesktop.DBus.Properties")
property = device_prop.Get("org.freedesktop.DeviceKit.Disks.Device","name_of_property")
# or
all_properties = device_prop.GetAll("org.freedesktop.DeviceKit.Disks.Device")
Interesting properties are:
- DriveMediaCompatibility
description: hardware compatibility
typical values: optical_cd, optical_cd_r, optical_cd_rw, optical_dvd, optical_dvd_r, optical_dvd_ram - DeviceIsOpticalDisc
typical values: 0/1
0: disk tray empty
1: optical media has been found - DeviceIsMounted
typical values: 0/1
0: nothing mounted yet
1: valid DeviceMountPaths - IdLabel
description: label of CD/DVD - DeviceMountPaths
descirption: mount point, if a CD/DVD has been mounted - OpticalDiscIsBlank
typical values: 0/1
0: media in the drive is not blank
1: media in the drive is blank - DeviceIsRemovable
typical values: 0/1
1: device can contain removable media (-> Eject should work)
You can get a quick overview with human readable property names with
devkit-disks --dump | more
How to filter out events that are not CD related
The most promising way is to check DriveMediaCompatibility for the value optical_cd or optical_dvd.
device_object = bus.get_object("org.freedesktop.DeviceKit.Disks", udi)
device_prop = dbus.Interface(device_object, "org.freedesktop.DBus.Properties")
md = device_prop.Get("org.freedesktop.DeviceKit.Disks.Device","DriveMediaCompatibility")
print "is CD-ROM:", (u"optical_cd" in md) or (u"optical_dvd" in md)
If you observe the events (using the dbus-monitor) when inserting or ejecting a CD, the following patterns emerge:
(I haven't found any authoritative documentation yet, but the steps seem logical):
- When the CDROM tray is empty:
DeviceIsOpticalDisc == 0 - Blank medium inserted:
DeviceIsOpticalDisc == 1
OpticalDiscIsBlank == 1 - After ejecting the blank medium:
DeviceIsOpticalDisc == 0
- Insert a medium containing data
- step 1 (medium gets recognized):
DeviceIsOpticalDisc == 1
OpticalDiscIsBlank == 0
DeviceIsMounted == 0 - step 2 (medium gets auto mounted):
DeviceIsOpticalDisc == 1
OpticalDiscIsBlank == 0
DeviceIsMounted == 1
- step 1 (medium gets recognized):
- eject medium:
- step 1 (auto umount)
DeviceIsOpticalDisc == 1
OpticalDiscIsBlank == 0
DeviceIsMounted == 0 - step 2 (eject)
DeviceIsOpticalDisc == 0
OpticalDiscIsBlank == 0
DeviceIsMounted == 0
- step 1 (auto umount)
- If DeviceIsOpticalDisc is being set to 1, the property IdLabel becomes valid.
- If DeviceIsMounted is being set to 1, the property DeviceMountPaths becomes valid.
As DeviceKit.Disks does not provide the information which property was modified, we have to track the state of DeviceIsMounted ourselves and read the files below the mount point(s) when DeviceIsMounted changes from 0 to 1.
Eject via software
This function is located in the interface org.freedesktop.DeviceKit.Disks.Device. Note that a volume must be unmounted first before it can be ejected (see property DeviceIsMounted).
system_bus = dbus.SystemBus()
device_object = system_bus.get_object("org.freedesktop.DeviceKit.Disks", udi)
# get properties
device_prop = dbus.Interface(device_object, "org.freedesktop.DBus.Properties")
all_properties = device_prop.GetAll("org.freedesktop.DeviceKit.Disks.Device")
# call unmount/eject depending on the device state
disk_dev_func = dbus.Interface(device_object, "org.freedesktop.DeviceKit.Disks.Device")
if all_properties['DeviceIsMounted'] == 1:
disk_dev_func.FilesystemUnmount('')
if all_properties['DeviceIsOpticalDisc'] == 1:
disk_dev_func.DriveEject('')
With this, we have all the building blocks for DeviceKit.disks implementation of the CD file listing utility
Keine Kommentare:
Kommentar veröffentlichen