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