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 Fluendo, S.L. (www.fluendo.com). 
  6  # All rights reserved. 
  7   
  8  # This file may be distributed and/or modified under the terms of 
  9  # the GNU General Public License version 2 as published by 
 10  # the Free Software Foundation. 
 11  # This file is distributed without any warranty; without even the implied 
 12  # warranty of merchantability or fitness for a particular purpose. 
 13  # See "LICENSE.GPL" in the source distribution for more information. 
 14   
 15  # Licensees having purchased or holding a valid Flumotion Advanced 
 16  # Streaming Server license may use this file in accordance with the 
 17  # Flumotion Advanced Streaming Server Commercial License Agreement. 
 18  # See "LICENSE.Flumotion" in the source distribution for more information. 
 19   
 20  # Headers in this file shall remain intact. 
 21   
 22  """gstreamer helpers 
 23  """ 
 24   
 25  from twisted.internet import defer 
 26  # moving this down causes havoc when running this file directly for some reason 
 27  from flumotion.common import errors, log 
 28   
 29  import gobject 
 30  import gst 
 31   
 32  __version__ = "$Rev: 7162 $" 
 33   
 34   
35 -def caps_repr(caps):
36 """ 37 Represent L{gst.Caps} as a string. 38 39 @rtype: string 40 """ 41 value = str(caps) 42 pos = value.find('streamheader') 43 if pos != -1: 44 return 'streamheader=<...>' 45 else: 46 return value
47 48
49 -def verbose_deep_notify_cb(object, orig, pspec, component):
50 """ 51 A default deep-notify signal handler for pipelines. 52 """ 53 value = orig.get_property(pspec.name) 54 if pspec.value_type == gobject.TYPE_BOOLEAN: 55 if value: 56 value = 'TRUE' 57 else: 58 value = 'FALSE' 59 output = value 60 elif pspec.value_type == gst.Caps.__gtype__: 61 output = caps_repr(value) 62 else: 63 output = value 64 65 # Filters 66 if pspec.name == 'active': 67 return 68 if pspec.name == 'caps' and output == 'None': 69 return 70 71 component.debug('%s: %s = %r', orig.get_path_string(), pspec.name, output)
72 73
74 -def element_factory_has_property(element_factory, property_name):
75 """ 76 Check if the given element factory has the given property. 77 78 @rtype: boolean 79 """ 80 # FIXME: find a better way than instantiating one 81 e = gst.element_factory_make(element_factory) 82 for pspec in gobject.list_properties(e): 83 if pspec.name == property_name: 84 return True 85 return False
86 87
88 -def element_factory_has_property_value(element_factory, property_name, value):
89 """ 90 Check if the given element factory allows the given value 91 for the given property. 92 93 @rtype: boolean 94 """ 95 # FIXME: find a better way than instantiating one 96 e = gst.element_factory_make(element_factory) 97 try: 98 e.set_property(property_name, value) 99 except TypeError: 100 return False 101 102 return True
103 104
105 -def element_factory_exists(name):
106 """ 107 Check if the given element factory name exists. 108 109 @rtype: boolean 110 """ 111 registry = gst.registry_get_default() 112 factory = registry.find_feature(name, gst.TYPE_ELEMENT_FACTORY) 113 114 if factory: 115 return True 116 117 return False
118 119
120 -def get_plugin_version(plugin_name):
121 """ 122 Find the version of the given plugin. 123 124 @rtype: tuple of (major, minor, micro, nano), or None if it could not be 125 found or determined 126 """ 127 plugin = gst.registry_get_default().find_plugin(plugin_name) 128 129 if not plugin: 130 return None 131 132 versionTuple = tuple([int(x) for x in plugin.get_version().split('.')]) 133 if len(versionTuple) < 4: 134 versionTuple = versionTuple + (0, ) 135 return versionTuple
136 137 # GstPython should have something for this, but doesn't. 138 139
140 -def get_state_change(old, new):
141 table = {(gst.STATE_NULL, gst.STATE_READY): 142 gst.STATE_CHANGE_NULL_TO_READY, 143 (gst.STATE_READY, gst.STATE_PAUSED): 144 gst.STATE_CHANGE_READY_TO_PAUSED, 145 (gst.STATE_PAUSED, gst.STATE_PLAYING): 146 gst.STATE_CHANGE_PAUSED_TO_PLAYING, 147 (gst.STATE_PLAYING, gst.STATE_PAUSED): 148 gst.STATE_CHANGE_PLAYING_TO_PAUSED, 149 (gst.STATE_PAUSED, gst.STATE_READY): 150 gst.STATE_CHANGE_PAUSED_TO_READY, 151 (gst.STATE_READY, gst.STATE_NULL): 152 gst.STATE_CHANGE_READY_TO_NULL} 153 return table.get((old, new), 0)
154 155
156 -class StateChangeMonitor(dict, log.Loggable):
157
158 - def __init__(self):
159 # statechange -> [ deferred ] 160 dict.__init__(self)
161
162 - def add(self, statechange):
163 if statechange not in self: 164 self[statechange] = [] 165 166 d = defer.Deferred() 167 self[statechange].append(d) 168 169 return d
170
171 - def state_changed(self, old, new):
172 self.log('state change: pipeline %s->%s', 173 old.value_nick, new.value_nick) 174 change = get_state_change(old, new) 175 if change in self: 176 dlist = self[change] 177 for d in dlist: 178 d.callback(None) 179 del self[change]
180
181 - def have_error(self, curstate, message):
182 # if we have a state change defer that has not yet 183 # fired, we should errback it 184 changes = [gst.STATE_CHANGE_NULL_TO_READY, 185 gst.STATE_CHANGE_READY_TO_PAUSED, 186 gst.STATE_CHANGE_PAUSED_TO_PLAYING] 187 188 extras = ((gst.STATE_PAUSED, gst.STATE_CHANGE_PLAYING_TO_PAUSED), 189 (gst.STATE_READY, gst.STATE_CHANGE_PAUSED_TO_READY), 190 (gst.STATE_NULL, gst.STATE_CHANGE_READY_TO_NULL)) 191 for state, change in extras: 192 if curstate <= state: 193 changes.append(change) 194 195 for change in changes: 196 if change in self: 197 self.log("We have an error, going to errback pending " 198 "state change defers") 199 gerror, debug = message.parse_error() 200 for d in self[change]: 201 d.errback(errors.GStreamerGstError( 202 message.src, gerror, debug)) 203 del self[change]
204