diff --git a/fHDHR/device/channels/channel.py b/fHDHR/device/channels/channel.py index ae9e11f..7719e4a 100644 --- a/fHDHR/device/channels/channel.py +++ b/fHDHR/device/channels/channel.py @@ -164,7 +164,7 @@ class Channel(): @property def api_stream_url(self): - return '/api/tuners?method=%s&channel=%s&origin=%s' % (self.fhdhr.config.dict["streaming"]["method"], self.dict["id"], self.origin) + return '/api/tuners?method=stream&stream_method=%s&channel=%s&origin=%s' % (self.fhdhr.origins.origins_dict[self.origin].stream_method, self.dict["id"], self.origin) @property def api_m3u_url(self): diff --git a/fHDHR/device/tuners/tuner.py b/fHDHR/device/tuners/tuner.py index 798f0f5..d068cb0 100644 --- a/fHDHR/device/tuners/tuner.py +++ b/fHDHR/device/tuners/tuner.py @@ -85,7 +85,7 @@ class Tuner(): def get_stream(self, stream_args, tuner): stream = Stream(self.fhdhr, stream_args, tuner) - return stream.get() + return stream def set_status(self, stream_args): if self.status["status"] != "Active": diff --git a/fHDHR_web/api/tuners.py b/fHDHR_web/api/tuners.py index 0448611..a1f0232 100644 --- a/fHDHR_web/api/tuners.py +++ b/fHDHR_web/api/tuners.py @@ -36,7 +36,7 @@ class Tuners(): if origin and origin not in origin_methods: return "%s Invalid channels origin" % origin - if method in list(self.fhdhr.config.dict["streaming"]["valid_methods"].keys()): + if method == "stream": channel_number = request.args.get('channel', None, type=str) if not channel_number: @@ -73,6 +73,13 @@ class Tuners(): origin = chan_obj.origin channel_number = chan_obj.number + stream_method = request.args.get('stream_method', default=self.fhdhr.origins.origins_dict[origin].stream_method, type=str) + if stream_method not in list(self.fhdhr.config.dict["streaming"]["valid_methods"].keys()): + response = Response("Service Unavailable", status=503) + response = Response("Service Unavailable", status=503) + response.headers["X-fHDHR-Error"] = str("806 - Tune Failed") + abort(response) + duration = request.args.get('duration', default=0, type=int) transcode_quality = request.args.get('transcode', default=None, type=str) @@ -86,7 +93,7 @@ class Tuners(): stream_args = { "channel": channel_number, "origin": origin, - "method": method, + "method": stream_method, "duration": duration, "origin_quality": self.fhdhr.config.dict["streaming"]["origin_quality"], "transcode_quality": transcode_quality or self.fhdhr.config.dict["streaming"]["transcode_quality"], @@ -125,7 +132,15 @@ class Tuners(): tuner.set_status(stream_args) session["tuner_used"] = tunernum - return Response(stream_with_context(tuner.get_stream(stream_args, tuner)), mimetype=stream_args["content_type"]) + try: + stream = tuner.get_stream(stream_args, tuner) + except TunerError as e: + response.headers["X-fHDHR-Error"] = str(e) + self.fhdhr.logger.error(response.headers["X-fHDHR-Error"]) + tuner.close() + abort(response) + + return Response(stream_with_context(stream.get()), mimetype=stream_args["content_type"]) elif method == "close": diff --git a/plugins/fHDHR_plugin_interface_hdhr/web/auto.py b/plugins/fHDHR_plugin_interface_hdhr/web/auto.py index e42dd82..cdf28db 100644 --- a/plugins/fHDHR_plugin_interface_hdhr/web/auto.py +++ b/plugins/fHDHR_plugin_interface_hdhr/web/auto.py @@ -20,7 +20,7 @@ class Auto(): origin = self.source - redirect_url = "/api/tuners?method=%s" % (self.fhdhr.config.dict["streaming"]["method"]) + redirect_url = "/api/tuners?method=stream" if channel.startswith("v"): channel_number = channel.replace('v', '') @@ -40,6 +40,7 @@ class Auto(): redirect_url += "&channel=%s" % str(channel_number) redirect_url += "&origin=%s" % str(origin) + redirect_url += "&stream_method=%s" % self.fhdhr.origins.origins_dict[origin].stream_method duration = request.args.get('duration', default=0, type=int) if duration: diff --git a/plugins/fHDHR_plugin_interface_hdhr/web/tuner.py b/plugins/fHDHR_plugin_interface_hdhr/web/tuner.py index 105b141..0248002 100644 --- a/plugins/fHDHR_plugin_interface_hdhr/web/tuner.py +++ b/plugins/fHDHR_plugin_interface_hdhr/web/tuner.py @@ -20,7 +20,7 @@ class Tuner(): origin = self.source - redirect_url = "/api/tuners?method=%s" % (self.fhdhr.config.dict["streaming"]["method"]) + redirect_url = "/api/tuners?method=stream" redirect_url += "&tuner=%s" % (tuner_number) @@ -42,6 +42,7 @@ class Tuner(): redirect_url += "&channel=%s" % str(channel_number) redirect_url += "&origin=%s" % str(origin) + redirect_url += "&stream_method=%s" % self.fhdhr.origins.origins_dict[origin].stream_method duration = request.args.get('duration', default=0, type=int) if duration: diff --git a/plugins/fHDHR_plugin_interface_rmg/web/devices_devicekey_media.py b/plugins/fHDHR_plugin_interface_rmg/web/devices_devicekey_media.py index 0d49f50..d04e4f2 100644 --- a/plugins/fHDHR_plugin_interface_rmg/web/devices_devicekey_media.py +++ b/plugins/fHDHR_plugin_interface_rmg/web/devices_devicekey_media.py @@ -23,12 +23,9 @@ class RMG_Devices_DeviceKey_Media(): response.headers["X-fHDHR-Error"] = "801 - Unknown devicekey" self.fhdhr.logger.error(response.headers["X-fHDHR-Error"]) abort(response) - - method = self.fhdhr.config.dict["streaming"]["method"] - redirect_url = "/api/tuners?method=%s" % (method) - origin = devicekey.split(self.fhdhr.config.dict["main"]["uuid"])[-1] - redirect_url += "&origin=%s" % (origin) + + redirect_url = "/api/tuners?method=stream" if str(channel).startswith('id://'): channel = str(channel).replace('id://', '') @@ -36,7 +33,10 @@ class RMG_Devices_DeviceKey_Media(): channel_tuple = channel.replace('triplet://', '').split(":") self.fhdhr.logger.error("Not Implemented %s" % ":".join(channel_tuple)) abort(501, "Not Implemented %s" % ":".join(channel_tuple)) + redirect_url += "&channel=%s" % (channel) + redirect_url += "&origin=%s" % (origin) + redirect_url += "&stream_method=%s" % self.fhdhr.origins.origins_dict[origin].stream_method redirect_url += "&accessed=%s" % urllib.parse.quote(request.url) diff --git a/plugins/fHDHR_plugin_stream_ffmpeg/__init__.py b/plugins/fHDHR_plugin_stream_ffmpeg/__init__.py index 27db2c8..4a5deab 100644 --- a/plugins/fHDHR_plugin_stream_ffmpeg/__init__.py +++ b/plugins/fHDHR_plugin_stream_ffmpeg/__init__.py @@ -1,23 +1,59 @@ +import os import sys import subprocess +from fHDHR.exceptions import TunerError + def setup(plugin): - try: - ffmpeg_command = [plugin.config.dict["ffmpeg"]["path"], - "-version", - "pipe:stdout" - ] - ffmpeg_proc = subprocess.Popen(ffmpeg_command, stdout=subprocess.PIPE) - ffmpeg_version = ffmpeg_proc.stdout.read() + # Check config for ffmpeg path + ffmpeg_path = None + if plugin.config.dict["ffmpeg"]["path"]: + # verify path is valid + if os.path.isfile(plugin.config.dict["ffmpeg"]["path"]): + ffmpeg_path = plugin.config.dict["ffmpeg"]["path"] + else: + plugin.logger.warning("Failed to find ffmpeg at %s." % plugin.config.dict["ffmpeg"]["path"]) + + if not ffmpeg_path: + plugin.logger.info("Attempting to find ffmpeg in PATH.") + if plugin.config.internal["versions"]["Operating System"]["version"] in ["Linux", "Darwin"]: + find_ffmpeg_command = ["which", "ffmpeg"] + elif plugin.config.internal["versions"]["Operating System"]["version"] in ["Windows"]: + find_ffmpeg_command = ["where", "ffmpeg"] + + ffmpeg_proc = subprocess.Popen(find_ffmpeg_command, stdout=subprocess.PIPE) + ffmpeg_path = ffmpeg_proc.stdout.read().decode().strip("\n") ffmpeg_proc.terminate() ffmpeg_proc.communicate() ffmpeg_proc.kill() - ffmpeg_version = ffmpeg_version.decode().split("version ")[1].split(" ")[0] - except FileNotFoundError: + if not ffmpeg_path: + ffmpeg_path = None + elif ffmpeg_path.isspace(): + ffmpeg_path = None + + if ffmpeg_path: + plugin.config.dict["ffmpeg"]["path"] = ffmpeg_path + + if ffmpeg_path: + ffmpeg_command = [ffmpeg_path, "-version", "pipe:stdout"] + try: + ffmpeg_proc = subprocess.Popen(ffmpeg_command, stdout=subprocess.PIPE) + ffmpeg_version = ffmpeg_proc.stdout.read().decode().split("version ")[1].split(" ")[0] + except FileNotFoundError: + ffmpeg_version = None + except PermissionError: + ffmpeg_version = None + finally: + ffmpeg_proc.terminate() + ffmpeg_proc.communicate() + ffmpeg_proc.kill() + + if not ffmpeg_version: ffmpeg_version = "Missing" plugin.logger.warning("Failed to find ffmpeg.") + plugin.config.register_version("ffmpeg", ffmpeg_version, "env") @@ -29,6 +65,9 @@ class Plugin_OBJ(): self.stream_args = stream_args self.tuner = tuner + if self.plugin_utils.config.internal["versions"]["ffmpeg"] == "Missing": + raise TunerError("806 - Tune Failed: FFMPEG Missing") + self.bytes_per_read = int(plugin_utils.config.dict["streaming"]["bytes_per_read"]) self.ffmpeg_command = self.ffmpeg_command_assemble(stream_args) diff --git a/plugins/fHDHR_plugin_stream_ffmpeg/ffmpeg_conf.json b/plugins/fHDHR_plugin_stream_ffmpeg/ffmpeg_conf.json index b57386c..6389c73 100644 --- a/plugins/fHDHR_plugin_stream_ffmpeg/ffmpeg_conf.json +++ b/plugins/fHDHR_plugin_stream_ffmpeg/ffmpeg_conf.json @@ -1,7 +1,7 @@ { "ffmpeg":{ "path":{ - "value": "ffmpeg", + "value": "none", "config_file": true, "config_web": true } diff --git a/plugins/fHDHR_plugin_stream_vlc/__init__.py b/plugins/fHDHR_plugin_stream_vlc/__init__.py index 23a9b3b..5a298dc 100644 --- a/plugins/fHDHR_plugin_stream_vlc/__init__.py +++ b/plugins/fHDHR_plugin_stream_vlc/__init__.py @@ -1,23 +1,59 @@ +import os import sys import subprocess +from fHDHR.exceptions import TunerError + def setup(plugin): - try: - vlc_command = [plugin.config.dict["vlc"]["path"], - "--version", - "pipe:stdout" - ] - vlc_proc = subprocess.Popen(vlc_command, stdout=subprocess.PIPE) - vlc_version = vlc_proc.stdout.read() + # Check config for vlc path + vlc_path = None + if plugin.config.dict["vlc"]["path"]: + # verify path is valid + if os.path.isfile(plugin.config.dict["vlc"]["path"]): + vlc_path = plugin.config.dict["vlc"]["path"] + else: + plugin.logger.warning("Failed to find vlc at %s." % plugin.config.dict["vlc"]["path"]) + + if not vlc_path: + plugin.logger.info("Attempting to find vlc in PATH.") + if plugin.config.internal["versions"]["Operating System"]["version"] in ["Linux", "Darwin"]: + find_vlc_command = ["which", "vlc"] + elif plugin.config.internal["versions"]["Operating System"]["version"] in ["Windows"]: + find_vlc_command = ["where", "vlc"] + + vlc_proc = subprocess.Popen(find_vlc_command, stdout=subprocess.PIPE) + vlc_path = vlc_proc.stdout.read().decode().strip("\n") vlc_proc.terminate() vlc_proc.communicate() vlc_proc.kill() - vlc_version = vlc_version.decode().split("version ")[1].split('\n')[0] - except FileNotFoundError: + if not vlc_path: + vlc_path = None + elif vlc_path.isspace(): + vlc_path = None + + if vlc_path: + plugin.config.dict["vlc"]["path"] = vlc_path + + if vlc_path: + vlc_command = [vlc_path, "--version", "pipe:stdout"] + try: + vlc_proc = subprocess.Popen(vlc_command, stdout=subprocess.PIPE) + vlc_version = vlc_proc.stdout.read().decode().split("version ")[1].split('\n')[0] + except FileNotFoundError: + vlc_version = None + except PermissionError: + vlc_version = None + finally: + vlc_proc.terminate() + vlc_proc.communicate() + vlc_proc.kill() + + if not vlc_version: vlc_version = "Missing" plugin.logger.warning("Failed to find vlc.") + plugin.config.register_version("vlc", vlc_version, "env") @@ -29,6 +65,9 @@ class Plugin_OBJ(): self.stream_args = stream_args self.tuner = tuner + if self.plugin_utils.config.internal["versions"]["vlc"] == "Missing": + raise TunerError("806 - Tune Failed: VLC Missing") + self.bytes_per_read = int(self.plugin_utils.config.dict["streaming"]["bytes_per_read"]) self.vlc_command = self.vlc_command_assemble(stream_args) diff --git a/plugins/fHDHR_plugin_stream_vlc/vlc_conf.json b/plugins/fHDHR_plugin_stream_vlc/vlc_conf.json index bb14110..195fa81 100644 --- a/plugins/fHDHR_plugin_stream_vlc/vlc_conf.json +++ b/plugins/fHDHR_plugin_stream_vlc/vlc_conf.json @@ -1,7 +1,7 @@ { "vlc":{ "path":{ - "value": "cvlc", + "value": "none", "config_file": true, "config_web": true }