diff --git a/fHDHR/epghandler/epgtypes/__init__.py b/fHDHR/epghandler/epgtypes/__init__.py index 10cd60d..1b084d2 100644 --- a/fHDHR/epghandler/epgtypes/__init__.py +++ b/fHDHR/epghandler/epgtypes/__init__.py @@ -30,18 +30,28 @@ class EPGTypes(): return epgdict def get_thumbnail(self, itemtype, itemid): - epgdict = self.get_epg() if itemtype == "channel": - for channel in list(epgdict.keys()): - if epgdict[channel]["id"] == itemid: - return epgdict[channel]["thumbnail"] + chandict = self.find_channel_dict(itemid) + return chandict["thumbnail"] elif itemtype == "content": - for channel in list(epgdict.keys()): - for progitem in epgdict[channel]["listing"]: - if progitem["id"] == itemid: - return progitem["thumbnail"] + progdict = self.find_program_dict(itemid) + return progdict["thumbnail"] return None + def find_channel_dict(self, channel_id): + epgdict = self.get_epg() + channel_list = [] + for channel in list(epgdict.keys()): + channel_list.append(epgdict[channel]) + return next(item for item in channel_list if item["id"] == channel_id) + + def find_program_dict(self, event_id): + epgdict = self.get_epg() + event_list = [] + for channel in list(epgdict.keys()): + event_list.extend(epgdict[channel]["listing"]) + return next(item for item in event_list if item["id"] == event_id) + def update(self): print("Updating " + self.epgtypename + " EPG cache file.") diff --git a/fHDHR/epghandler/epgtypes/zap2it.py b/fHDHR/epghandler/epgtypes/zap2it.py index e8902e2..80eee25 100644 --- a/fHDHR/epghandler/epgtypes/zap2it.py +++ b/fHDHR/epghandler/epgtypes/zap2it.py @@ -77,8 +77,8 @@ class ZapEPG(): programguide[str(cdict['channelNo'])] = { "callsign": cdict["callSign"], "name": cdict["name"] or cdict["callSign"], # TODO - "number": cdict["channelNo"], - "id": cdict["channelId"], + "number": str(cdict["channelNo"]), + "id": str(cdict["channelId"]), "thumbnail": str(cdict['thumbnail']).replace("//", "https://").split("?")[0], "listing": [], } @@ -103,7 +103,7 @@ class ZapEPG(): "seasonnumber": progdict['season'], "episodenumber": progdict['episode'], "isnew": False, - "id": progdict['id'] or self.xmltimestamp_zap(eventdict['startTime']), + "id": str(progdict['id'] or self.xmltimestamp_zap(eventdict['startTime'])), } for f in eventdict['filter']: diff --git a/fHDHR/fHDHRweb/__init__.py b/fHDHR/fHDHRweb/__init__.py index 0c034ed..c7048ee 100644 --- a/fHDHR/fHDHRweb/__init__.py +++ b/fHDHR/fHDHRweb/__init__.py @@ -65,6 +65,9 @@ class HDHR_Hub(): def post_lineup_scan_start(self): self.station_scan.scan() + def get_image(self, request_args): + return self.images.get_image(request_args) + hdhr = HDHR_Hub() @@ -139,35 +142,8 @@ class HDHR_HTTP_Server(): @app.route('/images', methods=['GET']) def images(): - - if 'source' not in list(request.args.keys()): - image = hdhr.images.generate_image("content", "Unknown Request") - else: - - itemtype = 'content' - if 'type' in list(request.args.keys()): - itemtype = request.args["type"] - - if request.args['source'] == 'epg': - if 'id' in list(request.args.keys()): - req_dict = { - "source": request.args["source"], - "type": request.args["type"], - "id": request.args["id"], - } - image = hdhr.images.get_image(req_dict) - else: - itemmessage = "Unknown Request" - image = hdhr.images.generate_image(itemtype, itemmessage) - elif request.args['source'] == 'generate': - itemmessage = "Unknown Request" - if 'message' in list(request.args.keys()): - itemmessage = request.args["message"] - image = hdhr.images.generate_image(itemtype, itemmessage) - else: - itemmessage = "Unknown Request" - image = hdhr.images.generate_image(itemtype, itemmessage) - return Response(image, content_type=hdhr.images.get_image_type(image), direct_passthrough=True) + image, imagetype = hdhr.get_image(request.args) + return Response(image, content_type=imagetype, direct_passthrough=True) @app.route('/watch', methods=['GET']) def watch(): diff --git a/fHDHR/fHDHRweb/fHDHRdevice/images.py b/fHDHR/fHDHRweb/fHDHRdevice/images.py index dd1c76d..dc8b211 100644 --- a/fHDHR/fHDHRweb/fHDHRdevice/images.py +++ b/fHDHR/fHDHRweb/fHDHRdevice/images.py @@ -11,6 +11,31 @@ class imageHandler(): self.config = settings self.epghandling = epghandling + def get_image(self, request_args): + + if 'source' not in list(request_args.keys()): + image = self.generate_image("content", "Unknown Request") + + elif request_args["source"] == "epg": + image = self.get_epg_image(request_args) + elif request_args["source"] == "generate": + image = self.generate_image(request_args["type"], request_args["message"]) + else: + image = self.generate_image("content", "Unknown Request") + + imagetype = self.get_image_type(image) + + return image, imagetype + + def get_epg_image(self, request_args): + imageUri = self.epghandling.get_thumbnail(request_args["type"], request_args["id"]) + if not imageUri: + return self.generate_image(request_args["type"], request_args["id"]) + + req = requests.get(imageUri) + return req.content + # return self.generate_image(request_args["type"], request_args["id"]) + def getSize(self, txt, font): testImg = PIL.Image.new('RGB', (1, 1)) testDraw = PIL.ImageDraw.Draw(testImg) @@ -42,19 +67,6 @@ class imageHandler(): img.save(s, 'png') return s.getvalue() - def get_image(self, req_args): - - imageUri = self.epghandling.get_thumbnail(req_args["type"], req_args["id"]) - if not imageUri: - return self.generate_image(req_args["type"], req_args["id"]) - - try: - req = requests.get(imageUri) - return req.content - except Exception as e: - print(e) - return self.generate_image(req_args["type"], req_args["id"]) - def get_image_type(self, image_data): header_byte = image_data[0:3].hex().lower() if header_byte == '474946': diff --git a/fHDHR/fHDHRweb/fHDHRdevice/xmltv_xml.py b/fHDHR/fHDHRweb/fHDHRdevice/xmltv_xml.py index e0a55d9..c6206fb 100644 --- a/fHDHR/fHDHRweb/fHDHRdevice/xmltv_xml.py +++ b/fHDHR/fHDHRweb/fHDHRdevice/xmltv_xml.py @@ -12,7 +12,7 @@ class xmlTV_XML(): self.config = settings self.epghandling = epghandling - def get_xmltv_xml(self, base_url): + def get_xmltv_xml(self, base_url, force_update=False): epgdict = self.epghandling.epgtypes.get_epg() return self.create_xmltv(base_url, epgdict) @@ -58,9 +58,9 @@ class xmlTV_XML(): sub_el(c_out, 'display-name', text=epgdict[c]['name']) if epgdict[c]["thumbnail"] is not None: - sub_el(c_out, 'icon', src=("http://" + str(base_url) + "/images?source=epg&type=channel&id=" + epgdict[c]['id'])) + sub_el(c_out, 'icon', src=("http://" + str(base_url) + "/images?source=epg&type=channel&id=" + str(epgdict[c]['id']))) else: - sub_el(c_out, 'icon', src=("http://" + str(base_url) + "/images?source=generate&message=" + epgdict[c]['number'])) + sub_el(c_out, 'icon', src=("http://" + str(base_url) + "/images?source=generate&message=" + str(epgdict[c]['number']))) for channelnum in list(epgdict.keys()): @@ -98,7 +98,7 @@ class xmlTV_XML(): text='S%02dE%02d' % (s_, e_)) if program["thumbnail"]: - sub_el(prog_out, 'icon', src=("http://" + str(base_url) + "/images?source=epg&type=content&id=" + program['id'])) + sub_el(prog_out, 'icon', src=("http://" + str(base_url) + "/images?source=epg&type=content&id=" + str(program['id']))) else: sub_el(prog_out, 'icon', src=("http://" + str(base_url) + "/images?source=generate&message=" + program['title'].replace(" ", ""))) diff --git a/fHDHR/originservice/nextpvr.py b/fHDHR/originservice/nextpvr.py index 13e3cff..d11e6ca 100644 --- a/fHDHR/originservice/nextpvr.py +++ b/fHDHR/originservice/nextpvr.py @@ -137,7 +137,7 @@ class fHDHRservice(): "callsign": cdict["callsign"], "name": cdict["name"] or cdict["callsign"], "number": cdict["number"], - "id": cdict["id"], + "id": str(cdict["id"]), "thumbnail": self.get_channel_thumbnail(cdict['id']), "listing": [], } @@ -172,7 +172,7 @@ class fHDHRservice(): "seasonnumber": progdict['season'], "episodenumber": progdict['episode'], "isnew": False, - "id": progdict['id'] or self.xmltimestamp_nextpvr(progdict["start"]), + "id": str(progdict['id'] or self.xmltimestamp_nextpvr(progdict["start"])), } if 'genre' in list(progdict.keys()): diff --git a/fHDHR/tools/__init__.py b/fHDHR/tools/__init__.py index 19a3459..4c0940c 100644 --- a/fHDHR/tools/__init__.py +++ b/fHDHR/tools/__init__.py @@ -3,6 +3,7 @@ import sys import ast import requests import xml.etree.ElementTree +import m3u8 UNARY_OPS = (ast.UAdd, ast.USub) BINARY_OPS = (ast.Add, ast.Sub, ast.Mult, ast.Div, ast.Mod) @@ -14,6 +15,26 @@ def clean_exit(): os._exit(0) +def m3u8_beststream(m3u8_url): + bestStream = None + videoUrlM3u = m3u8.load(m3u8_url) + if len(videoUrlM3u.playlists) > 0: + for videoStream in videoUrlM3u.playlists: + if bestStream is None: + bestStream = videoStream + elif ((videoStream.stream_info.resolution[0] > bestStream.stream_info.resolution[0]) and + (videoStream.stream_info.resolution[1] > bestStream.stream_info.resolution[1])): + bestStream = videoStream + elif ((videoStream.stream_info.resolution[0] == bestStream.stream_info.resolution[0]) and + (videoStream.stream_info.resolution[1] == bestStream.stream_info.resolution[1]) and + (videoStream.stream_info.bandwidth > bestStream.stream_info.bandwidth)): + bestStream = videoStream + if bestStream is not None: + return bestStream.absolute_uri + else: + return m3u8_url + + def sub_el(parent, name, text=None, **kwargs): el = xml.etree.ElementTree.SubElement(parent, name, **kwargs) if text: