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