-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdiscmonitor.py
131 lines (105 loc) · 4.29 KB
/
discmonitor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/usr/bin/python
"""
Module for monitoring optical drives.
"""
import os, sys
import dbus
import gobject
import thread
from dbus.mainloop import glib
from common_util import Error, Warn, Msg, Babble, Die
###########################
# Device monitoring/dbus #
###########################
def debugEvt(dev_name, dev_path, props):
sep = ("=" * 60) + "\n"
s = sep + "ChangedEvent from %s at %s received\n" % (dev_name, dev_path) + sep
for k,v in props.iteritems():
s += "%s : %s\n" % (k,v)
return s
def convertDBusTypes(obj):
"""Convert DBus objects to native python formats.
Because I like it better this way."""
typ = type(obj).__name__.lower()
if 'int' in typ or typ == 'byte':
obj = int(obj)
elif 'string' in typ:
obj = str(obj)
elif 'bool' in typ:
obj = bool(obj)
elif 'float' in typ:
obj = float(obj)
elif 'double' in typ:
obj = float(obj)
elif 'array' in typ:
obj = [convertDBusTypes(x) for x in obj]
elif 'dictionary' in typ:
obj = dict([(convertDBusTypes(k), convertDBusTypes(v))
for k,v in obj.iteritems()])
return obj
def deviceProperties(bus, dbus_dev_addr):
"""Return all properties of a device (given by its DBus address, e.g.
'/org/freedesktop/UDisks/devices/sr0') as a dictionary."""
dev_obj = bus.get_object("org.freedesktop.UDisks", dbus_dev_addr)
dev_props = dbus.Interface(dev_obj, "org.freedesktop.DBus.Properties")
d = {}
for prop in dev_props.GetAll(''):
val = dev_props.Get('', prop)
d[str(prop)] = convertDBusTypes(val)
return d
def deviceChangedCallback(bus, dev_name, dev_path, ripper):
"""Called when (among other things) a disk is inserted."""
devprops = deviceProperties(bus, dev_path)
closed, avail, blank = [devprops[x] for x in (
'OpticalDiscIsClosed',
'DeviceIsMediaAvailable',
'OpticalDiscIsBlank')]
disc_kind = devprops['DriveMedia']
if closed and avail and not blank:
# each rip job gets its own thread.
# we do this so that we don't block the udev monitoring loop, and
# also any exceptions in the rip thread will not terminate the main
# daemon thread.
discID = None
if 'IdLabel' in devprops:
discID = devprops['IdLabel']
if 'optical_bd' in disc_kind:
Msg('blu-ray inserted into %s' % dev_name)
# call ripper.ripBluRay in a dedicated thread, passing dev_name
thread.start_new_thread(ripper.ripBluRay, (dev_name, discID))
elif 'optical_dvd' in disc_kind:
Msg('dvd inserted into %s' % dev_name)
thread.start_new_thread(ripper.ripDVD, (dev_name, discID))
else:
Msg('%s inserted into %s; not ripping' % (disc_kind, dev_name))
def monitorDevices(device_array, ripper):
# this is needed to ensure threading works:
import gobject
gobject.threads_init()
# this is needed to monitor for callbacks:
glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()
udisks = bus.get_object('org.freedesktop.UDisks',
'/org/freedesktop/UDisks')
udisks = dbus.Interface(udisks, 'org.freedesktop.UDisks')
for dev in device_array:
try:
dev_path = udisks.FindDeviceByDeviceFile(dev)
dev_obj = bus.get_object("org.freedesktop.UDisks", dev_path)
dev_ifc = dbus.Interface(dev_obj,
"org.freedesktop.UDisks.Device")
# We use a lambda to store the device name with the callback
# so we can tell which drive was changed from inside the function
cbak = lambda: deviceChangedCallback(bus, dev, dev_path, ripper)
dev_ifc.connect_to_signal('Changed', cbak)
Msg("Monitoring %s" % dev)
except:
Warn("Device %s not found; will not monitor events" % dev)
# begin monitoring
mainloop = gobject.MainLoop()
try:
mainloop.run()
except KeyboardInterrupt:
# For some reason, this is raised when the daemon terminates with a
# SIGTERM. I don't understand why this happens.
pass