aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/livestreamer/stream
diff options
context:
space:
mode:
authorGravatar Christopher Rosell <chrippa@tanuki.se>2012-09-20 18:37:23 +0200
committerGravatar Christopher Rosell <chrippa@tanuki.se>2012-09-20 18:38:02 +0200
commitd00d0ad02007597393f1c1b7d2a87bd985619f3d (patch)
tree8feeba3c8e0a8d3e9ebb52dbc7df0e131138296d /src/livestreamer/stream
parent1b467b23180662393e5fcad0f209f8ab7472675b (diff)
Split stream.py.
Diffstat (limited to 'src/livestreamer/stream')
-rw-r--r--src/livestreamer/stream/__init__.py65
-rw-r--r--src/livestreamer/stream/http.py17
-rw-r--r--src/livestreamer/stream/rtmpdump.py35
3 files changed, 117 insertions, 0 deletions
diff --git a/src/livestreamer/stream/__init__.py b/src/livestreamer/stream/__init__.py
new file mode 100644
index 0000000..235d2f7
--- /dev/null
+++ b/src/livestreamer/stream/__init__.py
@@ -0,0 +1,65 @@
+from ..compat import str
+
+import os
+import pbs
+import time
+import tempfile
+
+class StreamError(Exception):
+ pass
+
+class Stream(object):
+ """
+ This is a base class that should be inherited when implementing
+ different stream types. Should only be used directly from plugins.
+ """
+
+ def __init__(self, session):
+ self.session = session
+
+ def open(self):
+ """
+ Opens a connection to the stream.
+ Returns a file-like object than can be used to read data.
+ Raises :exc:`StreamError` on failure.
+ """
+ raise NotImplementedError
+
+class StreamProcess(Stream):
+ def __init__(self, session, params={}):
+ Stream.__init__(self, session)
+
+ self.params = params
+ self.params["_bg"] = True
+ self.params["_err"] = open(os.devnull, "w")
+ self.errorlog = self.session.options.get("errorlog")
+
+ def cmdline(self):
+ return str(self.cmd.bake(**self.params))
+
+ def open(self):
+ if self.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 self.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
+
+
+from .http import HTTPStream
+from .rtmpdump import RTMPStream
+
+__all__ = ["StreamError", "Stream", "StreamProcess",
+ "RTMPStream", "HTTPStream"]
diff --git a/src/livestreamer/stream/http.py b/src/livestreamer/stream/http.py
new file mode 100644
index 0000000..ab9a763
--- /dev/null
+++ b/src/livestreamer/stream/http.py
@@ -0,0 +1,17 @@
+from . import Stream
+from ..utils import urlget
+
+class HTTPStream(Stream):
+ def __init__(self, session, url, **args):
+ Stream.__init__(self, session)
+
+ self.url = url
+ self.args = args
+
+ def open(self):
+ res = urlget(self.url, prefetch=False,
+ exception=StreamError,
+ **self.args)
+
+ return res.raw
+
diff --git a/src/livestreamer/stream/rtmpdump.py b/src/livestreamer/stream/rtmpdump.py
new file mode 100644
index 0000000..68ed969
--- /dev/null
+++ b/src/livestreamer/stream/rtmpdump.py
@@ -0,0 +1,35 @@
+from . import StreamProcess
+from ..compat import str, is_win32
+
+import pbs
+
+class RTMPStream(StreamProcess):
+ def __init__(self, session, params):
+ StreamProcess.__init__(self, session, params)
+
+ self.rtmpdump = self.session.options.get("rtmpdump") or (is_win32 and "rtmpdump.exe" or "rtmpdump")
+ self.params["flv"] = "-"
+
+ try:
+ self.cmd = getattr(pbs, self.rtmpdump)
+ except pbs.CommandNotFound as err:
+ raise StreamError(("Unable to find {0} command").format(str(err)))
+
+ def open(self):
+ if "jtv" in self.params and not self._has_jtv_support():
+ raise StreamError("Installed rtmpdump does not support --jtv argument")
+
+ return StreamProcess.open(self)
+
+ def _has_jtv_support(self):
+ try:
+ help = self.cmd(help=True, _err_to_out=True)
+ except pbs.ErrorReturnCode as err:
+ raise StreamError(("Error while checking rtmpdump compatibility: {0}").format(str(err.stdout, "ascii")))
+
+ for line in help.split("\n"):
+ if line[:5] == "--jtv":
+ return True
+
+ return False
+