Package flumotion :: Package common :: Module gstreamer
[hide private]

Source Code for Module flumotion.common.gstreamer

  1  # -*- Mode: Python; test-case-name: flumotion.test.test_common_gstreamer -*- 
  2  # vi:si:et:sw=4:sts=4:ts=4 
  3   
  4  # Flumotion - a streaming media server 
  5  # Copyright (C) 2004,2005,2006,2007,2008,2009 Fluendo, S.L. 
  6  # Copyright (C) 2010,2011 Flumotion Services, S.A. 
  7  # All rights reserved. 
  8  # 
  9  # This file may be distributed and/or modified under the terms of 
 10  # the GNU Lesser General Public License version 2.1 as published by 
 11  # the Free Software Foundation. 
 12  # This file is distributed without any warranty; without even the implied 
 13  # warranty of merchantability or fitness for a particular purpose. 
 14  # See "LICENSE.LGPL" in the source distribution for more information. 
 15  # 
 16  # Headers in this file shall remain intact. 
 17   
 18  """gstreamer helpers 
 19  """ 
 20   
 21  from twisted.internet import defer 
 22  # moving this down causes havoc when running this file directly for some reason 
 23  from flumotion.common import errors, log 
 24   
 25  import gobject 
 26  import gst 
 27   
 28  __version__ = "$Rev$" 
 29   
 30   
31 -def caps_repr(caps):
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
45 -def verbose_deep_notify_cb(object, orig, pspec, component):
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 # Filters 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
70 -def element_has_property(element, property_name):
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
83 -def element_factory_has_property(element_factory, property_name):
84 """ 85 Check if the given element factory has the given property. 86 87 @rtype: boolean 88 """ 89 # FIXME: find a better way than instantiating one 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
97 -def element_factory_has_property_value(element_factory, property_name, value):
98 """ 99 Check if the given element factory allows the given value 100 for the given property. 101 102 @rtype: boolean 103 """ 104 # FIXME: find a better way than instantiating one 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
114 -def element_factory_exists(name):
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
129 -def get_plugin_version(plugin_name):
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 # GstPython should have something for this, but doesn't. 147 148
149 -def get_state_change(old, new):
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
165 -def flumotion_reset_event():
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
171 -def event_is_flumotion_reset(event):
172 ''' Helper method to check if an event is a 'flumotion-reset' event ''' 173 return event.get_structure().get_name() == 'flumotion-reset'
174 175
176 -class StateChangeMonitor(dict, log.Loggable):
177
178 - def __init__(self):
179 # statechange -> [ deferred ] 180 dict.__init__(self)
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
191 - def state_changed(self, old, new):
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
201 - def have_error(self, curstate, message):
202 # if we have a state change defer that has not yet 203 # fired, we should errback it 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