aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Christopher Rosell <chrippa@tanuki.se>2012-06-12 19:53:12 +0200
committerGravatar Christopher Rosell <chrippa@tanuki.se>2012-06-12 19:53:12 +0200
commit04aae63fb01a6056558e16a0d149424fd073bc31 (patch)
treeee03b50b646f2d1e853cc75fe8a6fb819c08b297
parentad4b6b95c8969a445d96a054e7713a8fe7539581 (diff)
Improved subprocess error handling.
- Added --errorlog argument to log subprocess errors. - Check if rtmpdump has --jtv argument when needed.
-rw-r--r--src/livestreamer/cli.py3
-rw-r--r--src/livestreamer/stream.py42
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)