1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 __version__ = "$Rev: 8057 $"
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 sound_system))
119
120 m.id = mid
121 result.add(m)
122
123 return defer.succeed(result)
124
125
127 """
128 Probe the given GStreamer element factory with the given device for
129 audio mixer tracks.
130 Return a deferred firing a result.
131
132 The result is either:
133 - succesful, with a None value: no device found
134 - succesful, with a human-readable device name and a list of mixer
135 track labels.
136 - failed
137
138 @rtype: L{twisted.internet.defer.Deferred}
139 """
140 result = messages.Result()
141
142 def get_tracks(element):
143
144 if not element.implements_interface(gst.interfaces.Mixer):
145 msg = 'Cannot get mixer tracks from the device. '\
146 'Check permissions on the mixer device.'
147 log.debug('checks', "returning failure: %s" % msg)
148 raise check.CheckProcError(msg)
149
150 devName = element.get_property('device-name')
151 tracks = [track.label for track in element.list_tracks()]
152 structs = []
153 for structure in element.get_pad('src').get_caps():
154 structDict = dict(structure)
155 for key, value in structDict.items()[:]:
156
157 if isinstance(value, gst.IntRange):
158 structDict[key] = (value.high, value.low)
159 structs.append(structDict)
160 return (devName, tracks, structs)
161
162 def errbackAlsaBugResult(failure, result, mid, device):
163
164
165 if not failure.check(errors.GStreamerGstError):
166 return failure
167 if source_factory != 'alsasrc':
168 return failure
169 version = gstreamer.get_plugin_version('alsasrc')
170 if version > (0, 10, 14):
171 return failure
172
173 source, gerror, debug = failure.value.args
174 log.debug('check',
175 'GStreamer GError: %s (domain %s, code %d, debug %s)' % (
176 gerror.message, gerror.domain, gerror.code, debug))
177
178 if gerror.domain == "gst-resource-error-quark":
179 if gerror.code == int(gst.RESOURCE_ERROR_OPEN_WRITE):
180 m = messages.Error(T_(
181 N_("Could not open device '%s' for reading. "
182 "Check permissions on the device."), device))
183 result.add(m)
184 return result
185
186 return failure
187
188 pipeline = ('%s name=source device=%s ! fakesink') % (
189 source_factory, device)
190 d = do_element_check(pipeline, 'source', get_tracks,
191 set_state_deferred=True)
192
193 pipeline = ('%s name=source device=%s ! fakesink') % (
194 source_factory, device)
195 d = do_element_check(pipeline, 'source', get_tracks,
196 set_state_deferred=True)
197
198 d.addCallback(check.callbackResult, result)
199 d.addErrback(check.errbackNotFoundResult, result, mid, device)
200 d.addErrback(errbackAlsaBugResult, result, mid, device)
201 d.addErrback(check.errbackResult, result, mid, device)
202
203 return d
204