gstlal  1.4.1
pipeutil.py
Go to the documentation of this file.
1 # Copyright (C) 2010 Leo Singer
2 #
3 # This program is free software; you can redistribute it and/or modify it
4 # under the terms of the GNU General Public License as published by the
5 # Free Software Foundation; either version 2 of the License, or (at your
6 # option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful, but
9 # WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11 # Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License along
14 # with this program; if not, write to the Free Software Foundation, Inc.,
15 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 
17 
18 
19 
20 """
21 
22 Boilerplate code, shorthand, and utility functions for creating GStreamer
23 elements and pipelines.
24 
25 """
26 __author__ = "Leo Singer <leo.singer@ligo.org>"
27 __organization__ = ["LIGO", "California Institute of Technology"]
28 __copyright__ = "Copyright 2010, Leo Singer"
29 __all__ = ["gstlal_element_register", "mkelem", "mkelems_in_bin", "splice"]
30 
31 
32 # The following snippet is taken from http://gstreamer.freedesktop.org/wiki/FAQ#Mypygstprogramismysteriouslycoredumping.2Chowtofixthis.3F
33 import gi
34 gi.require_version('Gst', '1.0')
35 from gi.repository import GObject
36 from gi.repository import Gst
37 GObject.threads_init()
38 Gst.init(None)
39 
40 
41 def gstlal_element_register(clazz):
42  """Class decorator for registering a Python element. Note that decorator
43  syntax was extended from functions to classes in Python 2.6, so until 2.6
44  becomes the norm we have to invoke this as a function instead of by
45  saying::
46 
47  @gstlal_element_register
48  class foo(Gst.Element):
49  ...
50 
51  Until then, you have to do::
52 
53  class foo(Gst.Element):
54  ...
55  gstlal_element_register(foo)
56  """
57  from inspect import getmodule
58  GObject.type_register(clazz) # MOD: Found type_register in line: [ gobject.type_register(clazz)]
59  getmodule(clazz).__gstelementfactory__ = (clazz.__name__, Gst.RANK_NONE, clazz)
60  return clazz
61 
62 
63 def mkelem(elemname, props={}):
64  """Instantiate an element named elemname and optionally set some of its
65  properties from the dictionary props."""
66  elem = Gst.ElementFactory.make(elemname, None)
67  for (k, v) in props.iteritems():
68  elem.set_property(k, v)
69  return elem
70 
71 
72 def mkelems_in_bin(bin, *pipedesc):
73  """Create an array of elements from a list of tuples, add them to a bin,
74  link them sequentially, and return the list. Example:
75 
76  mkelem(bin, ('audiotestsrc', {'wave':9}), ('audioresample',))
77 
78  is equivalent to
79 
80  audiotestsrc wave=9 ! audioresample
81  """
82  elems = [mkelem(*elemdesc) for elemdesc in pipedesc]
83  for elem in elems:
84  bin.add(elem)
85  if len(elems) > 1:
86  Gst.element_link_many(*elems) # MOD: Error line [87]: element_link_many not yet implemented. See web page **
87  return elems
88 
89 
90 
91 def splice(bin, pad, element):
92  """Splice element into an existing bin by teeing off an existing pad.
93 
94  If necessary, a tee is added to the pipeline in order to splice the new element.
95 
96  bin is an instance of Gst.Bin or Gst.Pipeline. pad is a string that
97  describes any pad inside that bin. The syntax used in gst-launch is
98  understood. For example, the string 'foo.bar.bat' means the pad called 'bat'
99  on the element called 'bar' in the bin called 'foo' inside bin. 'foo.bar.'
100  refers to any pad on the element 'bar'. element_or_pad is either an element
101  or a pad.
102 
103  FIXME: implicit pad names not yet understood.
104  """
105 
106  padpath = pad.split('.')
107  padname = padpath.pop()
108 
109  elem = bin
110  for name in padpath:
111  elem = elem.get_by_name(name)
112  if elem is None:
113  raise NameError("no such element: '%s'" % name)
114 
115  pad = elem.get_static_pad(padname)
116  if pad is None:
117  raise NameError("no such pad: '%s'" % padname)
118 
119  tee_type = Gst.element_factory_find('tee').get_element_type()
120 
121  tee = pad.get_parent_element()
122  if tee.__gtype__ != tee_type:
123  peer_pad = pad.get_peer()
124  if peer_pad is None:
125  if hasattr(element, 'get_direction'):
126  elem.get_static_pad('src').link(element)
127  else:
128  elem.link(element)
129  return
130  else:
131  peer_element = peer_pad.get_parent_element()
132  if peer_element.__gtype__ == tee_type:
133  tee = peer_element
134  else:
135  if pad.get_direction() == Gst.PadDirection.SINK:
136  pad, peer_pad = peer_pad, pad
137  pad.unlink(peer_pad)
138  tee = Gst.ElementFactory.make("tee", None)
139  bin.add(tee)
140  pad.link(tee.get_static_pad('sink'))
141  tee.get_request_pad('src%d').link(peer_pad)
142  if hasattr(element, 'get_direction'):
143  tee.get_request_pad('src%d').link(element)
144  else:
145  tee.link(element)