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