From 0b0be39ebf40379a6cc9262a2b8c54223cdba062 Mon Sep 17 00:00:00 2001 From: Christopher Rosell Date: Wed, 13 Jun 2012 16:06:27 +0200 Subject: Added global options module. - Removed argument handlers from plugins and use options instead. - Removed arguments to stream.open() and use options instead. - Added rtmpdump option to override location manually. --- src/livestreamer/__init__.py | 1 - src/livestreamer/cli.py | 16 +++++++++------- src/livestreamer/options.py | 15 +++++++++++++++ src/livestreamer/plugins/__init__.py | 8 -------- src/livestreamer/plugins/justintv.py | 17 +++++------------ src/livestreamer/stream.py | 26 ++++++++++++++++---------- 6 files changed, 45 insertions(+), 38 deletions(-) create mode 100644 src/livestreamer/options.py diff --git a/src/livestreamer/__init__.py b/src/livestreamer/__init__.py index 1934e2d..1369fe5 100644 --- a/src/livestreamer/__init__.py +++ b/src/livestreamer/__init__.py @@ -18,7 +18,6 @@ def resolve_url(url): def get_plugins(): return plugins.get_plugins() - PluginError = plugins.PluginError NoStreamsError = plugins.NoStreamsError NoPluginError = plugins.NoPluginError diff --git a/src/livestreamer/cli.py b/src/livestreamer/cli.py index cf96a29..91e675f 100644 --- a/src/livestreamer/cli.py +++ b/src/livestreamer/cli.py @@ -12,9 +12,11 @@ parser.add_argument("-p", "--player", metavar="player", help="Command-line for p parser.add_argument("-o", "--output", metavar="filename", help="Write stream to file instead of playing it, use - for stdout") 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("-l", "--plugins", action="store_true", help="Print all currently installed plugins") 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") +parser.add_argument("-r", "--rtmpdump", metavar="path", help="Specify location of rtmpdump") +parser.add_argument("-j", "--jtv-cookie", metavar="cookie", help="Specify JustinTV cookie to allow access to subscription channels") RCFILE = os.path.expanduser("~/.livestreamerrc") @@ -76,7 +78,7 @@ def output_stream(stream, args): out = None try: - fd = stream.open(errorlog=args.errorlog) + fd = stream.open() except livestreamer.StreamError as err: exit(("Could not open stream - {0}").format(err)) @@ -109,6 +111,8 @@ def handle_url(args): try: streams = channel.get_streams() + except livestreamer.StreamError as err: + exit(str(err)) except livestreamer.PluginError as err: exit(str(err)) @@ -143,9 +147,6 @@ def print_plugins(): def main(): - for name, plugin in livestreamer.get_plugins().items(): - plugin.handle_parser(parser) - arglist = sys.argv[1:] if os.path.exists(RCFILE): @@ -153,8 +154,9 @@ def main(): args = parser.parse_args(arglist) - for name, plugin in livestreamer.get_plugins().items(): - plugin.handle_args(args) + livestreamer.options.set("errorlog", args.errorlog) + livestreamer.options.set("rtmpdump", args.rtmpdump) + livestreamer.options.set("jtvcookie", args.jtv_cookie) if args.url: handle_url(args) diff --git a/src/livestreamer/options.py b/src/livestreamer/options.py new file mode 100644 index 0000000..51bd30d --- /dev/null +++ b/src/livestreamer/options.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +options = { + "rtmpdump": None, + "errorlog": False, + "jtvcookie": None +} + +def set(key, value): + options[key] = value + +def get(key): + if key in options: + return options[key] + diff --git a/src/livestreamer/plugins/__init__.py b/src/livestreamer/plugins/__init__.py index ba5810b..7804a3c 100644 --- a/src/livestreamer/plugins/__init__.py +++ b/src/livestreamer/plugins/__init__.py @@ -14,14 +14,6 @@ class Plugin(object): def can_handle_url(self, url): raise NotImplementedError - @classmethod - def handle_parser(self, parser): - pass - - @classmethod - def handle_args(self, args): - self.args = args - def get_streams(self): ranking = ["iphonelow", "iphonehigh", "240p", "360p", "480p", "720p", "hd", "1080p", "live"] diff --git a/src/livestreamer/plugins/justintv.py b/src/livestreamer/plugins/justintv.py index c6d1219..5fc7cc5 100644 --- a/src/livestreamer/plugins/justintv.py +++ b/src/livestreamer/plugins/justintv.py @@ -4,6 +4,7 @@ from livestreamer.plugins import Plugin, PluginError, NoStreamsError, register_p from livestreamer.stream import RTMPStream from livestreamer.utils import swfverify, urlget from livestreamer.compat import urllib, str +from livestreamer import options import xml.dom.minidom, re, sys, random @@ -13,20 +14,10 @@ class JustinTV(Plugin): MetadataURL = "http://www.justin.tv/meta/{0}.xml?on_site=true" SWFURL = "http://www.justin.tv/widgets/live_embed_player.swf" - cookie = None - @classmethod def can_handle_url(self, url): return ("justin.tv" in url) or ("twitch.tv" in url) - @classmethod - def handle_parser(self, parser): - parser.add_argument("--jtv-cookie", metavar="cookie", help="JustinTV cookie to allow access to subscription channels") - - @classmethod - def handle_args(self, args): - self.cookie = args.jtv_cookie - def _get_channel_name(self, url): data = urlget(url) match = re.search(b"live_facebook_embed_player\.swf\?channel=(\w+)", data) @@ -35,8 +26,10 @@ class JustinTV(Plugin): return str(match.group(1), "ascii") def _get_metadata(self, channel): - if self.cookie: - headers = {"Cookie": self.cookie} + cookie = options.get("jtvcookie") + + if cookie: + headers = {"Cookie": cookie} req = urllib.Request(self.MetadataURL.format(channel), headers=headers) else: req = urllib.Request(self.MetadataURL.format(channel)) diff --git a/src/livestreamer/stream.py b/src/livestreamer/stream.py index 8dd4115..9f5aafc 100644 --- a/src/livestreamer/stream.py +++ b/src/livestreamer/stream.py @@ -1,3 +1,4 @@ +from livestreamer import options from livestreamer.utils import urlopen import os @@ -9,7 +10,7 @@ class StreamError(Exception): pass class Stream(object): - def open(self, **args): + def open(self): raise NotImplementedError class StreamProcess(Stream): @@ -17,12 +18,13 @@ class StreamProcess(Stream): self.params = params or {} self.params["_bg"] = True self.params["_err"] = open(os.devnull, "w") + self.errorlog = options.get("errorlog") def cmdline(self): return str(self.cmd.bake(**self.params)) - def open(self, errorlog=False): - if errorlog: + def open(self): + if self.errorlog: tmpfile = tempfile.NamedTemporaryFile(prefix="livestreamer", suffix=".err", delete=False) self.params["_err"] = tmpfile @@ -34,7 +36,7 @@ class StreamProcess(Stream): stream.process.poll() if stream.process.returncode is not None: - if errorlog: + if self.errorlog: raise StreamError(("Error while executing subprocess, error output logged to: {0}").format(tmpfile.name)) else: raise StreamError("Error while executing subprocess") @@ -45,18 +47,22 @@ class RTMPStream(StreamProcess): def __init__(self, params): StreamProcess.__init__(self, params) + self.rtmpdump = options.get("rtmpdump") self.params["flv"] = "-" try: - self.cmd = pbs.rtmpdump - except pbs.CommandNotFound: - raise StreamError("Unable to find 'rtmpdump' command") + if self.rtmpdump: + self.cmd = pbs.Command._create(self.rtmpdump) + else: + self.cmd = pbs.rtmpdump + except pbs.CommandNotFound as err: + raise StreamError(("Unable to find {0} command").format(str(err))) - def open(self, **args): + 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, **args) + return StreamProcess.open(self) def _has_jtv_support(self): help = self.cmd(help=True, _err_to_out=True) @@ -71,6 +77,6 @@ class HTTPStream(Stream): def __init__(self, url): self.url = url - def open(self, **args): + def open(self): return urlopen(self.url) -- cgit v1.2.3