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  """ 
 23  GStreamer helper functionality 
 24  """ 
 25   
 26  from twisted.internet import defer 
 27  # moving this down causes havoc when running this file directly for some reason 
 28  from flumotion.common import errors, log 
 29   
 30  import gobject 
 31  import gst 
 32   
33 -def caps_repr(caps):
34 """ 35 Represent L{gst.Caps} as a string. 36 37 @rtype: string 38 """ 39 value = str(caps) 40 pos = value.find('streamheader') 41 if pos != -1: 42 return 'streamheader=<...>' 43 else: 44 return value
45
46 -def verbose_deep_notify_cb(object, orig, pspec, component):
47 """ 48 A default deep-notify signal handler for pipelines. 49 """ 50 value = orig.get_property(pspec.name) 51 if pspec.value_type == gobject.TYPE_BOOLEAN: 52 if value: 53 value = 'TRUE' 54 else: 55 value = 'FALSE' 56 output = value 57 elif pspec.value_type == gst.Caps.__gtype__: 58 output = caps_repr(value) 59 else: 60 output = value 61 62 # Filters 63 if pspec.name == 'active': 64 return 65 if pspec.name == 'caps' and output == 'None': 66 return 67 68 component.debug('%s: %s = %s' % (orig.get_path_string(), pspec.name, output))
69
70 -def element_factory_has_property(element_factory, property_name):
71 """ 72 Check if the given element factory has the given property. 73 74 @rtype: boolean 75 """ 76 # FIXME: find a better way than instantiating one 77 e = gst.element_factory_make(element_factory) 78 for pspec in gobject.list_properties(e): 79 if pspec.name == property_name: 80 return True 81 return False
82
83 -def element_factory_has_property_value(element_factory, property_name, value):
84 """ 85 Check if the given element factory allows the given value for 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 try: 92 e.set_property(property_name, value) 93 except TypeError: 94 return False 95 96 return True
97
98 -def element_factory_exists(name):
99 """ 100 Check if the given element factory name exists. 101 102 @rtype: boolean 103 """ 104 registry = gst.registry_get_default() 105 factory = registry.find_feature(name, gst.TYPE_ELEMENT_FACTORY) 106 107 if factory: 108 return True 109 110 return False
111
112 -def get_plugin_version(plugin_name):
113 """ 114 Find the version of the given plugin. 115 116 @rtype: tuple of (major, minor, micro, nano), or None if it could not be 117 found or determined 118 """ 119 plugin = gst.registry_get_default().find_plugin(plugin_name) 120 121 if not plugin: 122 return None 123 124 versionTuple = tuple([int(x) for x in plugin.get_version().split('.')]) 125 if len(versionTuple) < 4: 126 versionTuple = versionTuple + (0,) 127 return versionTuple
128 129 # GstPython should have something for this, but doesn't.
130 -def get_state_change(old, new):
131 table = {(gst.STATE_NULL, gst.STATE_READY): 132 gst.STATE_CHANGE_NULL_TO_READY, 133 (gst.STATE_READY, gst.STATE_PAUSED): 134 gst.STATE_CHANGE_READY_TO_PAUSED, 135 (gst.STATE_PAUSED, gst.STATE_PLAYING): 136 gst.STATE_CHANGE_PAUSED_TO_PLAYING, 137 (gst.STATE_PLAYING, gst.STATE_PAUSED): 138 gst.STATE_CHANGE_PLAYING_TO_PAUSED, 139 (gst.STATE_PAUSED, gst.STATE_READY): 140 gst.STATE_CHANGE_PAUSED_TO_READY, 141 (gst.STATE_READY, gst.STATE_NULL): 142 gst.STATE_CHANGE_READY_TO_NULL} 143 return table.get((old, new), 0)
144
145 -class StateChangeMonitor(dict, log.Loggable):
146 - def __init__(self):
147 # statechange -> [ deferred ] 148 dict.__init__(self)
149
150 - def add(self, statechange):
151 if statechange not in self: 152 self[statechange] = [] 153 154 d = defer.Deferred() 155 self[statechange].append(d) 156 157 return d
158
159 - def state_changed(self, old, new):
160 self.log('state change: pipeline %s->%s', 161 old.value_nick, new.value_nick) 162 change = get_state_change(old, new) 163 if change in self: 164 dlist = self[change] 165 for d in dlist: 166 d.callback(None) 167 del self[change]
168
169 - def have_error(self, curstate, message):
170 # if we have a state change defer that has not yet 171 # fired, we should errback it 172 changes = [gst.STATE_CHANGE_NULL_TO_READY, 173 gst.STATE_CHANGE_READY_TO_PAUSED, 174 gst.STATE_CHANGE_PAUSED_TO_PLAYING] 175 176 extras = ((gst.STATE_PAUSED, gst.STATE_CHANGE_PLAYING_TO_PAUSED), 177 (gst.STATE_READY, gst.STATE_CHANGE_PAUSED_TO_READY), 178 (gst.STATE_NULL, gst.STATE_CHANGE_READY_TO_NULL)) 179 for state, change in extras: 180 if curstate <= state: 181 changes.append(change) 182 183 for change in changes: 184 if change in self: 185 self.log("We have an error, going to errback pending " 186 "state change defers") 187 gerror, debug = message.parse_error() 188 for d in self[change]: 189 d.errback(errors.GStreamerGstError( 190 message.src, gerror, debug)) 191 del self[change]
192