1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 __version__ = "$Rev$"
23
24 import gst
25 import dbus
26
27 from flumotion.common import messages, log, errors, gstreamer
28 from flumotion.common.i18n import N_, gettexter
29 from flumotion.worker.checks import check
30 from twisted.internet import defer
31
32 from gst010 import do_element_check
33
34 T_ = gettexter()
35
36
38 """
39 Search the available devices in worker for the specified factory.
40 Return a deferred firing a result.
41
42 The result is either:
43 - succesful, with an empty list: no device found
44 - succesful, with the list of found devices
45 - failed
46
47 @rtype: L{twisted.internet.defer.Deferred}
48 """
49 result = messages.Result()
50 devices = []
51
52 def getOssDevices():
53 bus = dbus.SystemBus()
54 hal = dbus.Interface(bus.get_object('org.freedesktop.Hal',
55 '/org/freedesktop/Hal/Manager'),
56 'org.freedesktop.Hal.Manager')
57 udis = hal.FindDeviceStringMatch('oss.type', 'pcm')
58
59 for udi in udis:
60 dev = dbus.Interface(bus.get_object('org.freedesktop.Hal', udi),
61 'org.freedesktop.Hal.Device')
62 if not dev.PropertyExists('oss.device'):
63 continue
64 if dev.GetProperty('oss.device') != 0:
65 continue
66
67 devices.append((str(dev.GetProperty('info.product')),
68 str(dev.GetProperty('oss.device_file'))))
69
70 def getAlsaDevices():
71 source = gst.element_factory_make('alsasrc')
72 pipeline = 'alsasrc name=source device=%s ! fakesink'
73
74 for device in source.probe_get_values_name('device'):
75 p = gst.parse_launch(pipeline % device)
76 p.set_state(gst.STATE_READY)
77 s = p.get_by_name('source')
78 devices.append((s.get_property('device-name'),
79 device.split(',')[0]))
80 p.set_state(gst.STATE_NULL)
81
82 try:
83 {'alsasrc': getAlsaDevices,
84 'osssrc': getOssDevices}[source_factory]()
85
86 except dbus.DBusException, e:
87 devices = [("/dev/dsp", "/dev/dsp"),
88 ("/dev/dsp1", "/dev/dsp1"),
89 ("/dev/dsp2", "/dev/dsp2")]
90
91 result.succeed(devices)
92
93 failure = defer.failure.Failure()
94 m = messages.Warning(T_(
95 N_("There has been an error while fetching the OSS audio devices "
96 "through Hal.\nThe listed devices have been guessed and may "
97 "not work properly.")), debug=check.debugFailure(failure))
98 m.id = mid
99 result.add(m)
100 return defer.succeed(result)
101 except:
102 failure = defer.failure.Failure()
103 log.debug('check', 'unhandled failure: %r (%s)\nTraceback:\n%s' % (
104 failure, failure.getErrorMessage(), failure.getTraceback()))
105 m = messages.Error(T_(N_("Could not probe devices.")),
106 debug=check.debugFailure(failure))
107
108 m.id = mid
109 result.add(m)
110 return defer.fail(result)
111 else:
112 result.succeed(devices)
113 if not devices:
114 m = messages.Error(T_(
115 N_("Could not find any device in the system.\n"
116 "Please check whether the device is correctly plugged "
117 "in and whether the modules are correctly loaded.")))
118
119 m.id = mid
120 result.add(m)
121
122 return defer.succeed(result)
123
124
126 """
127 Probe the given GStreamer element factory with the given device for
128 audio mixer tracks.
129 Return a deferred firing a result.
130
131 The result is either:
132 - succesful, with a None value: no device found
133 - succesful, with a human-readable device name and a list of mixer
134 track labels.
135 - failed
136
137 @rtype: L{twisted.internet.defer.Deferred}
138 """
139 result = messages.Result()
140
141 def get_tracks(element):
142
143 if not element.implements_interface(gst.interfaces.Mixer):
144 msg = 'Cannot get mixer tracks from the device. '\
145 'Check permissions on the mixer device.'
146 log.debug('checks', "returning failure: %s" % msg)
147 raise check.CheckProcError(msg)
148
149 devName = element.get_property('device-name')
150 tracks = [track.label for track in element.list_tracks()]
151 structs = []
152 for structure in element.get_pad('src').get_caps():
153 structDict = dict(structure)
154 for key, value in structDict.items()[:]:
155
156 if isinstance(value, gst.IntRange):
157 structDict[key] = (value.high, value.low)
158 structs.append(structDict)
159 return (devName, tracks, structs)
160
161 def errbackAlsaBugResult(failure, result, mid, device):
162
163
164 if not failure.check(errors.GStreamerGstError):
165 return failure
166 if source_factory != 'alsasrc':
167 return failure
168 version = gstreamer.get_plugin_version('alsasrc')
169 if version > (0, 10, 14):
170 return failure
171
172 source, gerror, debug = failure.value.args
173 log.debug('check',
174 'GStreamer GError: %s (domain %s, code %d, debug %s)' % (
175 gerror.message, gerror.domain, gerror.code, debug))
176
177 if gerror.domain == "gst-resource-error-quark":
178 if gerror.code == int(gst.RESOURCE_ERROR_OPEN_WRITE):
179 m = messages.Error(T_(
180 N_("Could not open device '%s' for reading. "
181 "Check permissions on the device."), device))
182 result.add(m)
183 return result
184
185 return failure
186
187 pipeline = ('%s name=source device=%s ! fakesink') % (
188 source_factory, device)
189 d = do_element_check(pipeline, 'source', get_tracks,
190 set_state_deferred=True)
191
192 d.addCallback(check.callbackResult, result)
193 d.addErrback(check.errbackNotFoundResult, result, mid, device)
194 d.addErrback(errbackAlsaBugResult, result, mid, device)
195 d.addErrback(check.errbackResult, result, mid, device)
196
197 return d
198