1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 """gstreamer helpers
19 """
20
21 from twisted.internet import defer
22
23 from flumotion.common import errors, log
24
25 import gobject
26 import gst
27
28 __version__ = "$Rev$"
29
30
32 """
33 Represent L{gst.Caps} as a string.
34
35 @rtype: string
36 """
37 value = str(caps)
38 pos = value.find('streamheader')
39 if pos != -1:
40 return 'streamheader=<...>'
41 else:
42 return value
43
44
46 """
47 A default deep-notify signal handler for pipelines.
48 """
49 value = orig.get_property(pspec.name)
50 if pspec.value_type == gobject.TYPE_BOOLEAN:
51 if value:
52 value = 'TRUE'
53 else:
54 value = 'FALSE'
55 output = value
56 elif pspec.value_type == gst.Caps.__gtype__:
57 output = caps_repr(value)
58 else:
59 output = value
60
61
62 if pspec.name == 'active':
63 return
64 if pspec.name == 'caps' and output == 'None':
65 return
66
67 component.debug('%s: %s = %r', orig.get_path_string(), pspec.name, output)
68
69
71 """
72 Check if the given element has the given property.
73
74 @rtype: boolean
75 """
76 try:
77 element.get_property(property_name)
78 return True
79 except TypeError:
80 return False
81
82
84 """
85 Check if the given element factory has the given property.
86
87 @rtype: boolean
88 """
89
90 e = gst.element_factory_make(element_factory)
91 for pspec in gobject.list_properties(e):
92 if pspec.name == property_name:
93 return True
94 return False
95
96
98 """
99 Check if the given element factory allows the given value
100 for the given property.
101
102 @rtype: boolean
103 """
104
105 e = gst.element_factory_make(element_factory)
106 try:
107 e.set_property(property_name, value)
108 except TypeError:
109 return False
110
111 return True
112
113
115 """
116 Check if the given element factory name exists.
117
118 @rtype: boolean
119 """
120 registry = gst.registry_get_default()
121 factory = registry.find_feature(name, gst.TYPE_ELEMENT_FACTORY)
122
123 if factory:
124 return True
125
126 return False
127
128
130 """
131 Find the version of the given plugin.
132
133 @rtype: tuple of (major, minor, micro, nano), or None if it could not be
134 found or determined
135 """
136 plugin = gst.registry_get_default().find_plugin(plugin_name)
137
138 if not plugin:
139 return None
140
141 versionTuple = tuple([int(x) for x in plugin.get_version().split('.')])
142 if len(versionTuple) < 4:
143 versionTuple = versionTuple + (0, )
144 return versionTuple
145
146
147
148
150 table = {(gst.STATE_NULL, gst.STATE_READY):
151 gst.STATE_CHANGE_NULL_TO_READY,
152 (gst.STATE_READY, gst.STATE_PAUSED):
153 gst.STATE_CHANGE_READY_TO_PAUSED,
154 (gst.STATE_PAUSED, gst.STATE_PLAYING):
155 gst.STATE_CHANGE_PAUSED_TO_PLAYING,
156 (gst.STATE_PLAYING, gst.STATE_PAUSED):
157 gst.STATE_CHANGE_PLAYING_TO_PAUSED,
158 (gst.STATE_PAUSED, gst.STATE_READY):
159 gst.STATE_CHANGE_PAUSED_TO_READY,
160 (gst.STATE_READY, gst.STATE_NULL):
161 gst.STATE_CHANGE_READY_TO_NULL}
162 return table.get((old, new), 0)
163
164
166 ''' Helper method to create a 'flumotion-reset' event '''
167 return gst.event_new_custom(gst.EVENT_CUSTOM_DOWNSTREAM,
168 gst.Structure('flumotion-reset'))
169
170
172 ''' Helper method to check if an event is a 'flumotion-reset' event '''
173 return event.get_structure().get_name() == 'flumotion-reset'
174
175
177
181
182 - def add(self, statechange):
183 if statechange not in self:
184 self[statechange] = []
185
186 d = defer.Deferred()
187 self[statechange].append(d)
188
189 return d
190
192 self.log('state change: pipeline %s->%s',
193 old.value_nick, new.value_nick)
194 change = get_state_change(old, new)
195 if change in self:
196 dlist = self[change]
197 for d in dlist:
198 d.callback(None)
199 del self[change]
200
202
203
204 changes = [gst.STATE_CHANGE_NULL_TO_READY,
205 gst.STATE_CHANGE_READY_TO_PAUSED,
206 gst.STATE_CHANGE_PAUSED_TO_PLAYING]
207
208 extras = ((gst.STATE_PAUSED, gst.STATE_CHANGE_PLAYING_TO_PAUSED),
209 (gst.STATE_READY, gst.STATE_CHANGE_PAUSED_TO_READY),
210 (gst.STATE_NULL, gst.STATE_CHANGE_READY_TO_NULL))
211 for state, change in extras:
212 if curstate <= state:
213 changes.append(change)
214
215 for change in changes:
216 if change in self:
217 self.log("We have an error, going to errback pending "
218 "state change defers")
219 gerror, debug = message.parse_error()
220 for d in self[change]:
221 d.errback(errors.GStreamerGstError(
222 message.src, gerror, debug))
223 del self[change]
224