From 04aae63fb01a6056558e16a0d149424fd073bc31 Mon Sep 17 00:00:00 2001 From: Christopher Rosell Date: Tue, 12 Jun 2012 19:53:12 +0200 Subject: Improved subprocess error handling. - Added --errorlog argument to log subprocess errors. - Check if rtmpdump has --jtv argument when needed. --- src/livestreamer/cli.py | 3 ++- src/livestreamer/stream.py | 42 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/livestreamer/cli.py b/src/livestreamer/cli.py index f610101..cf96a29 100644 --- a/src/livestreamer/cli.py +++ b/src/livestreamer/cli.py @@ -13,6 +13,7 @@ parser.add_argument("-o", "--output", metavar="filename", help="Write stream to parser.add_argument("-f", "--force", action="store_true", help="Always write to file even if it already exists") parser.add_argument("-O", "--stdout", action="store_true", help="Write stream to stdout instead of playing it") parser.add_argument("-c", "--cmdline", action="store_true", help="Print command-line used internally to play stream, this may not be available on all streams") +parser.add_argument("-e", "--errorlog", action="store_true", help="Log possible errors from internal command-line to a temporary file, use when debugging") parser.add_argument("-l", "--plugins", action="store_true", help="Print all currently installed plugins") RCFILE = os.path.expanduser("~/.livestreamerrc") @@ -75,7 +76,7 @@ def output_stream(stream, args): out = None try: - fd = stream.open() + fd = stream.open(errorlog=args.errorlog) except livestreamer.StreamError as err: exit(("Could not open stream - {0}").format(err)) diff --git a/src/livestreamer/stream.py b/src/livestreamer/stream.py index 03949f2..8dd4115 100644 --- a/src/livestreamer/stream.py +++ b/src/livestreamer/stream.py @@ -2,24 +2,43 @@ from livestreamer.utils import urlopen import os import pbs +import time +import tempfile class StreamError(Exception): pass class Stream(object): - def open(self): + def open(self, **args): raise NotImplementedError class StreamProcess(Stream): def __init__(self, params): self.params = params or {} + self.params["_bg"] = True + self.params["_err"] = open(os.devnull, "w") def cmdline(self): return str(self.cmd.bake(**self.params)) - def open(self): + def open(self, errorlog=False): + if errorlog: + tmpfile = tempfile.NamedTemporaryFile(prefix="livestreamer", + suffix=".err", delete=False) + self.params["_err"] = tmpfile + stream = self.cmd(**self.params) + # Wait 0.5 seconds to see if program exited prematurely + time.sleep(0.5) + stream.process.poll() + + if stream.process.returncode is not None: + if errorlog: + raise StreamError(("Error while executing subprocess, error output logged to: {0}").format(tmpfile.name)) + else: + raise StreamError("Error while executing subprocess") + return stream.process.stdout class RTMPStream(StreamProcess): @@ -27,18 +46,31 @@ class RTMPStream(StreamProcess): StreamProcess.__init__(self, params) self.params["flv"] = "-" - self.params["_bg"] = True - self.params["_err"] = open(os.devnull, "w") try: self.cmd = pbs.rtmpdump except pbs.CommandNotFound: raise StreamError("Unable to find 'rtmpdump' command") + def open(self, **args): + if "jtv" in self.params and not self._has_jtv_support(): + raise StreamError("Installed rtmpdump does not support --jtv argument") + + return StreamProcess.open(self, **args) + + def _has_jtv_support(self): + help = self.cmd(help=True, _err_to_out=True) + + for line in help.split("\n"): + if line[:5] == "--jtv": + return True + + return False + class HTTPStream(Stream): def __init__(self, url): self.url = url - def open(self): + def open(self, **args): return urlopen(self.url) -- cgit v1.2.3