mirror of
https://github.com/fHDHR/fHDHR_NextPVR.git
synced 2025-12-06 12:56:57 -05:00
commit
be631e18b2
@ -18,6 +18,7 @@
|
||||
|
||||
<button class="pull-left" onclick="OpenLink('/')">fHDHR</a></button>
|
||||
<button class="pull-left" onclick="OpenLink('/origin')">{{ fhdhr.config.dict["main"]["servicename"] }}</a></button>
|
||||
<button class="pull-left" onclick="OpenLink('/channels')">Channels</a></button>
|
||||
<button class="pull-left" onclick="OpenLink('/guide')">Guide</a></button>
|
||||
<button class="pull-left" onclick="OpenLink('/cluster')">Cluster</a></button>
|
||||
<button class="pull-left" onclick="OpenLink('/streams')">Streams</a></button>
|
||||
|
||||
46
data/www/templates/channels.html
Normal file
46
data/www/templates/channels.html
Normal file
@ -0,0 +1,46 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h4 style="text-align: center;">What's On {{ fhdhr.config.dict["fhdhr"]["friendlyname"] }}</h4>
|
||||
|
||||
<table class="center" style="width:100%">
|
||||
<tr>
|
||||
<th>Play</th>
|
||||
<th>Channel Name</th>
|
||||
<th>Channel CallSign</th>
|
||||
<th>Channel Number</th>
|
||||
<th>Status</th>
|
||||
<th>Options</th>
|
||||
</tr>
|
||||
|
||||
{% for chan_dict in channelslist %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if chan_dict["enabled"] %}
|
||||
<a href="{{ chan_dict["play_url"] }}">Play</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ chan_dict["name"] }}</td>
|
||||
<td>{{ chan_dict["callsign"] }}</td>
|
||||
<td>{{ chan_dict["number"] }}</td>
|
||||
<td>
|
||||
{% if chan_dict["enabled"] %}
|
||||
Enabled
|
||||
{% elif not chan_dict["enabled"] %}
|
||||
Disabled
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<div>
|
||||
{% if chan_dict["enabled"] %}
|
||||
<button onclick="OpenLink('/api/channels?method=disable&channel={{ chan_dict["number"] }}&redirect=%2Fchannels')">Disable</a></button>
|
||||
{% elif not chan_dict["enabled"] %}
|
||||
<button onclick="OpenLink('/api/channels?method=enable&channel={{ chan_dict["number"] }}&redirect=%2Fchannels')">Enable</a></button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
||||
@ -4,9 +4,14 @@
|
||||
|
||||
<h4 style="text-align: center;">What's On {{ fhdhr.config.dict["fhdhr"]["friendlyname"] }}</h4>
|
||||
|
||||
<p>
|
||||
{% for epg_method in epg_methods %}
|
||||
<button onclick="OpenLink('/guide?source={{ epg_method }}')">{{ epg_method }}</a></button>
|
||||
{% endfor %}
|
||||
</p>
|
||||
|
||||
<table class="center" style="width:100%">
|
||||
<tr>
|
||||
<th>Play</th>
|
||||
<th>Channel Name</th>
|
||||
<th>Channel Number</th>
|
||||
<th>Channel Thumbnail</th>
|
||||
@ -18,7 +23,6 @@
|
||||
|
||||
{% for chan_dict in chan_guide_list %}
|
||||
<tr>
|
||||
<td><a href="{{ chan_dict["play_url"] }}">Play</a>
|
||||
<td>{{ chan_dict["name"] }}</td>
|
||||
<td>{{ chan_dict["number"] }}</td>
|
||||
<td><img src="{{ chan_dict["chan_thumbnail"] }}" alt="{{ chan_dict["name"] }}" width="100" height="100">
|
||||
|
||||
@ -21,8 +21,8 @@
|
||||
|
||||
<tr>
|
||||
<td>{{ epg_method_name }}</td>
|
||||
<td><a href="/api/xmltv?method=get&source="{{ epg_method }}>{{ epg_method_name }}</a></td>
|
||||
<td><a href="/api/epg?method=get&source="{{ epg_method }}>{{ epg_method_name }}</a></td>
|
||||
<td><a href="/api/xmltv?method=get&source={{ epg_method }}">{{ epg_method_name }}</a></td>
|
||||
<td><a href="/api/epg?method=get&source={{ epg_method }}">{{ epg_method_name }}</a></td>
|
||||
<td>
|
||||
<div>
|
||||
<button onclick="OpenLink('/api/xmltv?method=update&source={{ epg_method }}&redirect=%2Fxmltv')">Update</a></button>
|
||||
|
||||
@ -1,157 +0,0 @@
|
||||
import datetime
|
||||
from collections import OrderedDict
|
||||
|
||||
from fHDHR.tools import hours_between_datetime
|
||||
|
||||
|
||||
class ChannelNumbers():
|
||||
|
||||
def __init__(self, fhdhr):
|
||||
self.fhdhr = fhdhr
|
||||
|
||||
def get_number(self, channel_id):
|
||||
cnumbers = self.fhdhr.db.get_fhdhr_value("channel_numbers", "list") or {}
|
||||
if channel_id in list(cnumbers.keys()):
|
||||
return cnumbers[channel_id]
|
||||
|
||||
used_numbers = []
|
||||
for channel_id in list(cnumbers.keys()):
|
||||
used_numbers.append(cnumbers[channel_id])
|
||||
|
||||
for i in range(1, 1000):
|
||||
if str(float(i)) not in used_numbers:
|
||||
break
|
||||
return str(float(i))
|
||||
|
||||
def set_number(self, channel_id, channel_number):
|
||||
cnumbers = self.fhdhr.db.get_fhdhr_value("channel_numbers", "list") or {}
|
||||
cnumbers[channel_id] = str(float(channel_number))
|
||||
self.fhdhr.db.set_fhdhr_value("channel_numbers", "list", cnumbers)
|
||||
|
||||
|
||||
class Channels():
|
||||
|
||||
def __init__(self, fhdhr, origin):
|
||||
self.fhdhr = fhdhr
|
||||
|
||||
self.origin = origin
|
||||
|
||||
self.channel_numbers = ChannelNumbers(fhdhr)
|
||||
|
||||
self.list = {}
|
||||
self.list_update_time = None
|
||||
self.get_channels()
|
||||
|
||||
def get_origin_status(self):
|
||||
try:
|
||||
return self.origin.get_status_dict()
|
||||
except AttributeError:
|
||||
return {}
|
||||
|
||||
def get_channels(self, forceupdate=False):
|
||||
"""Pull Channels from origin.
|
||||
|
||||
Output a list.
|
||||
|
||||
Don't pull more often than 12 hours.
|
||||
"""
|
||||
|
||||
updatelist = False
|
||||
if not self.list_update_time:
|
||||
updatelist = True
|
||||
elif hours_between_datetime(self.list_update_time, datetime.datetime.now()) > 12:
|
||||
updatelist = True
|
||||
elif forceupdate:
|
||||
updatelist = True
|
||||
|
||||
if updatelist:
|
||||
channel_dict_list = self.origin.get_channels()
|
||||
channel_dict_list = self.verify_channel_info(channel_dict_list)
|
||||
self.append_channel_info(channel_dict_list)
|
||||
if not self.list_update_time:
|
||||
self.fhdhr.logger.info("Found " + str(len(self.list)) + " channels for " + str(self.fhdhr.config.dict["main"]["servicename"]))
|
||||
self.list_update_time = datetime.datetime.now()
|
||||
|
||||
channel_list = []
|
||||
for chandict in list(self.list.keys()):
|
||||
channel_list.append(self.list[chandict])
|
||||
return channel_list
|
||||
|
||||
def get_station_list(self, base_url):
|
||||
station_list = []
|
||||
|
||||
for c in self.get_channels():
|
||||
station_list.append({
|
||||
'GuideNumber': c['number'],
|
||||
'GuideName': c['name'],
|
||||
'Tags': ",".join(c['tags']),
|
||||
'URL': self.get_fhdhr_stream_url(base_url, c['number']),
|
||||
})
|
||||
return station_list
|
||||
|
||||
def get_channel_stream(self, channel_number):
|
||||
if channel_number not in list(self.list.keys()):
|
||||
self.get_channels()
|
||||
if channel_number not in list(self.list.keys()):
|
||||
return None
|
||||
if "stream_url" not in list(self.list[channel_number].keys()):
|
||||
chandict = self.get_channel_dict("number", channel_number)
|
||||
streamlist, caching = self.origin.get_channel_stream(chandict, self.list)
|
||||
if caching:
|
||||
self.append_channel_info(streamlist)
|
||||
return self.list[channel_number]["stream_url"]
|
||||
else:
|
||||
chanstreamdict = next(item for item in streamlist if item["number"] == channel_number)
|
||||
return chanstreamdict["stream_url"]
|
||||
return self.list[channel_number]["stream_url"]
|
||||
|
||||
def get_station_total(self):
|
||||
return len(list(self.list.keys()))
|
||||
|
||||
def get_channel_dict(self, keyfind, valfind):
|
||||
chanlist = self.get_channels()
|
||||
return next(item for item in chanlist if item[keyfind] == valfind)
|
||||
|
||||
def get_fhdhr_stream_url(self, base_url, channel_number):
|
||||
return ('%s/auto/v%s' %
|
||||
(base_url,
|
||||
channel_number))
|
||||
|
||||
def verify_channel_info(self, channel_dict_list):
|
||||
"""Some Channel Information is Critical"""
|
||||
cleaned_channel_dict_list = []
|
||||
for station_item in channel_dict_list:
|
||||
|
||||
if "callsign" not in list(station_item.keys()):
|
||||
station_item["callsign"] = station_item["name"]
|
||||
|
||||
if "id" not in list(station_item.keys()):
|
||||
station_item["id"] = station_item["name"]
|
||||
|
||||
if "tags" not in list(station_item.keys()):
|
||||
station_item["tags"] = []
|
||||
|
||||
if "number" not in list(station_item.keys()):
|
||||
station_item["number"] = self.channel_numbers.get_number(station_item["id"])
|
||||
else:
|
||||
station_item["number"] = str(float(station_item["number"]))
|
||||
self.channel_numbers.set_number(station_item["id"], station_item["number"])
|
||||
|
||||
cleaned_channel_dict_list.append(station_item)
|
||||
return cleaned_channel_dict_list
|
||||
|
||||
def append_channel_info(self, channel_dict_list):
|
||||
"""Update the list dict
|
||||
|
||||
Take the channel dict list given.
|
||||
"""
|
||||
for chan in channel_dict_list:
|
||||
if chan["number"] not in list(self.list.keys()):
|
||||
self.list[chan["number"]] = {}
|
||||
for chankey in list(chan.keys()):
|
||||
self.list[chan["number"]][chankey] = chan[chankey]
|
||||
self.channel_order()
|
||||
|
||||
def channel_order(self):
|
||||
"""Verify the Channel Order"""
|
||||
self.list = OrderedDict(sorted(self.list.items()))
|
||||
76
fHDHR/device/channels/__init__.py
Normal file
76
fHDHR/device/channels/__init__.py
Normal file
@ -0,0 +1,76 @@
|
||||
import datetime
|
||||
|
||||
from fHDHR.tools import hours_between_datetime
|
||||
|
||||
from .channel import Channel
|
||||
from .chan_ident import Channel_IDs
|
||||
|
||||
|
||||
class Channels():
|
||||
|
||||
def __init__(self, fhdhr, origin):
|
||||
self.fhdhr = fhdhr
|
||||
|
||||
self.origin = origin
|
||||
|
||||
self.id_system = Channel_IDs(fhdhr)
|
||||
|
||||
self.list = {}
|
||||
self.list_update_time = None
|
||||
self.get_db_channels()
|
||||
self.get_channels()
|
||||
|
||||
def get_channel_obj(self, keyfind, valfind):
|
||||
return next(self.list[fhdhr_id] for fhdhr_id in list(self.list.keys()) if self.list[fhdhr_id].dict[keyfind] == valfind)
|
||||
|
||||
def get_channel_list(self, keyfind):
|
||||
return [self.list[x].dict[keyfind] for x in list(self.list.keys())]
|
||||
|
||||
def set_channel_status(self, keyfind, valfind, enablement):
|
||||
self.get_channel_obj(keyfind, valfind).set_status(enablement)
|
||||
|
||||
def get_db_channels(self):
|
||||
channel_ids = self.fhdhr.db.get_fhdhr_value("channels", "IDs") or []
|
||||
for channel_id in channel_ids:
|
||||
channel_obj = Channel(self.fhdhr, self.id_system, channel_id=channel_id)
|
||||
channel_id = channel_obj.dict["fhdhr_id"]
|
||||
self.list[channel_id] = channel_obj
|
||||
|
||||
def get_channels(self, forceupdate=False):
|
||||
"""Pull Channels from origin.
|
||||
|
||||
Output a list.
|
||||
|
||||
Don't pull more often than 12 hours.
|
||||
"""
|
||||
|
||||
updatelist = False
|
||||
if not self.list_update_time:
|
||||
updatelist = True
|
||||
elif hours_between_datetime(self.list_update_time, datetime.datetime.now()) > 12:
|
||||
updatelist = True
|
||||
elif forceupdate:
|
||||
updatelist = True
|
||||
|
||||
if updatelist:
|
||||
channel_dict_list = self.origin.get_channels()
|
||||
for channel_info in channel_dict_list:
|
||||
channel_obj = Channel(self.fhdhr, self.id_system, origin_id=channel_info["id"])
|
||||
channel_id = channel_obj.dict["fhdhr_id"]
|
||||
channel_obj.basics(channel_info)
|
||||
self.list[channel_id] = channel_obj
|
||||
|
||||
if not self.list_update_time:
|
||||
self.fhdhr.logger.info("Found " + str(len(self.list)) + " channels for " + str(self.fhdhr.config.dict["main"]["servicename"]))
|
||||
self.list_update_time = datetime.datetime.now()
|
||||
|
||||
channel_list = []
|
||||
for chan_obj in list(self.list.keys()):
|
||||
channel_list.append(self.list[chan_obj].dict)
|
||||
return channel_list
|
||||
|
||||
def get_channel_stream(self, channel_number):
|
||||
return self.origin.get_channel_stream(self.get_channel_dict("number", channel_number))
|
||||
|
||||
def get_channel_dict(self, keyfind, valfind):
|
||||
return self.get_channel_obj(keyfind, valfind).dict
|
||||
38
fHDHR/device/channels/chan_ident.py
Normal file
38
fHDHR/device/channels/chan_ident.py
Normal file
@ -0,0 +1,38 @@
|
||||
import uuid
|
||||
|
||||
|
||||
class Channel_IDs():
|
||||
def __init__(self, fhdhr):
|
||||
self.fhdhr = fhdhr
|
||||
|
||||
def get(self, origin_id):
|
||||
existing_ids = self.fhdhr.db.get_fhdhr_value("channels", "IDs") or []
|
||||
existing_channel_info = [self.fhdhr.db.get_channel_value(channel_id, "info") or {} for channel_id in existing_ids]
|
||||
for existing_channel in existing_channel_info:
|
||||
if existing_channel["origin_id"] == origin_id:
|
||||
return existing_channel["fhdhr_id"]
|
||||
return self.assign()
|
||||
|
||||
def assign(self):
|
||||
existing_ids = self.fhdhr.db.get_fhdhr_value("channels", "IDs") or []
|
||||
channel_id = None
|
||||
while not channel_id:
|
||||
unique_id = str(uuid.uuid4())
|
||||
if str(unique_id) not in existing_ids:
|
||||
channel_id = str(unique_id)
|
||||
existing_ids.append(channel_id)
|
||||
self.fhdhr.db.set_fhdhr_value("channels", "IDs", existing_ids)
|
||||
return channel_id
|
||||
|
||||
def get_number(self, channel_id):
|
||||
existing_ids = self.fhdhr.db.get_fhdhr_value("channels", "IDs") or []
|
||||
existing_channel_info = [self.fhdhr.db.get_channel_value(channel_id, "info") or {} for channel_id in existing_ids]
|
||||
cnumber = [existing_channel["number"] for existing_channel in existing_channel_info if existing_channel["fhdhr_id"] == channel_id] or None
|
||||
if cnumber:
|
||||
return cnumber
|
||||
|
||||
used_numbers = [existing_channel["number"] for existing_channel in existing_channel_info]
|
||||
for i in range(1000, 2000):
|
||||
if str(float(i)) not in used_numbers:
|
||||
break
|
||||
return str(float(i))
|
||||
92
fHDHR/device/channels/channel.py
Normal file
92
fHDHR/device/channels/channel.py
Normal file
@ -0,0 +1,92 @@
|
||||
|
||||
|
||||
class Channel():
|
||||
|
||||
def __init__(self, fhdhr, id_system, origin_id=None, channel_id=None):
|
||||
self.fhdhr = fhdhr
|
||||
|
||||
self.id_system = id_system
|
||||
|
||||
if not channel_id:
|
||||
if origin_id:
|
||||
channel_id = id_system.get(origin_id)
|
||||
else:
|
||||
channel_id = id_system.assign()
|
||||
self.dict = self.fhdhr.db.get_channel_value(str(channel_id), "info") or self.create_empty_channel(channel_id)
|
||||
self.fhdhr.db.set_channel_value(self.dict["fhdhr_id"], "info", self.dict)
|
||||
|
||||
def basics(self, channel_info):
|
||||
"""Some Channel Information is Critical"""
|
||||
|
||||
if "id" in list(channel_info.keys()):
|
||||
channel_info["origin_id"] = channel_info["id"]
|
||||
del channel_info["id"]
|
||||
|
||||
if "name" not in list(channel_info.keys()):
|
||||
channel_info["name"] = self.dict["fhdhr_id"]
|
||||
|
||||
if "callsign" not in list(channel_info.keys()):
|
||||
channel_info["callsign"] = channel_info["name"]
|
||||
|
||||
if "origin_id" not in list(channel_info.keys()):
|
||||
channel_info["origin_id"] = channel_info["name"]
|
||||
|
||||
if "tags" not in list(channel_info.keys()):
|
||||
channel_info["tags"] = []
|
||||
|
||||
if "number" not in list(channel_info.keys()):
|
||||
channel_info["number"] = self.id_system.get_number(channel_info["origin_id"])
|
||||
channel_info["number"] = str(float(channel_info["number"]))
|
||||
|
||||
self.append_channel_info(channel_info)
|
||||
|
||||
def create_empty_channel(self, channel_id):
|
||||
return {
|
||||
"fhdhr_id": str(channel_id),
|
||||
"origin_id": None,
|
||||
"name": None,
|
||||
"callsign": None,
|
||||
"number": None,
|
||||
"tags": [],
|
||||
"enabled": True
|
||||
}
|
||||
|
||||
def destroy(self):
|
||||
self.fhdhr.db.delete_channel_value(self.dict["fhdhr_id"], "info")
|
||||
channel_ids = self.fhdhr.db.get_fhdhr_value("channels", "IDs") or []
|
||||
if self.dict["fhdhr_id"] in channel_ids:
|
||||
channel_ids.remove(self.dict["fhdhr_id"])
|
||||
self.fhdhr.db.set_fhdhr_value("channels", "IDs", channel_ids)
|
||||
|
||||
def append_channel_info(self, channel_info):
|
||||
for chankey in list(channel_info.keys()):
|
||||
self.dict[chankey] = channel_info[chankey]
|
||||
self.fhdhr.db.set_channel_value(self.dict["fhdhr_id"], "info", self.dict)
|
||||
|
||||
def set_status(self, enablement):
|
||||
if enablement == "disable":
|
||||
self.dict["enabled"] = False
|
||||
elif enablement == "enable":
|
||||
self.dict["enabled"] = True
|
||||
self.fhdhr.db.set_channel_value(self.dict["fhdhr_id"], "info", self.dict)
|
||||
|
||||
def lineup_dict(self):
|
||||
return {
|
||||
'GuideNumber': self.dict['number'],
|
||||
'GuideName': self.dict['name'],
|
||||
'Tags': ",".join(self.dict['tags']),
|
||||
'URL': self.stream_url(),
|
||||
}
|
||||
|
||||
def stream_url(self):
|
||||
return ('/auto/v%s' % self.dict['number'])
|
||||
|
||||
def play_url(self):
|
||||
return ('/api/m3u?method=get&channel=%s' % self.dict['number'])
|
||||
|
||||
def __getattr__(self, name):
|
||||
''' will only get called for undefined attributes '''
|
||||
if name in list(self.dict.keys()):
|
||||
return self.dict[name]
|
||||
else:
|
||||
return None
|
||||
@ -26,6 +26,7 @@ class EPG():
|
||||
self.epg_method_selfadd()
|
||||
|
||||
self.epg_methods = self.fhdhr.config.dict["epg"]["method"]
|
||||
self.valid_epg_methods = [x for x in self.fhdhr.config.dict["main"]["valid_epg_methods"] if x and x not in [None, "None"]]
|
||||
self.def_method = self.fhdhr.config.dict["epg"]["def_method"]
|
||||
self.sleeptime = {}
|
||||
for epg_method in self.epg_methods:
|
||||
@ -59,8 +60,8 @@ class EPG():
|
||||
|
||||
self.fhdhr.db.delete_fhdhr_value("epg_dict", method)
|
||||
|
||||
def whats_on_now(self, channel):
|
||||
epgdict = self.get_epg()
|
||||
def whats_on_now(self, channel, method=None):
|
||||
epgdict = self.get_epg(method)
|
||||
listings = epgdict[channel]["listing"]
|
||||
for listing in listings:
|
||||
nowtime = datetime.datetime.utcnow()
|
||||
@ -72,10 +73,19 @@ class EPG():
|
||||
return epgitem
|
||||
return None
|
||||
|
||||
def whats_on_allchans(self):
|
||||
def whats_on_allchans(self, method=None):
|
||||
|
||||
if not method:
|
||||
method = self.def_method
|
||||
if (method == self.fhdhr.config.dict["main"]["dictpopname"] or
|
||||
method not in self.fhdhr.config.dict["main"]["valid_epg_methods"]):
|
||||
method = "origin"
|
||||
|
||||
channel_guide_list = []
|
||||
for channel in self.channels.get_channels():
|
||||
whatson = self.whats_on_now(channel["number"])
|
||||
epgdict = self.get_epg(method)
|
||||
channels = list(epgdict.keys())
|
||||
for channel in channels:
|
||||
whatson = self.whats_on_now(epgdict[channel]["number"], method)
|
||||
if whatson:
|
||||
channel_guide_list.append(whatson)
|
||||
return channel_guide_list
|
||||
|
||||
@ -35,7 +35,7 @@ class blocksEPG():
|
||||
"callsign": c["callsign"],
|
||||
"name": c["name"],
|
||||
"number": c["number"],
|
||||
"id": c["id"],
|
||||
"id": c["origin_id"],
|
||||
"thumbnail": ("/api/images?method=generate&type=channel&message=%s" % (str(c['number']))),
|
||||
"listing": [],
|
||||
}
|
||||
@ -45,7 +45,7 @@ class blocksEPG():
|
||||
"time_start": timestamp['time_start'],
|
||||
"time_end": timestamp['time_end'],
|
||||
"duration_minutes": 60,
|
||||
"thumbnail": ("/api/images?method=generate&type=content&message=%s" % (str(c["id"]) + "_" + str(timestamp['time_start']).split(" ")[0])),
|
||||
"thumbnail": ("/api/images?method=generate&type=content&message=%s" % (str(c["origin_id"]) + "_" + str(timestamp['time_start']).split(" ")[0])),
|
||||
"title": "Unavailable",
|
||||
"sub-title": "Unavailable",
|
||||
"description": "Unavailable",
|
||||
@ -56,7 +56,7 @@ class blocksEPG():
|
||||
"seasonnumber": None,
|
||||
"episodenumber": None,
|
||||
"isnew": False,
|
||||
"id": str(c["id"]) + "_" + str(timestamp['time_start']).split(" ")[0],
|
||||
"id": str(c["origin_id"]) + "_" + str(timestamp['time_start']).split(" ")[0],
|
||||
}
|
||||
|
||||
programguide[str(c["number"])]["listing"].append(clean_prog_dict)
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
from flask import request, redirect
|
||||
from flask import request, redirect, Response
|
||||
import urllib.parse
|
||||
import json
|
||||
|
||||
|
||||
class Channels():
|
||||
@ -18,7 +19,30 @@ class Channels():
|
||||
method = request.args.get('method', default=None, type=str)
|
||||
redirect_url = request.args.get('redirect', default=None, type=str)
|
||||
|
||||
if method == "scan":
|
||||
if method == "get":
|
||||
channels_info = []
|
||||
for fhdhr_id in list(self.fhdhr.device.channels.list.keys()):
|
||||
channel_obj = self.fhdhr.device.channels.list[fhdhr_id]
|
||||
channel_dict = channel_obj.dict.copy()
|
||||
channel_dict["play_url"] = channel_obj.play_url()
|
||||
channel_dict["stream_url"] = channel_obj.stream_url()
|
||||
channels_info.append(channel_dict)
|
||||
channels_info_json = json.dumps(channels_info, indent=4)
|
||||
|
||||
return Response(status=200,
|
||||
response=channels_info_json,
|
||||
mimetype='application/json')
|
||||
|
||||
elif method in ["enable", "disable"]:
|
||||
channel = request.args.get('channel', default=None, type=str)
|
||||
if not channel:
|
||||
if redirect_url:
|
||||
return redirect(redirect_url + "?retmessage=" + urllib.parse.quote("%s Failed" % method))
|
||||
else:
|
||||
return "%s Falied" % method
|
||||
self.fhdhr.device.channels.set_channel_status("number", channel, method)
|
||||
|
||||
elif method == "scan":
|
||||
self.fhdhr.device.station_scan.scan()
|
||||
|
||||
else:
|
||||
|
||||
@ -19,7 +19,7 @@ class Debug_JSON():
|
||||
|
||||
debugjson = {
|
||||
"base_url": base_url,
|
||||
"total channels": self.fhdhr.device.channels.get_station_total(),
|
||||
"total channels": len(self.fhdhr.device.channels.list),
|
||||
"tuner status": self.fhdhr.device.tuners.status(),
|
||||
}
|
||||
cluster_json = json.dumps(debugjson, indent=4)
|
||||
|
||||
@ -38,44 +38,50 @@ class M3U():
|
||||
"x-tvg-url=\"" + xmltvurl + "\"")
|
||||
)
|
||||
|
||||
channel_list = self.fhdhr.device.channels.get_channels()
|
||||
channel_number_list = [x["number"] for x in channel_list]
|
||||
channel_items = []
|
||||
|
||||
if channel == "all":
|
||||
channel_items = channel_list
|
||||
elif channel in channel_number_list:
|
||||
channel_items = [self.fhdhr.device.channels.get_channel_dict("number", channel)]
|
||||
fileName = "channels.m3u"
|
||||
for fhdhr_id in list(self.fhdhr.device.channels.list.keys()):
|
||||
channel_obj = self.fhdhr.device.channels.list[fhdhr_id]
|
||||
if channel_obj.enabled:
|
||||
channel_items.append(channel_obj)
|
||||
elif channel in self.fhdhr.device.channels.get_channel_list("number"):
|
||||
channel_obj = self.fhdhr.device.channels.get_channel_obj("number", channel)
|
||||
fileName = str(channel_obj.number) + ".m3u"
|
||||
if channel_obj.enabled:
|
||||
channel_items.append(channel_obj)
|
||||
else:
|
||||
return "Channel Disabled"
|
||||
else:
|
||||
return "Invalid Channel"
|
||||
|
||||
for channel_item in channel_items:
|
||||
for channel_obj in channel_items:
|
||||
|
||||
logourl = ('%s/api/images?method=get&type=channel&id=%s' %
|
||||
(base_url, str(channel_item['id'])))
|
||||
if self.fhdhr.config.dict["epg"]["images"] == "proxy" or not channel_obj.thumbnail:
|
||||
logourl = ('%s/api/images?method=get&type=channel&id=%s' %
|
||||
(base_url, str(channel_obj.dict['origin_id'])))
|
||||
else:
|
||||
logourl = channel_obj.thumbnail
|
||||
|
||||
fakefile.write(
|
||||
"%s\n" % (
|
||||
RECORD_MARKER + ":0" + " " +
|
||||
"channelID=\"" + str(channel_item['id']) + "\" " +
|
||||
"tvg-chno=\"" + str(channel_item['number']) + "\" " +
|
||||
"tvg-name=\"" + str(channel_item['name']) + "\" " +
|
||||
"tvg-id=\"" + str(channel_item['number']) + "\" " +
|
||||
"channelID=\"" + str(channel_obj.dict['origin_id']) + "\" " +
|
||||
"tvg-chno=\"" + str(channel_obj.dict['number']) + "\" " +
|
||||
"tvg-name=\"" + str(channel_obj.dict['name']) + "\" " +
|
||||
"tvg-id=\"" + str(channel_obj.dict['number']) + "\" " +
|
||||
"tvg-logo=\"" + logourl + "\" " +
|
||||
"group-title=\"" + self.fhdhr.config.dict["fhdhr"]["friendlyname"] + "\"," + str(channel_item['name']))
|
||||
"group-title=\"" + self.fhdhr.config.dict["fhdhr"]["friendlyname"] + "\"," + str(channel_obj.dict['name']))
|
||||
)
|
||||
|
||||
fakefile.write(
|
||||
"%s\n" % (
|
||||
('%s/auto/v%s' %
|
||||
(base_url, str(channel_item['number'])))
|
||||
)
|
||||
)
|
||||
fakefile.write("%s\n" % (base_url + channel_obj.stream_url()))
|
||||
|
||||
channels_m3u = fakefile.getvalue()
|
||||
|
||||
return Response(status=200,
|
||||
response=channels_m3u,
|
||||
mimetype='audio/x-mpegurl')
|
||||
resp = Response(status=200, response=channels_m3u, mimetype='audio/x-mpegurl')
|
||||
resp.headers["content-disposition"] = "attachment; filename=" + fileName
|
||||
return resp
|
||||
|
||||
if redirect_url:
|
||||
return redirect(redirect_url + "?retmessage=" + urllib.parse.quote("%s Success" % method))
|
||||
|
||||
@ -18,7 +18,9 @@ class Watch():
|
||||
|
||||
def get(self, *args):
|
||||
|
||||
full_url = request.url
|
||||
client_address = request.remote_addr
|
||||
|
||||
accessed_url = request.args.get('accessed', default=request.url, type=str)
|
||||
|
||||
method = request.args.get('method', default=self.fhdhr.config.dict["fhdhr"]["stream_type"], type=str)
|
||||
|
||||
@ -32,9 +34,17 @@ class Watch():
|
||||
if not channel_number:
|
||||
return "Missing Channel"
|
||||
|
||||
if channel_number not in list(self.fhdhr.device.channels.list.keys()):
|
||||
if channel_number not in self.fhdhr.device.channels.get_channel_list("number"):
|
||||
response = Response("Not Found", status=404)
|
||||
response.headers["X-fHDHR-Error"] = "801 - Unknown Channel"
|
||||
self.fhdhr.logger.error(response.headers["X-fHDHR-Error"])
|
||||
abort(response)
|
||||
|
||||
channel_dict = self.fhdhr.device.channels.get_channel_dict("number", channel_number)
|
||||
if not channel_dict["enabled"]:
|
||||
response = Response("Service Unavailable", status=503)
|
||||
response.headers["X-fHDHR-Error"] = str("806 - Tune Failed")
|
||||
self.fhdhr.logger.error(response.headers["X-fHDHR-Error"])
|
||||
abort(response)
|
||||
|
||||
duration = request.args.get('duration', default=0, type=int)
|
||||
@ -44,6 +54,7 @@ class Watch():
|
||||
if transcode not in valid_transcode_types:
|
||||
response = Response("Service Unavailable", status=503)
|
||||
response.headers["X-fHDHR-Error"] = "802 - Unknown Transcode Profile"
|
||||
self.fhdhr.logger.error(response.headers["X-fHDHR-Error"])
|
||||
abort(response)
|
||||
|
||||
stream_args = {
|
||||
@ -51,7 +62,8 @@ class Watch():
|
||||
"method": method,
|
||||
"duration": duration,
|
||||
"transcode": transcode,
|
||||
"accessed": full_url,
|
||||
"accessed": accessed_url,
|
||||
"client": client_address
|
||||
}
|
||||
|
||||
try:
|
||||
@ -64,6 +76,7 @@ class Watch():
|
||||
% (stream_args["method"], str(stream_args["channel"]), str(e)))
|
||||
response = Response("Service Unavailable", status=503)
|
||||
response.headers["X-fHDHR-Error"] = str(e)
|
||||
self.fhdhr.logger.error(response.headers["X-fHDHR-Error"])
|
||||
abort(response)
|
||||
tuner = self.fhdhr.device.tuners.tuners[int(tunernum)]
|
||||
|
||||
@ -74,6 +87,7 @@ class Watch():
|
||||
% (stream_args["method"], str(stream_args["channel"]), str(e)))
|
||||
response = Response("Service Unavailable", status=503)
|
||||
response.headers["X-fHDHR-Error"] = str(e)
|
||||
self.fhdhr.logger.error(response.headers["X-fHDHR-Error"])
|
||||
tuner.close()
|
||||
abort(response)
|
||||
|
||||
|
||||
@ -16,7 +16,14 @@ class Lineup_JSON():
|
||||
|
||||
base_url = request.url_root[:-1]
|
||||
|
||||
jsonlineup = self.fhdhr.device.channels.get_station_list(base_url)
|
||||
jsonlineup = []
|
||||
for fhdhr_id in list(self.fhdhr.device.channels.list.keys()):
|
||||
channel_obj = self.fhdhr.device.channels.list[fhdhr_id]
|
||||
if channel_obj.enabled:
|
||||
lineup_dict = channel_obj.lineup_dict()
|
||||
lineup_dict["URL"] = base_url + lineup_dict["URL"]
|
||||
jsonlineup.append(lineup_dict)
|
||||
|
||||
lineup_json = json.dumps(jsonlineup, indent=4)
|
||||
|
||||
return Response(status=200,
|
||||
|
||||
@ -17,7 +17,7 @@ class Lineup_Status_JSON():
|
||||
station_scanning = self.fhdhr.device.station_scan.scanning()
|
||||
if station_scanning:
|
||||
jsonlineup = self.scan_in_progress()
|
||||
elif not self.fhdhr.device.channels.get_station_total():
|
||||
elif not len(self.fhdhr.device.channels.list):
|
||||
jsonlineup = self.scan_in_progress()
|
||||
else:
|
||||
jsonlineup = self.not_scanning()
|
||||
@ -28,11 +28,10 @@ class Lineup_Status_JSON():
|
||||
mimetype='application/json')
|
||||
|
||||
def scan_in_progress(self):
|
||||
channel_count = self.fhdhr.device.channels.get_station_total()
|
||||
jsonlineup = {
|
||||
"ScanInProgress": "true",
|
||||
"Progress": 99,
|
||||
"Found": channel_count
|
||||
"Found": len(self.fhdhr.device.channels.list)
|
||||
}
|
||||
return jsonlineup
|
||||
|
||||
|
||||
@ -20,13 +20,16 @@ class Lineup_XML():
|
||||
base_url = request.url_root[:-1]
|
||||
|
||||
out = xml.etree.ElementTree.Element('Lineup')
|
||||
station_list = self.fhdhr.device.channels.get_station_list(base_url)
|
||||
for station_item in station_list:
|
||||
program_out = sub_el(out, 'Program')
|
||||
sub_el(program_out, 'GuideNumber', station_item['GuideNumber'])
|
||||
sub_el(program_out, 'GuideName', station_item['GuideName'])
|
||||
sub_el(program_out, 'Tags', ",".join(station_item['Tags']))
|
||||
sub_el(program_out, 'URL', station_item['URL'])
|
||||
for fhdhr_id in list(self.fhdhr.device.channels.list.keys()):
|
||||
channel_obj = self.fhdhr.device.channels.list[fhdhr_id]
|
||||
if channel_obj.enabled:
|
||||
lineup_dict = channel_obj.lineup_dict()
|
||||
lineup_dict["URL"] = base_url + lineup_dict["URL"]
|
||||
program_out = sub_el(out, 'Program')
|
||||
sub_el(program_out, 'GuideNumber', lineup_dict['GuideNumber'])
|
||||
sub_el(program_out, 'GuideName', lineup_dict['GuideName'])
|
||||
sub_el(program_out, 'Tags', lineup_dict['Tags'])
|
||||
sub_el(program_out, 'URL', lineup_dict['URL'])
|
||||
|
||||
fakefile = BytesIO()
|
||||
fakefile.write(b'<?xml version="1.0" encoding="UTF-8"?>\n')
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
from .index_html import Index_HTML
|
||||
from .origin_html import Origin_HTML
|
||||
from .channels_html import Channels_HTML
|
||||
from .guide_html import Guide_HTML
|
||||
from .cluster_html import Cluster_HTML
|
||||
from .streams_html import Streams_HTML
|
||||
@ -18,6 +19,7 @@ class fHDHR_Pages():
|
||||
|
||||
self.index_html = Index_HTML(fhdhr)
|
||||
self.origin_html = Origin_HTML(fhdhr)
|
||||
self.channels_html = Channels_HTML(fhdhr)
|
||||
self.guide_html = Guide_HTML(fhdhr)
|
||||
self.cluster_html = Cluster_HTML(fhdhr)
|
||||
self.streams_html = Streams_HTML(fhdhr)
|
||||
|
||||
23
fHDHR/http/pages/channels_html.py
Normal file
23
fHDHR/http/pages/channels_html.py
Normal file
@ -0,0 +1,23 @@
|
||||
from flask import request, render_template
|
||||
|
||||
|
||||
class Channels_HTML():
|
||||
endpoints = ["/channels", "/channels.html"]
|
||||
endpoint_name = "channels_html"
|
||||
|
||||
def __init__(self, fhdhr):
|
||||
self.fhdhr = fhdhr
|
||||
|
||||
def __call__(self, *args):
|
||||
return self.get(*args)
|
||||
|
||||
def get(self, *args):
|
||||
|
||||
channelslist = []
|
||||
for fhdhr_id in list(self.fhdhr.device.channels.list.keys()):
|
||||
channel_obj = self.fhdhr.device.channels.list[fhdhr_id]
|
||||
channel_dict = channel_obj.dict.copy()
|
||||
channel_dict["play_url"] = channel_obj.play_url()
|
||||
channelslist.append(channel_dict)
|
||||
|
||||
return render_template('channels.html', request=request, fhdhr=self.fhdhr, channelslist=channelslist)
|
||||
@ -4,7 +4,7 @@ import urllib.parse
|
||||
|
||||
class Cluster_HTML():
|
||||
endpoints = ["/cluster", "/cluster.html"]
|
||||
endpoint_name = "cluster"
|
||||
endpoint_name = "cluster_html"
|
||||
|
||||
def __init__(self, fhdhr):
|
||||
self.fhdhr = fhdhr
|
||||
|
||||
@ -3,7 +3,7 @@ from flask import request, render_template
|
||||
|
||||
class Diagnostics_HTML():
|
||||
endpoints = ["/diagnostics", "/diagnostics.html"]
|
||||
endpoint_name = "diagnostics"
|
||||
endpoint_name = "diagnostics_html"
|
||||
|
||||
def __init__(self, fhdhr):
|
||||
self.fhdhr = fhdhr
|
||||
|
||||
@ -6,7 +6,7 @@ from fHDHR.tools import humanized_time
|
||||
|
||||
class Guide_HTML():
|
||||
endpoints = ["/guide", "/guide.html"]
|
||||
endpoint_name = "guide"
|
||||
endpoint_name = "guide_html"
|
||||
|
||||
def __init__(self, fhdhr):
|
||||
self.fhdhr = fhdhr
|
||||
@ -20,13 +20,16 @@ class Guide_HTML():
|
||||
|
||||
chan_guide_list = []
|
||||
|
||||
for channel in self.fhdhr.device.epg.whats_on_allchans():
|
||||
source = request.args.get('source', default=self.fhdhr.device.epg.def_method, type=str)
|
||||
epg_methods = self.fhdhr.device.epg.valid_epg_methods
|
||||
if source not in epg_methods:
|
||||
source = self.fhdhr.device.epg.def_method
|
||||
|
||||
for channel in self.fhdhr.device.epg.whats_on_allchans(source):
|
||||
end_time = datetime.datetime.strptime(channel["listing"][0]["time_end"], '%Y%m%d%H%M%S +0000')
|
||||
remaining_time = humanized_time(int((end_time - nowtime).total_seconds()))
|
||||
play_url = ("/api/m3u?method=get&channel=%s\n" % (channel["number"]))
|
||||
|
||||
chan_dict = {
|
||||
"play_url": play_url,
|
||||
"name": channel["name"],
|
||||
"number": channel["number"],
|
||||
"chan_thumbnail": channel["thumbnail"],
|
||||
@ -37,4 +40,4 @@ class Guide_HTML():
|
||||
}
|
||||
chan_guide_list.append(chan_dict)
|
||||
|
||||
return render_template('guide.html', request=request, fhdhr=self.fhdhr, chan_guide_list=chan_guide_list)
|
||||
return render_template('guide.html', request=request, fhdhr=self.fhdhr, chan_guide_list=chan_guide_list, epg_methods=epg_methods)
|
||||
|
||||
@ -3,7 +3,7 @@ from flask import request, render_template
|
||||
|
||||
class Index_HTML():
|
||||
endpoints = ["/", "/index", "/index.html"]
|
||||
endpoint_name = "root"
|
||||
endpoint_name = "root_html"
|
||||
|
||||
def __init__(self, fhdhr):
|
||||
self.fhdhr = fhdhr
|
||||
@ -20,7 +20,7 @@ class Index_HTML():
|
||||
"Script Directory": str(self.fhdhr.config.internal["paths"]["script_dir"]),
|
||||
"Config File": str(self.fhdhr.config.config_file),
|
||||
"Cache Path": str(self.fhdhr.config.internal["paths"]["cache_dir"]),
|
||||
"Total Channels": str(self.fhdhr.device.channels.get_station_total()),
|
||||
"Total Channels": len(self.fhdhr.device.channels.list),
|
||||
"Tuner Usage": ("%s/%s" % (str(tuners_in_use), str(max_tuners))),
|
||||
}
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ from flask import request, render_template
|
||||
|
||||
class Origin_HTML():
|
||||
endpoints = ["/origin", "/origin.html"]
|
||||
endpoint_name = "origin"
|
||||
endpoint_name = "origin_html"
|
||||
|
||||
def __init__(self, fhdhr):
|
||||
self.fhdhr = fhdhr
|
||||
@ -13,6 +13,6 @@ class Origin_HTML():
|
||||
|
||||
def get(self, *args):
|
||||
|
||||
origin_status_dict = self.fhdhr.device.channels.get_origin_status()
|
||||
origin_status_dict["Total Channels"] = str(self.fhdhr.device.channels.get_station_total())
|
||||
origin_status_dict = self.fhdhr.origin.get_status_dict()
|
||||
origin_status_dict["Total Channels"] = len(self.fhdhr.device.channels.list)
|
||||
return render_template('origin.html', request=request, fhdhr=self.fhdhr, origin_status_dict=origin_status_dict, list=list)
|
||||
|
||||
@ -3,7 +3,7 @@ from flask import request, render_template
|
||||
|
||||
class Settings_HTML():
|
||||
endpoints = ["/settings", "/settings.html"]
|
||||
endpoint_name = "settings"
|
||||
endpoint_name = "settings_html"
|
||||
|
||||
def __init__(self, fhdhr):
|
||||
self.fhdhr = fhdhr
|
||||
|
||||
@ -3,7 +3,7 @@ from flask import request, render_template
|
||||
|
||||
class Streams_HTML():
|
||||
endpoints = ["/streams", "/streams.html"]
|
||||
endpoint_name = "streams"
|
||||
endpoint_name = "streams_html"
|
||||
|
||||
def __init__(self, fhdhr):
|
||||
self.fhdhr = fhdhr
|
||||
|
||||
@ -3,7 +3,7 @@ from flask import request, render_template
|
||||
|
||||
class Version_HTML():
|
||||
endpoints = ["/version", "/version.html"]
|
||||
endpoint_name = "version"
|
||||
endpoint_name = "version_html"
|
||||
|
||||
def __init__(self, fhdhr):
|
||||
self.fhdhr = fhdhr
|
||||
|
||||
@ -3,7 +3,7 @@ from flask import request, render_template
|
||||
|
||||
class xmlTV_HTML():
|
||||
endpoints = ["/xmltv", "/xmltv.html"]
|
||||
endpoint_name = "xmltv"
|
||||
endpoint_name = "xmltv_html"
|
||||
|
||||
def __init__(self, fhdhr):
|
||||
self.fhdhr = fhdhr
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
from flask import Response, request, stream_with_context, abort
|
||||
|
||||
from fHDHR.exceptions import TunerError
|
||||
from flask import request, abort, redirect
|
||||
import urllib.parse
|
||||
|
||||
|
||||
class Auto():
|
||||
@ -15,7 +14,9 @@ class Auto():
|
||||
|
||||
def get(self, channel, *args):
|
||||
|
||||
full_url = request.url
|
||||
method = request.args.get('method', default=self.fhdhr.config.dict["fhdhr"]["stream_type"], type=str)
|
||||
|
||||
redirect_url = "/api/watch?method=%s" % (method)
|
||||
|
||||
if channel.startswith("v"):
|
||||
channel_number = channel.replace('v', '')
|
||||
@ -24,70 +25,21 @@ class Auto():
|
||||
subchannel = 0
|
||||
if "-" in channel:
|
||||
subchannel = channel.replace('ch', '').split("-")[1]
|
||||
self.fhdhr.logger.error("Not Implemented %s-%s" % (str(channel_freq), str(subchannel)))
|
||||
abort(501, "Not Implemented %s-%s" % (str(channel_freq), str(subchannel)))
|
||||
else:
|
||||
channel_number = channel
|
||||
|
||||
if channel_number not in list(self.fhdhr.device.channels.list.keys()):
|
||||
response = Response("Not Found", status=404)
|
||||
response.headers["X-fHDHR-Error"] = "801 - Unknown Channel"
|
||||
abort(response)
|
||||
redirect_url += "&channel=%s" % str(channel_number)
|
||||
|
||||
method = request.args.get('method', default=self.fhdhr.config.dict["fhdhr"]["stream_type"], type=str)
|
||||
duration = request.args.get('duration', default=0, type=int)
|
||||
if duration:
|
||||
redirect_url += "&duration=%s" % str(duration)
|
||||
|
||||
transcode = request.args.get('transcode', default=None, type=str)
|
||||
valid_transcode_types = [None, "heavy", "mobile", "internet720", "internet480", "internet360", "internet240"]
|
||||
if transcode not in valid_transcode_types:
|
||||
response = Response("Service Unavailable", status=503)
|
||||
response.headers["X-fHDHR-Error"] = "802 - Unknown Transcode Profile"
|
||||
abort(response)
|
||||
if transcode:
|
||||
redirect_url += "&transcode=%s" % str(transcode)
|
||||
|
||||
stream_args = {
|
||||
"channel": channel_number,
|
||||
"method": method,
|
||||
"duration": duration,
|
||||
"transcode": transcode,
|
||||
"accessed": full_url,
|
||||
}
|
||||
redirect_url += "&accessed=%s" % urllib.parse.quote(request.url)
|
||||
|
||||
try:
|
||||
tunernum = self.fhdhr.device.tuners.first_available()
|
||||
except TunerError as e:
|
||||
self.fhdhr.logger.info("A %s stream request for channel %s was rejected due to %s"
|
||||
% (stream_args["method"], str(stream_args["channel"]), str(e)))
|
||||
response = Response("Service Unavailable", status=503)
|
||||
response.headers["X-fHDHR-Error"] = str(e)
|
||||
abort(response)
|
||||
tuner = self.fhdhr.device.tuners.tuners[int(tunernum)]
|
||||
|
||||
try:
|
||||
stream_args = self.fhdhr.device.tuners.get_stream_info(stream_args)
|
||||
except TunerError as e:
|
||||
self.fhdhr.logger.info("A %s stream request for channel %s was rejected due to %s"
|
||||
% (stream_args["method"], str(stream_args["channel"]), str(e)))
|
||||
response = Response("Service Unavailable", status=503)
|
||||
response.headers["X-fHDHR-Error"] = str(e)
|
||||
tuner.close()
|
||||
abort(response)
|
||||
|
||||
self.fhdhr.logger.info("Tuner #" + str(tunernum) + " to be used for stream.")
|
||||
tuner.set_status(stream_args)
|
||||
|
||||
if stream_args["method"] == "direct":
|
||||
return Response(tuner.get_stream(stream_args, tuner), content_type=stream_args["content_type"], direct_passthrough=True)
|
||||
elif stream_args["method"] in ["ffmpeg", "vlc"]:
|
||||
return Response(stream_with_context(tuner.get_stream(stream_args, tuner)), mimetype=stream_args["content_type"])
|
||||
|
||||
"""
|
||||
try:
|
||||
if stream_args["method"] == "direct":
|
||||
return Response(tuner.get_stream(stream_args, tuner), content_type=stream_args["content_type"], direct_passthrough=True)
|
||||
elif stream_args["method"] in ["ffmpeg", "vlc"]:
|
||||
return Response(stream_with_context(tuner.get_stream(stream_args, tuner)), mimetype=stream_args["content_type"])
|
||||
except TunerError as e:
|
||||
tuner.close()
|
||||
self.fhdhr.logger.info("A %s stream request for channel %s failed due to %s"
|
||||
% (stream_args["method"], str(stream_args["channel"]), str(e)))
|
||||
response = Response("Service Unavailable", status=503)
|
||||
response.headers["X-fHDHR-Error"] = str(e)
|
||||
abort(response)
|
||||
"""
|
||||
return redirect(redirect_url)
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
from flask import Response, request, stream_with_context, abort
|
||||
|
||||
from fHDHR.exceptions import TunerError
|
||||
from flask import request, abort, redirect
|
||||
import urllib.parse
|
||||
|
||||
|
||||
class Tuner():
|
||||
@ -15,7 +14,11 @@ class Tuner():
|
||||
|
||||
def get(self, tuner_number, channel, *args):
|
||||
|
||||
full_url = request.url
|
||||
method = request.args.get('method', default=self.fhdhr.config.dict["fhdhr"]["stream_type"], type=str)
|
||||
|
||||
redirect_url = "/api/watch?method=%s" % (method)
|
||||
|
||||
redirect_url += "&tuner=%s" % str(tuner_number)
|
||||
|
||||
if channel.startswith("v"):
|
||||
channel_number = channel.replace('v', '')
|
||||
@ -24,70 +27,21 @@ class Tuner():
|
||||
subchannel = 0
|
||||
if "-" in channel:
|
||||
subchannel = channel.replace('ch', '').split("-")[1]
|
||||
self.fhdhr.logger.error("Not Implemented %s-%s" % (str(channel_freq), str(subchannel)))
|
||||
abort(501, "Not Implemented %s-%s" % (str(channel_freq), str(subchannel)))
|
||||
else:
|
||||
channel_number = channel
|
||||
|
||||
if channel_number not in list(self.fhdhr.device.channels.list.keys()):
|
||||
response = Response("Not Found", status=404)
|
||||
response.headers["X-fHDHR-Error"] = "801 - Unknown Channel"
|
||||
abort(response)
|
||||
redirect_url += "&channel=%s" % str(channel_number)
|
||||
|
||||
method = request.args.get('method', default=self.fhdhr.config.dict["fhdhr"]["stream_type"], type=str)
|
||||
duration = request.args.get('duration', default=0, type=int)
|
||||
if duration:
|
||||
redirect_url += "&duration=%s" % str(duration)
|
||||
|
||||
transcode = request.args.get('transcode', default=None, type=str)
|
||||
valid_transcode_types = [None, "heavy", "mobile", "internet720", "internet480", "internet360", "internet240"]
|
||||
if transcode not in valid_transcode_types:
|
||||
response = Response("Service Unavailable", status=503)
|
||||
response.headers["X-fHDHR-Error"] = "802 - Unknown Transcode Profile"
|
||||
abort(response)
|
||||
if transcode:
|
||||
redirect_url += "&transcode=%s" % str(transcode)
|
||||
|
||||
stream_args = {
|
||||
"channel": channel_number,
|
||||
"method": method,
|
||||
"duration": duration,
|
||||
"transcode": transcode,
|
||||
"accessed": full_url,
|
||||
}
|
||||
redirect_url += "&accessed=%s" % urllib.parse.quote(request.url)
|
||||
|
||||
try:
|
||||
tunernum = self.fhdhr.device.tuners.tuner_grab(tuner_number)
|
||||
except TunerError as e:
|
||||
self.fhdhr.logger.info("A %s stream request for channel %s was rejected due to %s"
|
||||
% (stream_args["method"], str(stream_args["channel"]), str(e)))
|
||||
response = Response("Service Unavailable", status=503)
|
||||
response.headers["X-fHDHR-Error"] = str(e)
|
||||
abort(response)
|
||||
tuner = self.fhdhr.device.tuners.tuners[int(tunernum)]
|
||||
|
||||
try:
|
||||
stream_args = self.fhdhr.device.tuners.get_stream_info(stream_args)
|
||||
except TunerError as e:
|
||||
self.fhdhr.logger.info("A %s stream request for channel %s was rejected due to %s"
|
||||
% (stream_args["method"], str(stream_args["channel"]), str(e)))
|
||||
response = Response("Service Unavailable", status=503)
|
||||
response.headers["X-fHDHR-Error"] = str(e)
|
||||
tuner.close()
|
||||
abort(response)
|
||||
|
||||
self.fhdhr.logger.info("Tuner #" + str(tunernum) + " to be used for stream.")
|
||||
tuner.set_status(stream_args)
|
||||
|
||||
if stream_args["method"] == "direct":
|
||||
return Response(tuner.get_stream(stream_args, tuner), content_type=stream_args["content_type"], direct_passthrough=True)
|
||||
elif stream_args["method"] in ["ffmpeg", "vlc"]:
|
||||
return Response(stream_with_context(tuner.get_stream(stream_args, tuner)), mimetype=stream_args["content_type"])
|
||||
|
||||
"""
|
||||
try:
|
||||
if stream_args["method"] == "direct":
|
||||
return Response(tuner.get_stream(stream_args, tuner), content_type=stream_args["content_type"], direct_passthrough=True)
|
||||
elif stream_args["method"] in ["ffmpeg", "vlc"]:
|
||||
return Response(stream_with_context(tuner.get_stream(stream_args, tuner)), mimetype=stream_args["content_type"])
|
||||
except TunerError as e:
|
||||
tuner.close()
|
||||
self.fhdhr.logger.info("A %s stream request for channel %s failed due to %s"
|
||||
% (stream_args["method"], str(stream_args["channel"]), str(e)))
|
||||
response = Response("Service Unavailable", status=503)
|
||||
response.headers["X-fHDHR-Error"] = str(e)
|
||||
abort(response)
|
||||
"""
|
||||
return redirect(redirect_url)
|
||||
|
||||
@ -20,8 +20,8 @@ class OriginChannels_StandIN():
|
||||
def get_channels(self):
|
||||
return []
|
||||
|
||||
def get_channel_stream(self, chandict, allchandict):
|
||||
return [{"number": chandict["number"], "stream_url": None}], False
|
||||
def get_channel_stream(self, chandict):
|
||||
return None
|
||||
|
||||
|
||||
class OriginServiceWrapper():
|
||||
@ -54,8 +54,8 @@ class OriginServiceWrapper():
|
||||
def get_channels(self):
|
||||
return self.channels.get_channels()
|
||||
|
||||
def get_channel_stream(self, chandict, allchandict):
|
||||
return self.channels.get_channel_stream(chandict, allchandict)
|
||||
def get_channel_stream(self, chandict):
|
||||
return self.channels.get_channel_stream(chandict)
|
||||
|
||||
def update_epg(self, channels):
|
||||
return self.epg.update_epg(channels)
|
||||
|
||||
@ -40,10 +40,7 @@ class OriginChannels():
|
||||
channel_list.append(clean_station_item)
|
||||
return channel_list
|
||||
|
||||
def get_channel_stream(self, chandict, allchandict):
|
||||
caching = True
|
||||
streamlist = []
|
||||
streamdict = {}
|
||||
def get_channel_stream(self, chandict):
|
||||
streamurl = ('%s%s:%s/live?channel=%s&client=%s' %
|
||||
("https://" if self.fhdhr.config.dict["origin"]["ssl"] else "http://",
|
||||
self.fhdhr.config.dict["origin"]["address"],
|
||||
@ -51,6 +48,4 @@ class OriginChannels():
|
||||
str(chandict["number"]),
|
||||
str(chandict["number"]),
|
||||
))
|
||||
streamdict = {"number": chandict["number"], "stream_url": streamurl}
|
||||
streamlist.append(streamdict)
|
||||
return streamlist, caching
|
||||
return streamurl
|
||||
|
||||
@ -49,8 +49,8 @@ class OriginEPG():
|
||||
"callsign": cdict["callsign"],
|
||||
"name": cdict["name"] or cdict["callsign"],
|
||||
"number": cdict["number"],
|
||||
"id": str(cdict["id"]),
|
||||
"thumbnail": self.get_channel_thumbnail(cdict['id']),
|
||||
"id": str(cdict["origin_id"]),
|
||||
"thumbnail": self.get_channel_thumbnail(cdict['origin_id']),
|
||||
"listing": [],
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ class OriginEPG():
|
||||
("https://" if self.fhdhr.config.dict["origin"]["ssl"] else "http://",
|
||||
self.fhdhr.config.dict["origin"]["address"],
|
||||
str(self.fhdhr.config.dict["origin"]["port"]),
|
||||
str(cdict["id"]),
|
||||
str(cdict["origin_id"]),
|
||||
))
|
||||
epg_req = self.fhdhr.web.session.get(epg_url)
|
||||
epg_dict = xmltodict.parse(epg_req.content)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user