gstlal  0.8.1
 All Classes Namespaces Files Functions Variables Pages
simplehandler.py
Go to the documentation of this file.
1 # Copyright (C) 2009--2013 Kipp Cannon, Chad Hanna, Drew Keppel
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 # Preamble
22 #
23 # =============================================================================
24 #
25 
26 
27 import sys
28 import os
29 
30 
31 import pygtk
32 pygtk.require("2.0")
33 import gobject
34 gobject.threads_init()
35 import pygst
36 pygst.require('0.10')
37 import gst
38 import signal
39 
40 
41 ## @file
42 # The simplehander module
43 #
44 # ### Review Status
45 #
46 # | Names | Hash | Date |
47 # | ------------------------------------------- | ------------------------------------------- | ---------- |
48 # | Florent, Sathya, Duncan Me., Jolien, Kipp, Chad | b3ef077fe87b597578000f140e4aa780f3a227aa | 2014-05-01 |
49 #
50 # #### Action items
51 #
52 # - Get event based programming expert to have a look?
53 #
54 
55 ## @package python.simplehandler
56 # The simplehander module
57 #
58 
59 
60 
61 #
62 # =============================================================================
63 #
64 # Pipeline Handler
65 #
66 # =============================================================================
67 #
68 
69 
70 class Handler(object):
71  """!
72  A simple handler that prints pipeline error messages to stderr, and
73  stops the pipeline and terminates the mainloop at EOS. Complex
74  applications will need to write their own pipeline handler, but for
75  most simple applications this will suffice, and it's easier than
76  copy-and-pasting this all over the place.
77  """
78  def __init__(self, mainloop, pipeline):
79  self.mainloop = mainloop
80  self.pipeline = pipeline
81 
82  bus = pipeline.get_bus()
83  bus.add_signal_watch()
84  self.on_message_handler_id = bus.connect("message", self.on_message)
85 
86  def excepthook(*args):
87  # system exception hook that forces hard exit. without this,
88  # exceptions that occur inside python code invoked as a call-back
89  # from the gstreamer pipeline just stop the pipeline, they don't
90  # cause gstreamer to exit.
91 
92  # FIXME: they probably *would* cause if we could figure out why
93  # element errors and the like simply stop the pipeline instead of
94  # crashing it, as well. Perhaps this should be removed when/if the
95  # "element error's don't crash program" problem is fixed
96  sys.__excepthook__(*args)
97  os._exit(1)
98 
99  sys.excepthook = excepthook
100 
101 
102  def quit(self, bus):
103  """
104  Decouple this object from the Bus object to allow the Bus'
105  reference count to drop to 0, and .quit() the mainloop
106  object. This method is invoked by the default EOS and
107  ERROR message handlers.
108  """
109  bus.disconnect(self.on_message_handler_id)
110  del self.on_message_handler_id
111  bus.remove_signal_watch()
112  self.mainloop.quit()
113 
114  def do_on_message(self, bus, message):
115  """!
116  Add extra message handling by overriding this in your
117  subclass. If this method returns True, no further message
118  handling is performed. If this method returns False,
119  message handling continues with default cases or EOS, INFO,
120  WARNING and ERROR messages.
121  """
122  return False
123 
124  def on_message(self, bus, message):
125  if self.do_on_message(bus, message):
126  pass
127  elif message.type == gst.MESSAGE_EOS:
128  self.pipeline.set_state(gst.STATE_NULL)
129  self.quit(bus)
130  elif message.type == gst.MESSAGE_INFO:
131  gerr, dbgmsg = message.parse_info()
132  print >>sys.stderr, "info (%s:%d '%s'): %s" % (gerr.domain, gerr.code, gerr.message, dbgmsg)
133  elif message.type == gst.MESSAGE_WARNING:
134  gerr, dbgmsg = message.parse_warning()
135  print >>sys.stderr, "warning (%s:%d '%s'): %s" % (gerr.domain, gerr.code, gerr.message, dbgmsg)
136  elif message.type == gst.MESSAGE_ERROR:
137  gerr, dbgmsg = message.parse_error()
138  # FIXME: this deadlocks. shouldn't we be doing this?
139  #self.pipeline.set_state(gst.STATE_NULL)
140  self.quit(bus)
141  sys.exit("error (%s:%d '%s'): %s" % (gerr.domain, gerr.code, gerr.message, dbgmsg))
142 
143 
144 class OneTimeSignalHandler(object):
145  """!
146  A helper class for application signal handling. Use this to help your
147  application to cleanly shutdown gstreamer pipelines when responding to e.g.,
148  ctrl+c.
149  """
150  def __init__(self, pipeline, signals = [signal.SIGINT, signal.SIGTERM]):
151  self.pipeline = pipeline
152  self.count = 0
153  for sig in signals:
154  signal.signal(sig, self)
155 
156  def do_on_call(self, signum, frame):
157  """!
158  Over ride this for your subclass
159  """
160  pass
161 
162  def __call__(self, signum, frame):
163  self.count += 1
164  if self.count == 1:
165  print >>sys.stderr, "*** SIG %d attempting graceful shutdown (this might take several minutes) ... ***" % signum
166  try:
167  self.do_on_call(signum, frame)
168  if not self.pipeline.send_event(gst.event_new_eos()):
169  raise Exception("pipeline.send_event(EOS) returned failure")
170  except Exception, e:
171  print >>sys.stderr, "graceful shutdown failed: %s\naborting." % str(e)
172  os._exit(1)
173  else:
174  print >>sys.stderr, "*** received SIG %d %d times... ***" % (signum, self.count)