386 lines
22 KiB
Python
386 lines
22 KiB
Python
# Copyright (C) 2024 Lunatixz
|
|
#
|
|
#
|
|
# This file is part of PseudoTV Live.
|
|
#
|
|
# PseudoTV Live is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# PseudoTV Live is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with PseudoTV Live. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
# -*- coding: utf-8 -*-
|
|
from globals import *
|
|
from jsonrpc import JSONRPC
|
|
from rules import RulesList
|
|
|
|
|
|
class Plugin:
|
|
@contextmanager
|
|
def preparingPlayback(self):
|
|
if self.playCheck(loadJSON(decodeString(PROPERTIES.getEXTProperty('%s.lastPlayed.sysInfo'%(ADDON_ID))))):
|
|
try: yield
|
|
finally: PROPERTIES.setEXTProperty('%s.lastPlayed.sysInfo'%(ADDON_ID),encodeString(dumpJSON(self.sysInfo)))
|
|
else: #todo evaluate potential for error handling.
|
|
if REAL_SETTINGS.getSetting('Debug_Enable').lower() == 'true':
|
|
yield self.playError()
|
|
|
|
|
|
def __init__(self, sysARG=sys.argv, sysInfo={}):
|
|
with BUILTIN.busy_dialog():
|
|
self.sysARG = sysARG
|
|
self.sysInfo = sysInfo
|
|
self.jsonRPC = JSONRPC()
|
|
self.cache = SETTINGS.cache
|
|
|
|
self.debugEnabled = SETTINGS.getSettingBool('Debug_Enable')
|
|
|
|
self.sysInfo['radio'] = sysInfo.get('mode','').lower() == "radio"
|
|
self.sysInfo['now'] = int(sysInfo.get('now') or int(getUTCstamp()))
|
|
self.sysInfo['start'] = int(sysInfo.get('start') or '-1')
|
|
self.sysInfo['stop'] = int(sysInfo.get('stop') or '-1')
|
|
self.sysInfo['citem'] = (sysInfo.get('citem') or combineDicts({'id':sysInfo.get("chid")},sysInfo.get('fitem',{}).get('citem',{})))
|
|
|
|
if sysInfo.get('fitem'):
|
|
if sysInfo.get("nitem"): self.sysInfo.update({'citem':combineDicts(self.sysInfo["nitem"].pop('citem'),self.sysInfo["fitem"].pop('citem'))})
|
|
else: self.sysInfo.update({'citem':combineDicts(self.sysInfo["citem"],self.sysInfo["fitem"].pop('citem'))})
|
|
|
|
if self.sysInfo.get('start') == -1:
|
|
self.sysInfo['start'] = self.sysInfo['fitem'].get('start')
|
|
self.sysInfo['stop'] = self.sysInfo['fitem'].get('stop')
|
|
|
|
self.sysInfo['duration'] = float(sysInfo.get('duration') or self.jsonRPC._getRuntime(self.sysInfo['fitem']) or timeString2Seconds(BUILTIN.getInfoLabel('Duration(hh:mm:ss)')))
|
|
else:
|
|
self.sysInfo['duration'] = float((sysInfo.get('duration') or '-1'))
|
|
|
|
try:
|
|
self.sysInfo['seek'] = int(sysInfo.get('seek') or (abs(self.sysInfo['start'] - self.sysInfo['now']) if self.sysInfo['start'] > 0 else -1))
|
|
self.sysInfo["progresspercentage"] = -1 if self.sysInfo['seek'] == -1 else (self.sysInfo["seek"]/self.sysInfo["duration"]) * 100
|
|
except:
|
|
self.sysInfo['seek'] = int(sysInfo.get('seek','-1'))
|
|
self.sysInfo["progresspercentage"] = -1
|
|
|
|
self.log('__init__, sysARG = %s\nsysInfo = %s'%(sysARG,self.sysInfo))
|
|
|
|
|
|
def log(self, msg, level=xbmc.LOGDEBUG):
|
|
return log('%s: %s'%(self.__class__.__name__,msg),level)
|
|
|
|
|
|
def _resolveURL(self, found, listitem):
|
|
xbmcplugin.setResolvedUrl(int(self.sysARG[1]), found, listitem)
|
|
|
|
|
|
def _setResume(self, chid, liz):
|
|
if self.sysInfo.get('seek',0) > SETTINGS.getSettingInt('Seek_Tolerance') and self.sysInfo.get('progresspercentage',100) < 100:
|
|
self.log('[%s] _setResume, seek = %s, progresspercentage = %s\npath = %s'%(chid, self.sysInfo.get('seek',0), self.sysInfo.get('progresspercentage',100), liz.getPath()))
|
|
liz.setProperty('startoffset', str(self.sysInfo['seek'])) #secs
|
|
infoTag = ListItemInfoTag(liz,'video')
|
|
infoTag.set_resume_point({'ResumeTime':self.sysInfo['seek'],'TotalTime':(self.sysInfo['duration'] * 60)})
|
|
else:
|
|
self.sysInfo["seek"] = -1
|
|
self.sysInfo["progresspercentage"] = -1
|
|
return liz
|
|
|
|
|
|
def _quePlaylist(self, chid, listitems, pltype=xbmc.PLAYLIST_VIDEO, shuffle=BUILTIN.isPlaylistRandom()):
|
|
self.log('[%s] _quePlaylist, listitems = %s, shuffle = %s'%(chid, len(listitems),shuffle))
|
|
channelPlaylist = xbmc.PlayList(pltype)
|
|
channelPlaylist.clear()
|
|
xbmc.sleep(100) #give channelPlaylist.clear() enough time to clear queue.
|
|
[channelPlaylist.add(liz.getPath(),liz,idx) for idx,liz in enumerate(listitems) if liz.getPath()]
|
|
self.log('[%s] _quePlaylist, Playlist size = %s, shuffle = %s'%(chid, channelPlaylist.size(),shuffle))
|
|
if shuffle: channelPlaylist.shuffle()
|
|
else: channelPlaylist.unshuffle()
|
|
return channelPlaylist
|
|
|
|
|
|
def getRadioItems(self, name, chid, vid, limit=RADIO_ITEM_LIMIT):
|
|
self.log('[%s] getRadioItems'%(chid))
|
|
return interleave([self.jsonRPC.requestList({'id':chid}, path, 'music', page=limit, sort={"method":"random"})[0] for path in vid.split('|')], SETTINGS.getSettingInt('Interleave_Value'))
|
|
|
|
|
|
def getPausedItems(self, name, chid):
|
|
self.log('[%s] getPausedItems'%(chid))
|
|
def __buildfItem(idx, item):
|
|
if 'citem' in item: item.pop('citem')
|
|
sysInfo = self.sysInfo.copy()
|
|
sysInfo['isPlaylist'] = True
|
|
liz = LISTITEMS.buildItemListItem(item,'video')
|
|
|
|
if item.get('file') == item.get('resume',{}).get('file',str(random.random())):
|
|
seektime = int(item.get('resume',{}).get('position',0.0))
|
|
runtime = int(item.get('resume',{}).get('total',0.0))
|
|
self.log('[%s] getPausedItems, within seek tolerance setting seek totaltime = %s, resumetime = %s'%(chid, runtime, seektime))
|
|
liz.setProperty('startoffset', str(seektime)) #secs
|
|
infoTag = ListItemInfoTag(liz, 'video')
|
|
infoTag.set_resume_point({'ResumeTime':seektime, 'TotalTime':runtime * 60})
|
|
|
|
sysInfo.update({'fitem':item,'resume':{"idx":idx}})
|
|
liz.setProperty('sysInfo',encodeString(dumpJSON(sysInfo)))
|
|
return liz
|
|
|
|
nextitems = RulesList([self.sysInfo.get('citem',{'name':name,'id':chid})]).runActions(RULES_ACTION_PLAYBACK_RESUME, self.sysInfo.get('citem',{'name':name,'id':chid}))
|
|
if nextitems:
|
|
nextitems = nextitems[:SETTINGS.getSettingInt('Page_Limit')]# list of upcoming items, truncate for speed
|
|
self.log('[%s] getPausedItems, building nextitems (%s)'%(chid, len(nextitems)))
|
|
return [__buildfItem(idx, nextitem) for idx, nextitem in enumerate(nextitems)]
|
|
else: DIALOG.notificationDialog(LANGUAGE(32000))
|
|
return []
|
|
|
|
|
|
def getPVRItems(self, name: str, chid: str) -> list:
|
|
self.log('[%s] getPVRItems, chname = %s'%(chid,name))
|
|
def __buildfItem(idx, item):
|
|
sysInfo = self.sysInfo.copy()
|
|
nowitem = decodePlot(item.get('plot',''))
|
|
if 'citem' in nowitem: nowitem.pop('citem')
|
|
nowitem['pvritem'] = item
|
|
sysInfo.update({'fitem':nowitem,'position':idx})
|
|
|
|
try: #next broadcast
|
|
nextitem = decodePlot(nextitems[idx+1][1].get('plot',''))
|
|
if 'citem' in nextitem: nextitem.pop('citem')
|
|
nextitem.get('customproperties',{})['pvritem'] = nextitems[idx + 1]
|
|
sysInfo.update({'nitem':nextitem})
|
|
except: pass
|
|
|
|
liz = LISTITEMS.buildItemListItem(nowitem,'video')
|
|
if (item.get('progress',0) > 0 and item.get('runtime',0) > 0):
|
|
self.log('[%s] getPVRItems, within seek tolerance setting seek totaltime = %s, resumetime = %s'%(chid,(item['runtime'] * 60),item['progress']))
|
|
liz.setProperty('startoffset', str(item['progress'])) #secs
|
|
infoTag = ListItemInfoTag(liz, 'video')
|
|
infoTag.set_resume_point({'ResumeTime':item['progress'],'TotalTime':(item['runtime'] * 60)})
|
|
liz.setProperty('sysInfo',encodeString(dumpJSON(sysInfo)))
|
|
return liz
|
|
|
|
found = False
|
|
pvritem = self.jsonRPC.matchChannel(name,chid,radio=False)
|
|
if pvritem:
|
|
pastItems = pvritem.get('broadcastpast',[])
|
|
nowitem = pvritem.get('broadcastnow',{})
|
|
nextitems = pvritem.get('broadcastnext',[]) # upcoming items
|
|
nextitems.insert(0,nowitem)
|
|
nextitems = pastItems + nextitems
|
|
|
|
if (self.sysInfo.get('fitem') or self.sysInfo.get('vid')):
|
|
for pos, nextitem in enumerate(nextitems):
|
|
fitem = decodePlot(nextitem.get('plot',{}))
|
|
file = self.sysInfo.get('fitem',{}).get('file') if self.sysInfo.get('fitem') else self.sysInfo.get('vid')
|
|
if file == fitem.get('file') and self.sysInfo.get('citem',{}).get('id') == fitem.get('citem',{}).get('id',str(random.random())):
|
|
found = True
|
|
self.log('[%s] getPVRItems found matching fitem'%(chid))
|
|
del nextitems[0:pos] # start array at correct position
|
|
break
|
|
|
|
elif self.sysInfo.get('now') and self.sysInfo.get('vid'):
|
|
for pos, nextitem in enumerate(nextitems):
|
|
fitem = decodePlot(nextitem.get('plot',{}))
|
|
ntime = datetime.datetime.fromtimestamp(float(self.sysInfo.get('now')))
|
|
if ntime >= strpTime(nextitem.get('starttime')) and ntime < strpTime(nextitem.get('endtime')) and chid == fitem.get('citem',{}).get('id',str(random.random())):
|
|
found = True
|
|
self.log('[%s] getPVRItems found matching starttime'%(chid))
|
|
del nextitems[0:pos] # start array at correct position
|
|
break
|
|
|
|
elif nowitem: found = True
|
|
|
|
if found:
|
|
nowitem = nextitems.pop(0)
|
|
if round(nowitem['progresspercentage']) > SETTINGS.getSettingInt('Seek_Threshold'):
|
|
self.log('[%s] getPVRItems, progress past threshold advance to nextitem'%(chid))
|
|
nowitem = nextitems.pop(0)
|
|
|
|
if round(nowitem['progress']) < SETTINGS.getSettingInt('Seek_Tolerance'):
|
|
self.log('[%s] getPVRItems, progress start at the beginning'%(chid))
|
|
nowitem['progress'] = 0
|
|
nowitem['progresspercentage'] = 0
|
|
|
|
self.sysInfo.update({'citem':decodePlot(nowitem.get('plot','')).get('citem',self.sysInfo.get('citem'))})
|
|
self.sysInfo['callback'] = self.jsonRPC.getCallback(self.sysInfo)
|
|
nextitems = nextitems[:SETTINGS.getSettingInt('Page_Limit')]# list of upcoming items, truncate for speed
|
|
nextitems.insert(0,nowitem)
|
|
self.log('[%s] getPVRItems, building nextitems (%s)'%(chid,len(nextitems)))
|
|
return [__buildfItem(idx, item) for idx, item in enumerate(nextitems)]
|
|
else: DIALOG.notificationDialog(LANGUAGE(32164))
|
|
else: DIALOG.notificationDialog(LANGUAGE(32000))
|
|
return [xbmcgui.ListItem()]
|
|
|
|
|
|
def playTV(self, name: str, chid: str):
|
|
self.log('[%s] playTV'%(chid))
|
|
with self.preparingPlayback(), PROPERTIES.suspendActivity():
|
|
if self.sysInfo.get('fitem') and (self.sysInfo.get('fitem').get('file','-1') == self.sysInfo.get('vid','0')): #-> live
|
|
liz = self._setResume(chid, LISTITEMS.buildItemListItem(self.sysInfo['fitem']))
|
|
else:
|
|
liz = self.getPVRItems(name, chid)[0]
|
|
liz.setProperty('sysInfo',encodeString(dumpJSON(self.sysInfo)))
|
|
self._resolveURL(True, liz)
|
|
|
|
|
|
def playLive(self, name: str, chid: str, vid: str):
|
|
self.log('[%s] playLive, name = %s'%(chid, name))
|
|
with self.preparingPlayback(), PROPERTIES.suspendActivity():
|
|
if self.sysInfo.get('fitem').get('file','-1') == self.sysInfo.get('vid','0'):#-> live playback from UI incl. listitem
|
|
liz = self._setResume(chid, LISTITEMS.buildItemListItem(self.sysInfo['fitem']))
|
|
liz.setProperty('sysInfo',encodeString(dumpJSON(self.sysInfo)))
|
|
self._resolveURL(True, liz)
|
|
elif self.sysInfo.get('fitem') and self.sysInfo.get('start') <= self.sysInfo.get('now') <= self.sysInfo.get('stop'):#-> VOD called by non-current EPG cell. (Unreliable during playback)
|
|
self.sysInfo['mode'] = 'vod'
|
|
self.sysInfo['name'] = self.sysInfo['fitem'].get('label')
|
|
self.sysInfo['vid'] = self.sysInfo['fitem'].get('file')
|
|
self.sysInfo["seek"] = -1
|
|
self.sysInfo["progresspercentage"] = -1
|
|
self.log('[%s] playLive, VOD = %s'%(chid, self.sysInfo['vid']))
|
|
DIALOG.notificationDialog(LANGUAGE(32185)%(self.sysInfo['name']))
|
|
liz = LISTITEMS.buildItemListItem(self.sysInfo.get('fitem'))
|
|
liz.setProperty("IsPlayable","true")
|
|
liz.setProperty('sysInfo',encodeString(dumpJSON(self.sysInfo)))
|
|
timerit(PLAYER().play)(1.0,[self.sysInfo['vid'],liz,True])
|
|
self._resolveURL(False, liz)
|
|
elif vid:#-> onChange callback from "live" or widget or channel switch (change via input not ui)
|
|
self.log('[%s] playLive, VID = %s'%(chid, vid))
|
|
liz = self._setResume(chid, xbmcgui.ListItem(name,path=vid))
|
|
liz.setProperty("IsPlayable","true")
|
|
liz.setProperty('sysInfo',encodeString(dumpJSON(self.sysInfo)))
|
|
self._resolveURL(True, liz)
|
|
else:
|
|
self.playTV(name, chid)
|
|
|
|
|
|
def playBroadcast(self, name: str, chid: str, vid: str): #-> catchup-source
|
|
self.log('[%s] playBroadcast'%(chid))
|
|
with self.preparingPlayback(), PROPERTIES.suspendActivity():
|
|
if self.sysInfo.get('fitem'): #-> catchup-id called via ui "play programme"
|
|
liz = LISTITEMS.buildItemListItem(self.sysInfo.get('fitem'))
|
|
else:
|
|
liz = xbmcgui.ListItem(name,path=vid)
|
|
liz.setProperty("IsPlayable","true")
|
|
self.sysInfo["seek"] = -1
|
|
self.sysInfo["progresspercentage"] = -1
|
|
liz.setProperty('sysInfo',encodeString(dumpJSON(self.sysInfo)))
|
|
self._resolveURL(True, liz)
|
|
|
|
|
|
def playVOD(self, title: str, vid: str): #-> catchup-id
|
|
self.log('[%s] playVOD, title = %s'%(vid,title))
|
|
with self.preparingPlayback(), PROPERTIES.suspendActivity():
|
|
liz = LISTITEMS.buildItemListItem(self.sysInfo.get('fitem'))
|
|
liz.setProperty("IsPlayable","true")
|
|
liz.setProperty('sysInfo',encodeString(dumpJSON(self.sysInfo)))
|
|
self._resolveURL(True, liz)
|
|
|
|
|
|
def playDVR(self, title: str, vid: str): #-> catchup-id
|
|
self.log('[%s] playDVR, title = %s'%(vid, title))
|
|
with self.preparingPlayback(), PROPERTIES.suspendActivity():
|
|
liz = self._setResume(vid, LISTITEMS.buildItemListItem(self.sysInfo.get('fitem')))
|
|
liz.setProperty('sysInfo',encodeString(dumpJSON(self.sysInfo)))
|
|
self._resolveURL(True, liz)
|
|
|
|
|
|
def playRadio(self, name: str, chid: str, vid: str):
|
|
self.log('[%s] playRadio'%(chid))
|
|
def __buildfItem(idx, item: dict={}):
|
|
return LISTITEMS.buildItemListItem(item, 'music')
|
|
with self.preparingPlayback(), PROPERTIES.suspendActivity():
|
|
items = randomShuffle(self.getRadioItems(name, chid, vid))
|
|
listitems = [__buildfItem(idx, item) for idx, item in enumerate(items)]
|
|
if len(listitems) > 0:
|
|
playlist = self._quePlaylist(chid, listitems, pltype=xbmc.PLAYLIST_MUSIC, shuffle=True)
|
|
timerit(BUILTIN.executeWindow)(OSD_TIMER,['ReplaceWindow(visualisation)'])
|
|
BUILTIN.executebuiltin("Dialog.Close(all)")
|
|
PLAYER().play(playlist,windowed=True)
|
|
self._resolveURL(False, xbmcgui.ListItem())
|
|
|
|
|
|
def playPlaylist(self, name: str, chid: str):
|
|
self.log('[%s] playPlaylist'%(chid))
|
|
with self.preparingPlayback(), PROPERTIES.suspendActivity():
|
|
listitems = self.getPVRItems(name, chid)
|
|
if len(listitems) > 0:
|
|
playlist = self._quePlaylist(chid, listitems,shuffle=False)
|
|
if BUILTIN.getInfoBool('Playing','Player'): BUILTIN.executebuiltin('PlayerControl(Stop)')
|
|
timerit(BUILTIN.executeWindow)(OSD_TIMER,['ReplaceWindow(fullscreenvideo)'])
|
|
BUILTIN.executebuiltin("Dialog.Close(all)")
|
|
PLAYER().play(playlist,windowed=True)
|
|
self._resolveURL(False, xbmcgui.ListItem())
|
|
|
|
|
|
def playPaused(self, name: str, chid: str):
|
|
self.log('[%s] playPaused'%(chid))
|
|
with self.preparingPlayback(), PROPERTIES.suspendActivity():
|
|
listitems = self.getPausedItems(name, chid)
|
|
if len(listitems) > 0:
|
|
playlist = self._quePlaylist(chid, listitems,shuffle=False)
|
|
if BUILTIN.getInfoBool('Playing','Player'): BUILTIN.executebuiltin('PlayerControl(Stop)')
|
|
timerit(BUILTIN.executeWindow)(OSD_TIMER,['ReplaceWindow(fullscreenvideo)'])
|
|
BUILTIN.executebuiltin("Dialog.Close(all)")
|
|
PLAYER().play(playlist,windowed=True)
|
|
self._resolveURL(False, xbmcgui.ListItem())
|
|
|
|
|
|
def playCheck(self, oldInfo: dict={}) -> bool:
|
|
def _chkPath():
|
|
status = True
|
|
if oldInfo.get('isPlaylist') or not self.sysInfo.get('vid',''): status = True
|
|
elif self.sysInfo.get('vid','').startswith(tuple(VFS_TYPES)): status = hasAddon(self.sysInfo['vid'])
|
|
elif not self.sysInfo.get('vid','').startswith(tuple(WEB_TYPES)): status = FileAccess.exists(self.sysInfo['vid'])
|
|
self.log('[%s] playCheck _chkPath, valid = %s\npath %s'%(self.sysInfo.get('citem',{}).get('id'),status,self.sysInfo.get('vid')))
|
|
if not status: DIALOG.notificationDialog(LANGUAGE(32167),show=self.debugEnabled)
|
|
return status
|
|
|
|
def _chkLoop():
|
|
if self.sysInfo.get('chid') == oldInfo.get('chid',random.random()):
|
|
if self.sysInfo.get('start') == oldInfo.get('start',random.random()):
|
|
self.sysInfo['playcount'] = oldInfo.get('playcount',0) + 1 #carry over playcount
|
|
self.sysInfo['runtime'] = oldInfo.get('runtime',0) #carry over previous player runtime
|
|
|
|
if self.sysInfo['mode'] == 'live':
|
|
if self.sysInfo['now'] >= self.sysInfo['stop']:
|
|
self.log('[%s] playCheck _chkLoop, failed! Current time (%s) is past the contents stop time (%s).'%(self.sysInfo.get('citem',{}).get('id'),self.sysInfo['now'],self.sysInfo['stop']))
|
|
DIALOG.notificationDialog("Current time (%s) is past the contents stop time (%s)."%(self.sysInfo['now'],self.sysInfo['stop']),show=self.debugEnabled)
|
|
return False
|
|
elif self.sysInfo['runtime'] > 0 and self.sysInfo['duration'] > self.sysInfo['runtime']:
|
|
self.log('[%s] playCheck _chkLoop, failed! Duration error between player (%s) and pvr (%s).'%(self.sysInfo.get('citem',{}).get('id'),self.sysInfo['duration'],self.sysInfo['runtime']))
|
|
DIALOG.notificationDialog("Duration error between player (%s) and pvr (%s)."%(self.sysInfo['runtime'],self.sysInfo['duration']),show=self.debugEnabled)
|
|
return False
|
|
elif self.sysInfo['seek'] >= oldInfo.get('runtime',self.sysInfo['duration']):
|
|
self.log('[%s] playCheck _chkLoop, failed! Seeking to a position (%s) past media runtime (%s).'%(self.sysInfo.get('citem',{}).get('id'),self.sysInfo['seek'],oldInfo.get('runtime',self.sysInfo['duration'])))
|
|
DIALOG.notificationDialog("Seeking to a position (%s) past media runtime (%s)."%(self.sysInfo['seek'],oldInfo.get('runtime',self.sysInfo['duration'])),show=self.debugEnabled)
|
|
return False
|
|
elif self.sysInfo['seek'] == oldInfo.get('seek',self.sysInfo['seek']):
|
|
self.log('[%s] playCheck _chkLoop, failed! Seeking to same position.'%(self.sysInfo.get('citem',{}).get('id')))
|
|
DIALOG.notificationDialog("Playback Failed: Seeking to same position",show=self.debugEnabled)
|
|
return False
|
|
return True
|
|
|
|
status = _chkPath()
|
|
if status: status = _chkLoop()
|
|
self.log('[%s] playCheck, status = %s\nsysInfo=%s\noldInfo = %s'%(self.sysInfo.get('citem',{}).get('id'),status, self.sysInfo,oldInfo))
|
|
return True
|
|
|
|
|
|
def playError(self):
|
|
PROPERTIES.setEXTProperty('%s.lastPlayed.sysInfo'%(ADDON_ID),encodeString(dumpJSON(self.sysInfo)))
|
|
self.log('[%s] playError, attempt = %s\n%s'%(self.sysInfo.get('chid','-1'),self.sysInfo.get('playcount'),self.sysInfo))
|
|
self._resolveURL(False, xbmcgui.ListItem()) #release pending playback
|
|
if self.sysInfo.get('playcount',0) == 0:
|
|
DIALOG.notificationWait(LANGUAGE(32038)%(self.sysInfo.get('playcount',0)))
|
|
timerit(BUILTIN.executebuiltin)(0.1,['AlarmClock(last,Number(0),.5,true,false)']) #last channel
|
|
elif self.sysInfo.get('playcount',3) < 3:
|
|
DIALOG.notificationWait(LANGUAGE(32038)%(self.sysInfo.get('playcount',3)))
|
|
timerit(BUILTIN.executebuiltin)(0.1,['PlayMedia(%s%s)'%(self.sysARG[0],self.sysARG[2])]) #retry channel
|
|
else:
|
|
DIALOG.notificationDialog(LANGUAGE(32000))
|
|
PROPERTIES.setPropTimer('chkPVRRefresh')
|
|
timerit(DIALOG.okDialog)(0.1,[LANGUAGE(32134)%(ADDON_NAME)])
|
|
|