Repository URL to install this package:
|
Version:
3.32-20211018 ▾
|
enigma2-plugin-extensions-xstreamity
/
usr
/
lib
/
enigma2
/
python
/
Plugins
/
Extensions
/
XStreamity
/
catchup.py
|
|---|
#!/usr/bin/python
# -*- coding: utf-8 -*-
from . import _
from . import streamplayer
from . import xstreamity_globals as glob
from .plugin import skin_path, screenwidth, hdr, cfg, common_path, dir_tmp, downloads_json, pythonVer
from .xStaticText import StaticText
from Components.ActionMap import ActionMap
from Components.Sources.List import List
from Components.Pixmap import Pixmap
from Components.config import config
from datetime import datetime, timedelta
from enigma import eTimer, eServiceReference
from PIL import Image, ImageChops, ImageFile, PngImagePlugin
from requests.adapters import HTTPAdapter
from Screens.MessageBox import MessageBox
from Screens.Screen import Screen
from Tools.LoadPixmap import LoadPixmap
from twisted.web.client import downloadPage
try:
from urlparse import urlparse
except:
from urllib.parse import urlparse
import base64
import json
import math
import os
import re
import requests
import sys
import time
# https twisted client hack #
try:
from twisted.internet import ssl
from twisted.internet._sslverify import ClientTLSOptions
sslverify = True
except:
sslverify = False
if sslverify:
class SNIFactory(ssl.ClientContextFactory):
def __init__(self, hostname=None):
self.hostname = hostname
def getContext(self):
ctx = self._contextFactory(self.method)
if self.hostname:
ClientTLSOptions(self.hostname, ctx)
return ctx
def mycall(self, cid, pos, length):
if cid.decode("ascii") == "tRNS":
return self.chunk_TRNS(pos, length)
else:
return getattr(self, "chunk_" + cid.decode("ascii"))(pos, length)
def mychunk_TRNS(self, pos, length):
i16 = PngImagePlugin.i16
_simple_palette = re.compile(b"^\xff*\x00\xff*$")
s = ImageFile._safe_read(self.fp, length)
if self.im_mode == "P":
if _simple_palette.match(s):
i = s.find(b"\0")
if i >= 0:
self.im_info["transparency"] = i
else:
self.im_info["transparency"] = s
elif self.im_mode in ("1", "L", "I"):
self.im_info["transparency"] = i16(s)
elif self.im_mode == "RGB":
self.im_info["transparency"] = i16(s), i16(s, 2), i16(s, 4)
return s
if pythonVer != 2:
PngImagePlugin.ChunkStream.call = mycall
PngImagePlugin.PngStream.chunk_TRNS = mychunk_TRNS
_initialized = 0
def _mypreinit():
global _initialized
if _initialized >= 1:
return
try:
from . import MyPngImagePlugin
assert MyPngImagePlugin
except ImportError:
pass
_initialized = 1
Image.preinit = _mypreinit
class XStreamity_Catchup(Screen):
def __init__(self, session):
Screen.__init__(self, session)
self.session = session
skin = skin_path + 'catchup.xml'
with open(skin, 'r') as f:
self.skin = f.read()
self.setup_title = (_('Catch Up TV'))
self.main_title = (_('Catch Up TV'))
url = str(glob.current_playlist['playlist_info']['player_api']) + "&action=get_live_categories"
self.level = 1
glob.nextlist = []
glob.nextlist.append({"playlist_url": url, "index": 0, "level": self.level})
self["channel"] = StaticText(self.main_title)
self.list = []
self.channelList = []
self["channel_list"] = List(self.channelList, enableWrapAround=True)
self.selectedlist = self["channel_list"]
# epg variables
self["epg_bg"] = Pixmap()
self["epg_bg"].hide()
self["epg_title"] = StaticText()
self["epg_description"] = StaticText()
self.epgshortlist = []
self["epg_short_list"] = List(self.epgshortlist, enableWrapAround=True)
self["epg_short_list"].onSelectionChanged.append(self.displayShortEPG)
self["epg_picon"] = Pixmap()
self["epg_picon"].hide()
self["key_red"] = StaticText(_('Back'))
self["key_green"] = StaticText(_('OK'))
self["key_yellow"] = StaticText('')
self["key_rec"] = StaticText('')
self.isStream = False
self.pin = False
self.protocol = glob.current_playlist['playlist_info']['protocol']
self.domain = glob.current_playlist['playlist_info']['domain']
self.host = glob.current_playlist['playlist_info']['host']
self.livetype = glob.current_playlist['player_info']['livetype']
self.username = glob.current_playlist['playlist_info']['username']
self.password = glob.current_playlist['playlist_info']['password']
self.output = glob.current_playlist['playlist_info']['output']
self.live_categories = str(glob.current_playlist['playlist_info']['player_api']) + "&action=get_live_categories"
self.live_streams = str(glob.current_playlist['playlist_info']['player_api']) + "&action=get_live_streams"
self.simpledatatable = str(glob.current_playlist['playlist_info']['player_api']) + "&action=get_simple_data_table&stream_id="
self["page"] = StaticText('')
self["listposition"] = StaticText('')
self.page = 0
self.pageall = 0
self.position = 0
self.positionall = 0
self.itemsperpage = 10
self.showingshortEPG = False
self.listType = ''
self["actions"] = ActionMap(["XStreamityActions"], {
'red': self.back,
'cancel': self.back,
'ok': self.parentalCheck,
'green': self.parentalCheck,
'yellow': self.reverse,
"left": self.pageUp,
"right": self.pageDown,
"up": self.goUp,
"down": self.goDown,
"channelUp": self.pageUp,
"channelDown": self.pageDown,
"0": self.reset,
"rec": self.downloadVideo,
"5": self.downloadVideo,
}, -2)
self.onFirstExecBegin.append(self.createSetup)
self.onLayoutFinish.append(self.__layoutFinished)
def __layoutFinished(self):
self.setTitle(self.setup_title)
def goUp(self):
instance = self.selectedlist.master.master.instance
instance.moveSelection(instance.moveUp)
self.selectionChanged()
def goDown(self):
instance = self.selectedlist.master.master.instance
instance.moveSelection(instance.moveDown)
self.selectionChanged()
def pageUp(self):
instance = self.selectedlist.master.master.instance
instance.moveSelection(instance.pageUp)
self.selectionChanged()
def pageDown(self):
instance = self.selectedlist.master.master.instance
instance.moveSelection(instance.pageDown)
self.selectionChanged()
def reset(self):
self.selectedlist.setIndex(0)
self.selectionChanged()
def createSetup(self):
self["epg_title"].setText('')
self["epg_description"].setText('')
self.downloadLiveStreams()
if self.level == 1:
url = glob.nextlist[-1]['playlist_url']
response = glob.current_playlist['data']['live_categories']
self.processData(response, url)
else:
self.downloadData()
def downloadData(self):
url = glob.nextlist[-1]["playlist_url"]
levelpath = str(dir_tmp) + 'level' + str(self.level) + '.xml'
if not os.path.exists(levelpath):
adapter = HTTPAdapter(max_retries=0)
http = requests.Session()
http.mount("http://", adapter)
http.mount("https://", adapter)
try:
r = http.get(url, headers=hdr, stream=True, timeout=10, verify=False)
r.raise_for_status()
if r.status_code == requests.codes.ok:
content = r.json()
with open(levelpath, 'w') as f:
f.write(json.dumps(content))
self.processData(content, url)
except Exception as e:
print(e)
else:
with open(levelpath, "r") as f:
content = f.read()
self.processData(json.loads(content), url)
def processData(self, response, url):
self.channelList = []
currentCategory = ''
index = 0
# ~~~~~~~~~~~~~~~ level 1 ~~~~~~~~~~~~~~~ #
if "&action=get_live_categories" in url:
self.isStream = False
self.listType = "category"
currentCategory = glob.current_playlist['data']['live_categories']
nextAction = "&action=get_live_streams&category_id="
# ~~~~~~~~~~~~~~~ level 2 ~~~~~~~~~~~~~~~ #
elif "&action=get_live_streams" in url:
currentCategory = response
nextAction = ''
self.isStream = True
self.listType = "live_streams"
self.list = []
if self.listType == "category":
for item in currentCategory:
for archive in self.live_list_archive:
category_id = ''
category_name = ''
if "category_id" in item:
if item['category_id'] == archive['category_id']:
if 'category_name' in item:
category_name = item['category_name']
category_id = item['category_id']
next_url = "%s%s%s" % (glob.current_playlist['playlist_info']['player_api'], nextAction, category_id)
if category_id not in glob.current_playlist['player_info']['livehidden']:
self.list.append([index, str(category_name), str(next_url), str(category_id)])
index += 1
break
self.buildLists()
elif self.listType == "live_streams":
for item in currentCategory:
name = ''
stream_id = ''
stream_icon = ''
epg_channel_id = ''
added = ''
if 'tv_archive' in item and 'tv_archive_duration' in item:
if item['tv_archive'] == 1 and item['tv_archive_duration'] != "0":
if 'name' in item and item['name']:
name = item['name']
if 'stream_id' in item and item['stream_id']:
stream_id = item['stream_id']
if 'stream_icon' in item and item['stream_icon']:
if item['stream_icon'].startswith("http"):
stream_icon = item['stream_icon']
if 'epg_channel_id' in item and item['epg_channel_id']:
epg_channel_id = item['epg_channel_id']
if epg_channel_id and "&" in epg_channel_id:
epg_channel_id = epg_channel_id.replace("&", "&")
if 'added' in item and item['added']:
added = item['added']
epgnowtitle = epgnowtime = epgnowdescription = epgnexttitle = epgnexttime = epgnextdescription = ''
next_url = "%s/live/%s/%s/%s.%s" % (self.host, self.username, self.password, stream_id, self.output)
self.list.append([
index, str(name), str(stream_id), str(stream_icon), str(epg_channel_id), str(added), str(next_url),
epgnowtime, epgnowtitle, epgnowdescription, epgnexttime, epgnexttitle, epgnextdescription
])
index += 1
self.buildLists()
if self["channel_list"].getCurrent():
if glob.nextlist[-1]['index'] != 0:
self["channel_list"].setIndex(glob.nextlist[-1]['index'])
if not self.isStream:
self.hideEPG()
pass
def buildLists(self):
if self.listType == "category":
self.channelList = []
self.channelList = [buildCategoryList(x[0], x[1], x[2], x[3]) for x in self.list]
self["channel_list"].setList(self.channelList)
self.selectionChanged()
elif self.listType == "live_streams":
self.channelList = []
self.channelList = [buildLiveStreamList(x[0], x[1], x[2], x[3], x[4], x[5], x[6]) for x in self.list]
self["channel_list"].setList(self.channelList)
self.selectionChanged()
def downloadLiveStreams(self):
url = self.live_streams
self.streams = ''
self.live_list_archive = []
adapter = HTTPAdapter(max_retries=0)
http = requests.Session()
http.mount("http://", adapter)
http.mount("https://", adapter)
try:
r = http.get(url, headers=hdr, stream=True, timeout=10, verify=False)
r.raise_for_status()
if r.status_code == requests.codes.ok:
self.streams = r.json()
except Exception as e:
print(e)
if self.streams:
for item in self.streams:
if "tv_archive" and "tv_archive_duration" in item:
if int(item["tv_archive"]) == 1 and int(item["tv_archive_duration"]) > 0:
self.live_list_archive.append(item)
else:
self.close()
def back(self):
self.hideEPG()
self["key_rec"].setText("")
if self.selectedlist == self["epg_short_list"]:
instance = self["epg_short_list"].master.master.instance
instance.setSelectionEnable(0)
self.catchup_all = []
self['epg_short_list'].setList(self.catchup_all)
instance = self["channel_list"].master.master.instance
instance.setSelectionEnable(1)
self.selectedlist = self["channel_list"]
else:
del glob.nextlist[-1]
if len(glob.nextlist) == 0:
self.close()
else:
self.stopStream()
levelpath = str(dir_tmp) + 'level' + str(self.level) + '.xml'
try:
os.remove(levelpath)
except:
pass
self.level -= 1
self.createSetup()
def pinEntered(self, result=None):
# print("*** pinEntered ***")
if not result:
self.pin = False
self.session.open(MessageBox, _("Incorrect pin code."), type=MessageBox.TYPE_ERROR, timeout=5)
if self.pin is True:
glob.pintime = time.time()
self.next()
else:
return
def parentalCheck(self):
self.pin = True
if self.level == 1:
if cfg.parental.getValue() is True and int(time.time()) - int(glob.pintime) > 900:
adult = _("all"), "all", "+18", "adult", "18+", "18 rated", "xxx", "sex", "porn", "pink", "blue"
if any(s in str(self["channel_list"].getCurrent()[0]).lower() and str(self["channel_list"].getCurrent()[0]).lower() != "Allgemeines" for s in adult):
from Screens.InputBox import PinInput
self.session.openWithCallback(self.pinEntered, PinInput, pinList=[config.ParentalControl.setuppin.value], triesEntry=config.ParentalControl.retries.servicepin, title=_("Please enter the parental control pin code"), windowTitle=_("Enter pin code"))
else:
self.next()
else:
self.next()
else:
self.next()
def next(self):
if self["channel_list"].getCurrent():
self.currentindex = self["channel_list"].getCurrent()[2]
next_url = self["channel_list"].getCurrent()[3]
glob.nextlist[-1]['index'] = self.currentindex
glob.currentchannellist = self.channelList
glob.currentchannellistindex = self.currentindex
if self.level == 1:
glob.nextlist.append({"playlist_url": next_url, "index": 0})
self["epg_picon"].hide()
self.level += 1
self["channel_list"].setIndex(0)
self.createSetup()
else:
self["epg_picon"].show()
if self.selectedlist == self["channel_list"]:
self.shortEPG()
else:
self.playCatchup()
def shortEPG(self):
if self["channel_list"].getCurrent():
next_url = self["channel_list"].getCurrent()[3]
if next_url != 'None':
if "/live/" in next_url:
stream_id = next_url.rpartition("/")[-1].partition(".")[0]
response = ''
shortEPGJson = []
url = str(self.simpledatatable) + str(stream_id)
adapter = HTTPAdapter(max_retries=0)
http = requests.Session()
http.mount("http://", adapter)
http.mount("https://", adapter)
try:
r = http.get(url, headers=hdr, stream=True, timeout=10, verify=False)
r.raise_for_status()
if r.status_code == requests.codes.ok:
try:
response = r.json()
except:
response = ''
except Exception as e:
print(e)
response = ''
if response != '':
shortEPGJson = response
index = 0
self.epgshortlist = []
duplicatecheck = []
if "epg_listings" in shortEPGJson:
if shortEPGJson["epg_listings"]:
for listing in shortEPGJson["epg_listings"]:
if ('has_archive' in listing and listing['has_archive'] == 1) or ('now_playing' in listing and listing['now_playing'] == 1):
epg_title = ""
epg_description = ""
epg_date_all = ""
epg_time_all = ""
start = ""
end = ""
catchupstart = int(cfg.catchupstart.getValue())
catchupend = int(cfg.catchupend.getValue())
if 'title' in listing:
epg_title = base64.b64decode(listing['title']).decode('utf-8')
if 'description' in listing:
epg_description = base64.b64decode(listing['description']).decode('utf-8')
shift = 0
if "serveroffset" in glob.current_playlist["player_info"]:
shift = int(glob.current_playlist["player_info"]["serveroffset"])
if listing['start'] and listing['end']:
start = listing['start']
end = listing['end']
start_datetime_original = datetime.strptime(start, "%Y-%m-%d %H:%M:%S")
start_datetime_offset = datetime.strptime(start, "%Y-%m-%d %H:%M:%S") + timedelta(hours=shift)
start_datetime_margin = datetime.strptime(start, "%Y-%m-%d %H:%M:%S") + timedelta(hours=shift) - timedelta(minutes=catchupstart)
try:
# end_datetime_original = datetime.strptime(end, "%Y-%m-%d %H:%M:%S")
end_datetime_offset = datetime.strptime(end, "%Y-%m-%d %H:%M:%S") + timedelta(hours=shift)
end_datetime_margin = datetime.strptime(end, "%Y-%m-%d %H:%M:%S") + timedelta(hours=shift) + timedelta(minutes=catchupend)
except:
try:
end = listing['stop']
# end_datetime_original = datetime.strptime(end, "%Y-%m-%d %H:%M:%S")
end_datetime_offset = datetime.strptime(end, "%Y-%m-%d %H:%M:%S") + timedelta(hours=shift)
end_datetime_margin = datetime.strptime(end, "%Y-%m-%d %H:%M:%S") + timedelta(hours=shift) + timedelta(minutes=catchupend)
except:
return
epg_date_all = start_datetime_offset.strftime('%a %d/%m')
epg_time_all = str(start_datetime_offset.strftime('%H:%M')) + " - " + str(end_datetime_offset.strftime('%H:%M'))
epg_duration = int((end_datetime_margin - start_datetime_margin).total_seconds() / 60.0)
url_datestring = str(start_datetime_original.strftime('%Y-%m-%d:%H-%M'))
if [epg_date_all, epg_time_all] not in duplicatecheck:
duplicatecheck.append([epg_date_all, epg_time_all])
self.epgshortlist.append(buildShortEPGListEntry(str(epg_date_all), str(epg_time_all), str(epg_title), str(epg_description), str(url_datestring), str(epg_duration), index))
index += 1
self.epgshortlist.reverse()
self["epg_short_list"].setList(self.epgshortlist)
duplicatecheck = []
if self["epg_short_list"].getCurrent():
glob.catchupdata = [str(self["epg_short_list"].getCurrent()[0]), str(self["epg_short_list"].getCurrent()[3])]
instance = self["epg_short_list"].master.master.instance
instance.setSelectionEnable(1)
self.selectedlist = self["epg_short_list"]
self["key_rec"].setText(_("Download"))
self.displayShortEPG()
else:
self.session.open(MessageBox, _("Catchup currently not available. Missing EPG data"), type=MessageBox.TYPE_INFO, timeout=5)
return
def displayShortEPG(self):
if self["epg_short_list"].getCurrent():
title = str(self["epg_short_list"].getCurrent()[0])
description = str(self["epg_short_list"].getCurrent()[3])
timeall = str(self["epg_short_list"].getCurrent()[2])
self["epg_title"].setText(timeall + " " + title)
self["epg_description"].setText(description)
self.showEPGElements()
def playCatchup(self):
next_url = self["channel_list"].getCurrent()[3]
stream = next_url.rpartition('/')[-1]
date = str(self["epg_short_list"].getCurrent()[4])
duration = str(self["epg_short_list"].getCurrent()[5])
playurl = "%s/timeshift/%s/%s/%s/%s/%s" % (self.host, self.username, self.password, duration, date, stream)
if next_url != 'None' and "/live/" in next_url:
streamtype = "4097"
self.reference = eServiceReference(int(streamtype), 0, str(playurl))
glob.catchupdata = [str(self["epg_short_list"].getCurrent()[0]), str(self["epg_short_list"].getCurrent()[3])]
self.session.openWithCallback(self.createSetup, streamplayer.XStreamity_CatchupPlayer, str(playurl), str(streamtype))
else:
from Screens.MessageBox import MessageBox
self.session.open(MessageBox, _('Catchup error. No data for this slot'), MessageBox.TYPE_WARNING, timeout=5)
def stopStream(self):
if glob.currentPlayingServiceRefString != glob.newPlayingServiceRefString:
if glob.newPlayingServiceRefString != '':
if self.session.nav.getCurrentlyPlayingServiceReference():
self.session.nav.stopService()
self.session.nav.playService(eServiceReference(glob.currentPlayingServiceRefString))
def selectionChanged(self):
if self["channel_list"].getCurrent():
channeltitle = self["channel_list"].getCurrent()[0]
currentindex = self["channel_list"].getIndex()
self.position = currentindex + 1
self.positionall = len(self.channelList)
self.page = int(math.ceil(float(self.position) / float(self.itemsperpage)))
self.pageall = int(math.ceil(float(self.positionall) / float(self.itemsperpage)))
self["page"].setText(_('Page: ') + str(self.page) + _(" of ") + str(self.pageall))
self["listposition"].setText(str(self.position) + "/" + str(self.positionall))
self["channel"].setText(self.main_title + ": " + str(channeltitle))
if self.level >= 2:
self.timerimage = eTimer()
try:
self.timerimage.callback.append(self.downloadImage)
except:
self.timerimage_conn = self.timerimage.timeout.connect(self.downloadImage)
self.timerimage.start(250, True)
else:
self.position = 0
self.positionall = 0
self.page = 0
self.pageall = 0
self["page"].setText(_('Page: ') + str(self.page) + _(" of ") + str(self.pageall))
self["listposition"].setText(str(self.position) + "/" + str(self.positionall))
def downloadImage(self):
if self["channel_list"].getCurrent():
try:
os.remove(str(dir_tmp) + 'original.png')
os.remove(str(dir_tmp) + 'temp.png')
except:
pass
desc_image = ''
try:
desc_image = self["channel_list"].getCurrent()[5]
except:
pass
if desc_image and desc_image != "n/A":
temp = dir_tmp + 'temp.png'
try:
parsed = urlparse(desc_image)
domain = parsed.hostname
scheme = parsed.scheme
if pythonVer == 3:
desc_image = desc_image.encode()
if scheme == "https" and sslverify:
sniFactory = SNIFactory(domain)
downloadPage(desc_image, temp, sniFactory, timeout=5).addCallback(self.resizeImage).addErrback(self.loadDefaultImage)
else:
downloadPage(desc_image, temp, timeout=5).addCallback(self.resizeImage).addErrback(self.loadDefaultImage)
except:
self.loadDefaultImage()
else:
self.loadDefaultImage()
def loadDefaultImage(self, data=None):
# print("*** loadDefaultImage ***")
if data:
print(data)
if self["epg_picon"].instance:
self["epg_picon"].instance.setPixmapFromFile(common_path + "picon.png")
def resizeImage(self, data=None):
# print("*** resizeImage ***")
if self["channel_list"].getCurrent():
original = str(dir_tmp) + 'temp.png'
size = [147, 88]
if screenwidth.width() > 1280:
size = [220, 130]
if os.path.exists(original):
try:
im = Image.open(original).convert('RGBA')
im.thumbnail(size, Image.ANTIALIAS)
# crop and center image
bg = Image.new('RGBA', size, (255, 255, 255, 0))
imagew, imageh = im.size
im_alpha = im.convert('RGBA').split()[-1]
bgwidth, bgheight = bg.size
bg_alpha = bg.convert('RGBA').split()[-1]
temp = Image.new('L', (bgwidth, bgheight), 0)
temp.paste(im_alpha, (int((bgwidth - imagew) / 2), int((bgheight - imageh) / 2)), im_alpha)
bg_alpha = ImageChops.screen(bg_alpha, temp)
bg.paste(im, (int((bgwidth - imagew) / 2), int((bgheight - imageh) / 2)))
im = bg
im.save(original, 'PNG')
if self["epg_picon"].instance:
self["epg_picon"].instance.setPixmapFromFile(original)
except Exception as e:
print("******* picon resize failed *******")
print(e)
else:
self.loadDefaultImage()
def showEPGElements(self):
self["epg_picon"].show()
self["epg_bg"].show()
self["key_yellow"].setText(_('Reverse'))
def hideEPG(self):
self["epg_short_list"].setList([])
self["epg_picon"].hide()
self["epg_bg"].hide()
self["epg_title"].setText('')
self["epg_description"].setText('')
self["key_yellow"].setText('')
# record button download video file
def downloadVideo(self):
# load x-downloadlist.json file
if self["key_rec"].getText() != '':
if self["channel_list"].getCurrent():
next_url = self["channel_list"].getCurrent()[3]
stream = next_url.rpartition('/')[-1]
date = str(self["epg_short_list"].getCurrent()[4])
duration = str(self["epg_short_list"].getCurrent()[5])
playurl = "%s/timeshift/%s/%s/%s/%s/%s" % (self.host, self.username, self.password, duration, date, stream)
date_all = str(self["epg_short_list"].getCurrent()[1]).strip()
time_all = str(self["epg_short_list"].getCurrent()[2]).strip()
time_start = time_all.partition(" - ")[0].strip()
current_year = int(datetime.now().year)
date = str(datetime.strptime(str(current_year) + str(date_all) + str(time_start), "%Y%a %d/%m%H:%M")).replace("-", "").replace(":", "")[:-2]
otitle = str(self["epg_short_list"].getCurrent()[0])
channel = str(self["channel_list"].getCurrent()[0])
title = str(date) + " - " + str(channel) + " - " + str(otitle)
downloads_all = []
if os.path.isfile(downloads_json):
with open(downloads_json, "r") as f:
try:
downloads_all = json.load(f)
except:
pass
exists = False
for video in downloads_all:
url = video[2]
if playurl == url:
exists = True
if exists is False:
downloads_all.append([_("Catch-up"), title, playurl, _("Not Started"), 0, 0])
with open(downloads_json, 'w') as f:
json.dump(downloads_all, f)
self.session.open(MessageBox, _(title) + "\n\n" + _("Added to download manager"), MessageBox.TYPE_INFO, timeout=5)
else:
self.session.open(MessageBox, _(title) + "\n\n" + _("Already added to download manager"), MessageBox.TYPE_ERROR, timeout=5)
def reverse(self):
self.epgshortlist.reverse()
self["epg_short_list"].setList(self.epgshortlist)
def buildCategoryList(index, title, next_url, category_id):
png = LoadPixmap(common_path + "more.png")
return (title, png, index, next_url, category_id)
def buildLiveStreamList(index, title, stream_id, stream_icon, epg_channel_id, added, next_url):
png = LoadPixmap(common_path + "more.png")
return (title, png, index, next_url, stream_id, stream_icon, epg_channel_id, added)
def buildShortEPGListEntry(date_all, time_all, title, description, start, duration, index):
return (title, date_all, time_all, description, start, duration, index)