diff --git a/addons.xml b/addons.xml index 5c683e36..6f0d6f21 100644 --- a/addons.xml +++ b/addons.xml @@ -1,6 +1,6 @@ - + diff --git a/addons.xml.md5 b/addons.xml.md5 index 56879593..f6e6325f 100644 --- a/addons.xml.md5 +++ b/addons.xml.md5 @@ -1 +1 @@ -56ec0c3f60fe16dd084b0788864f4517 \ No newline at end of file +87ba2ca47a599184788fd2399d910d57 \ No newline at end of file diff --git a/plugin.video.pseudotv.live/addon.xml b/plugin.video.pseudotv.live/addon.xml index 06b91bf6..5bca2af8 100644 --- a/plugin.video.pseudotv.live/addon.xml +++ b/plugin.video.pseudotv.live/addon.xml @@ -1,5 +1,5 @@ - + diff --git a/plugin.video.pseudotv.live/resources/lib/autotune.py b/plugin.video.pseudotv.live/resources/lib/autotune.py index 1462c8e3..5a3e9dc2 100644 --- a/plugin.video.pseudotv.live/resources/lib/autotune.py +++ b/plugin.video.pseudotv.live/resources/lib/autotune.py @@ -71,8 +71,9 @@ def _runTune(self, samples: bool=False, rebuild: bool=False, dia=None): if samples: opt = '' msg = (LANGUAGE(32042)%ADDON_NAME) - hasBackup = PROPERTIES.hasBackup() - hasServers = PROPERTIES.hasServers() + hasBackup = PROPERTIES.hasBackup() + hasServers = PROPERTIES.hasServers() + hasChannels = PROPERTIES.hasChannels() if hasBackup: opt = LANGUAGE(32112) msg = '%s\n%s'%((LANGUAGE(32042)%ADDON_NAME),LANGUAGE(32111)) @@ -83,9 +84,9 @@ def _runTune(self, samples: bool=False, rebuild: bool=False, dia=None): retval = DIALOG.yesnoDialog(message=msg,customlabel=opt) if retval == 1: dia = DIALOG.progressBGDialog(header='%s, %s'%(ADDON_NAME,'%s %s'%(LANGUAGE(32021),LANGUAGE(30038)))) elif retval == 2: - if hasBackup: return Backup().recoverChannels() - elif hasServers: return BUILTIN.executebuiltin('RunScript(special://home/addons/%s/resources/lib/multiroom.py, Select_Server)'%(ADDON_ID)) - elif not PROPERTIES.hasFirstrun(): return openAddonSettings() + if hasBackup: return Backup().recoverChannels() + elif hasServers: return BUILTIN.executebuiltin('RunScript(special://home/addons/%s/resources/lib/multiroom.py, Select_Server)'%(ADDON_ID)) + elif not hasChannels: return openAddonSettings() else: if SETTINGS.getSettingBool('Debug_Enable'): DIALOG.notificationDialog(LANGUAGE(32058)) return @@ -177,8 +178,8 @@ def buildAvailableRange(existing): citem['logo'] = eitem.get('logo',citem.get('logo',LOGO)) citem['favorite'] = eitem.get('favorite',False) self.channels.addChannel(citem) - if self.channels.setChannels(): - PROPERTIES.forceUpdateTime('chkChannels') + PROPERTIES.setUpdateChannels(citem['id']) + return self.channels.setChannels() def clearLibrary(self): diff --git a/plugin.video.pseudotv.live/resources/lib/builder.py b/plugin.video.pseudotv.live/resources/lib/builder.py index 997445a0..7c354b14 100644 --- a/plugin.video.pseudotv.live/resources/lib/builder.py +++ b/plugin.video.pseudotv.live/resources/lib/builder.py @@ -56,7 +56,7 @@ def __init__(self, service=None): self.filters = {} #{"and": [{"operator": "contains", "field": "title", "value": "Star Wars"},{"operator": "contains", "field": "tag", "value": "Good"}],"or":[]} self.sort = {"ignorearticle":True,"method":"%s"%(SETTINGS.getSetting('Sort_Method').lower()),"order":"ascending","useartistsortname":True} self.limits = {"end":-1,"start":0,"total":0} - self.completeBuild = False + self.completedBuild = False self.bctTypes = {"ratings" :{"min":-1, "max":SETTINGS.getSettingInt('Enable_Preroll'), "auto":SETTINGS.getSettingInt('Enable_Preroll') == -1, "enabled":bool(SETTINGS.getSettingInt('Enable_Preroll')), "chance":SETTINGS.getSettingInt('Random_Pre_Chance'), "sources" :{"ids":SETTINGS.getSetting('Resource_Ratings').split('|'),"paths":[os.path.join(FILLER_LOC,'Ratings' ,'')]},"items":{}}, @@ -119,14 +119,14 @@ def __hasProgrammes(cacheResponse): start = roundTimeDown(getUTCstamp(),offset=60)#offset time to start bottom of the hour stopTimes = dict(self.xmltv.loadStopTimes(fallback=datetime.datetime.fromtimestamp(start).strftime(DTFORMAT))) self.pDialog = DIALOG.progressBGDialog() - self.completeBuild = True + self.completedBuild = True updated = set() for idx, citem in enumerate(self.sortChannels(self.verify(channels))): citem = self.runActions(RULES_ACTION_CHANNEL_TEMP_CITEM, citem, citem, inherited=self) self.log('build, id = %s, rules = %s'%(citem['id'],citem.get('rules',{}))) if self.service._interrupt(): - self.completeBuild = False + self.completedBuild = False self.pErrors = [LANGUAGE(32160)] self.pDialog = DIALOG.progressBGDialog(self.pCount, self.pDialog, message='%s: %s'%(LANGUAGE(32144),LANGUAGE(32213)), header=ADDON_NAME) break @@ -149,16 +149,16 @@ def __hasProgrammes(cacheResponse): if self.addChannelStation(citem) and __hasProgrammes(cacheResponse): updated.add(self.addChannelProgrammes(citem, cacheResponse)) #added xmltv lineup entries. else: - if self.completeBuild: self.pErrors.append(LANGUAGE(32026)) + if self.completedBuild: self.pErrors.append(LANGUAGE(32026)) chanErrors = ' | '.join(list(sorted(set(self.pErrors)))) self.log('build, [%s] In-Valid Channel (%s) %s'%(citem['id'],self.pName,chanErrors)) self.pDialog = DIALOG.progressBGDialog(self.pCount, self.pDialog, message='%s: %s'%(self.pName,chanErrors),header='%s, %s'%(ADDON_NAME,'%s %s'%(LANGUAGE(32027),LANGUAGE(32023)))) if not __hasGuideData(citem): self.delChannelStation(citem) #only remove m3u references when no valid programmes found. self.runActions(RULES_ACTION_CHANNEL_STOP, citem, inherited=self) - self.pDialog = DIALOG.progressBGDialog(100, self.pDialog, message='%s %s'%(self.pMSG,LANGUAGE(32025) if self.completeBuild else LANGUAGE(32135))) - self.log('build, completeBuild = %s, updated = %s, saved = %s'%(self.completeBuild,bool(updated),self.saveChannelLineups())) - return self.completeBuild, bool(updated) + self.pDialog = DIALOG.progressBGDialog(100, self.pDialog, message='%s %s'%(self.pMSG,LANGUAGE(32025) if self.completedBuild else LANGUAGE(32135))) + self.log('build, completed = %s, updated = %s, saved = %s'%(self.completedBuild,bool(updated),self.saveChannelLineups())) + return self.completedBuild, bool(updated) def sortChannels(self, channels: list) -> list: diff --git a/plugin.video.pseudotv.live/resources/lib/default.py b/plugin.video.pseudotv.live/resources/lib/default.py index 9fd20d78..d8a8805e 100644 --- a/plugin.video.pseudotv.live/resources/lib/default.py +++ b/plugin.video.pseudotv.live/resources/lib/default.py @@ -42,7 +42,6 @@ def run(sysARG, fitem: dict={}, nitem: dict={}): elif mode == 'resume': threadit(Plugin(sysARG, sysInfo=params).playResume)(params["name"],params["chid"]) elif mode == 'broadcast': threadit(Plugin(sysARG, sysInfo=params).playBroadcast)(params["name"],params["chid"],params["vid"]) elif mode == 'radio': threadit(Plugin(sysARG, sysInfo=params).playRadio)(params["name"],params["chid"],params["vid"]) - elif mode == 'guide' and hasAddon(PVR_CLIENT_ID,install=True,enable=True) and not PROPERTIES.hasChannels() and PROPERTIES.hasFirstrun(): openAddonSettings() elif mode == 'guide' and hasAddon(PVR_CLIENT_ID,install=True,enable=True): SETTINGS.openGuide() elif mode == 'settings' and hasAddon(PVR_CLIENT_ID,install=True,enable=True): openAddonSettings() else: DIALOG.notificationDialog(LANGUAGE(32000)) diff --git a/plugin.video.pseudotv.live/resources/lib/fillers.py b/plugin.video.pseudotv.live/resources/lib/fillers.py index 39d1c135..82b71336 100644 --- a/plugin.video.pseudotv.live/resources/lib/fillers.py +++ b/plugin.video.pseudotv.live/resources/lib/fillers.py @@ -111,8 +111,8 @@ def getSingle(self, type, keys=['resources'], chance=False): items = [] for key in keys: tmpLST = self.builder.bctTypes.get(type,{}).get('items',{}).get(key.lower(),[]) - if len(tmpLST) > 0: items.append(random.choice(tmpLST)) - elif chance: items.extend(self.getSingle(type)) + if len(tmpLST) > 0: items.append(random.choice(tmpLST)) + elif len(items) == 0 and chance: items.extend(self.getSingle(type)) self.log('getSingle, type = %s, keys = %s, chance = %s, returning = %s'%(type,keys,chance,len(items))) return setDictLST(items) @@ -153,7 +153,7 @@ def injectBCTs(self, citem, fileList): if self.builder.bctTypes[ftype].get('enabled',False) and dbtype.startswith(tuple(preIncludeTypes)) and chtype not in IGNORE_CHTYPE: preFileList.extend(self.getSingle(ftype, preKeys, chanceBool(self.builder.bctTypes[ftype].get('chance',0)))) - for item in setDictLSTLST(preFileList): + for item in setDictLST(preFileList): if (item.get('duration') or 0) == 0: continue else: runtime += item.get('duration') diff --git a/plugin.video.pseudotv.live/resources/lib/globals.py b/plugin.video.pseudotv.live/resources/lib/globals.py index c038798d..fb80fc5e 100644 --- a/plugin.video.pseudotv.live/resources/lib/globals.py +++ b/plugin.video.pseudotv.live/resources/lib/globals.py @@ -65,16 +65,14 @@ def slugify(s, lowercase=False): return s def validString(s): - return "".join(x for x in s if (x.isalnum() or x not in '\/:*?"<>|')) + return "".join(x for x in s if (x.isalnum() or x not in '\\/:*?"<>|')) def stripNumber(s): return re.sub(r'\d+','',s) def stripRegion(s): - try: - match = re.compile('(.*) \((.*)\)', re.IGNORECASE).search(s) - if match.group(1): return match.group(1) - except: return s + match = re.compile(r'(.*) \((.*)\)', re.IGNORECASE).search(s) + if match: return match.group(1) def chanceBool(percent=25): return random.randrange(100) <= percent @@ -139,10 +137,10 @@ def __setCache(key,data,json_data,cache,checksum,life): if results and cache: return __setCache(cacheKey,results,json_data,cache,checksum,life) else: return results except requests.exceptions.ConnectionError as e: - log("Globals: requestURL, failed! Error connecting to the server: %s"%('Returning cache' if cache else '')) + log("Globals: requestURL, failed! Error connecting to the server: %s"%('Returning cache' if cache else 'No Response')) return __getCache(cacheKey,json_data,cache,checksum) if cache else __error(json_data) except requests.exceptions.HTTPError as e: - log("Globals: requestURL, failed! HTTP error occurred: %s\n%s"%('Returning cache' if cache else '')) + log("Globals: requestURL, failed! HTTP error occurred: %s\n%s"%('Returning cache' if cache else 'No Response')) return __getCache(cacheKey,json_data,cache,checksum) if cache else __error(json_data) except requests.exceptions.RequestException as e: log("Globals: requestURL, failed! An error occurred: %s"%(e), xbmc.LOGERROR) @@ -175,7 +173,7 @@ def getRecordID(name, path, number): def splitYear(label): try: - match = re.compile('(.*) \((.*)\)', re.IGNORECASE).search(label) + match = re.compile(r'(.*) \((.*)\)', re.IGNORECASE).search(label) if match and match.group(2): label, year = match.groups() if year.isdigit(): @@ -334,8 +332,8 @@ def playSFX(filename, cached=False): xbmc.playSFX(filename, useCached=cached) def cleanLabel(text): - text = re.sub('\[COLOR=(.+?)\]', '', text) - text = re.sub('\[/COLOR\]', '', text) + text = re.sub(r'\[COLOR=(.+?)\]', '', text) + text = re.sub(r'\[/COLOR\]', '', text) text = text.replace("[B]",'').replace("[/B]",'') text = text.replace("[I]",'').replace("[/I]",'') return text.replace(":",'') diff --git a/plugin.video.pseudotv.live/resources/lib/jsonrpc.py b/plugin.video.pseudotv.live/resources/lib/jsonrpc.py index 8942e72e..c42dfaf2 100644 --- a/plugin.video.pseudotv.live/resources/lib/jsonrpc.py +++ b/plugin.video.pseudotv.live/resources/lib/jsonrpc.py @@ -158,13 +158,13 @@ def playerOpen(self, params={}): return self.sendJSON(param).get('result') == 'OK' - def getSetting(self, category, section, cache=True): + def getSetting(self, category, section, cache=False): param = {"method":"Settings.GetSettings","params":{"filter":{"category":category,"section":section}}} if cache: return self.cacheJSON(param).get('result',{}).get('settings',[]) else: return self.sendJSON(param).get('result', {}).get('settings',[]) - def getSettingValue(self, key, default='', cache=True): + def getSettingValue(self, key, default='', cache=False): param = {"method":"Settings.GetSettingValue","params":{"setting":key}} if cache: return (self.cacheJSON(param).get('result',{}).get('value') or default) else: return (self.sendJSON(param).get('result',{}).get('value') or default) @@ -246,7 +246,6 @@ def getMusicGenres(self, cache=True): def getDirectory(self, param={}, cache=True, checksum=ADDON_VERSION, expiration=datetime.timedelta(minutes=15)): param["properties"] = self.getEnums("List.Fields.Files", type='items') param = {"method":"Files.GetDirectory","params":param} - #todo carry over "error" to requestlist for user message. if cache: return self.cacheJSON(param, expiration, checksum).get('result', {}) else: return self.sendJSON(param).get('result', {}) @@ -268,8 +267,8 @@ def getFileDetails(self, file, media='video', properties=["duration","runtime"]) def getViewMode(self): - default = {"nonlinearstretch":False,"pixelratio":1,"verticalshift":0,"viewmode":"custom","zoom": 1.0} - response = self.cacheJSON({"method":"Player.GetViewMode","params":{}}).get('result',default) + default = {"nonlinearstretch":False,"pixelratio":1,"verticalshift":0,"viewmode":"custom","zoom": 1.0} + response = self.sendJSON({"method":"Player.GetViewMode","params":{}}).get('result',default) self.log('getViewMode, response = %s'%(response)) return response @@ -540,7 +539,6 @@ def padItems(self, files, page=SETTINGS.getSettingInt('Page_Limit')): return files - @cacheit(expiration=datetime.timedelta(seconds=FIFTEEN),json_data=False) def inputFriendlyName(self): with PROPERTIES.interruptActivity(): friendly = self.getSettingValue("services.devicename") diff --git a/plugin.video.pseudotv.live/resources/lib/kodi.py b/plugin.video.pseudotv.live/resources/lib/kodi.py index 4052facb..b70ad84e 100644 --- a/plugin.video.pseudotv.live/resources/lib/kodi.py +++ b/plugin.video.pseudotv.live/resources/lib/kodi.py @@ -510,10 +510,10 @@ def chkPVRInstance(self, instance=ADDON_NAME): self.log('chkPVRInstance, path = %s, failed to open file = %s\n%s'%(PVR_CLIENT_LOC,file,e)) continue - match = re.compile('(.*?)\', re.IGNORECASE).search(txt) + match = re.compile(r'(.*?)\', re.IGNORECASE).search(txt) try: name = match.group(1) except: - match = re.compile('(.*?)\', re.IGNORECASE).search(txt) + match = re.compile(r'(.*?)\', re.IGNORECASE).search(txt) try: name = match.group(1) except: name = None @@ -535,13 +535,13 @@ def getPVRInstanceSettings(self, instance): fle = FileAccess.open(instancePath,'r') for line in fle.readlines(): if not 'id=' in line: continue - match = re.compile('(.*?)\', re.IGNORECASE).search(line) + match = re.compile(r'(.*?)\', re.IGNORECASE).search(line) try: instanceConf.update({match.group(1):(match.group(2),match.group(3))}) except: - match = re.compile('(.*?)\', re.IGNORECASE).search(line) + match = re.compile(r'(.*?)\', re.IGNORECASE).search(line) try: instanceConf.update({match.group(1):('',match.group(2))}) except: - match = re.compile('', re.IGNORECASE).search(line) + match = re.compile(r'', re.IGNORECASE).search(line) try: instanceConf.update({match.group(1):(match.group(2),None)}) except: pass fle.close() @@ -633,14 +633,6 @@ def setRemoteHost(self, value): return self.setProperty('%s.Remote_Host'%(ADDON_ID),value) - def hasFirstrun(self): - return self.getEXTProperty('%s.has.Firstrun'%(ADDON_ID)) - - - def setFirstrun(self, state=True): - return self.setEXTPropertyBool('%s.has.Firstrun'%(ADDON_ID),state) - - def isRunning(self, key): return self.getEXTPropertyBool('%s.Running.%s'%(ADDON_ID,key)) @@ -653,22 +645,17 @@ def forceUpdateTime(self, key): return self.setPropertyInt(key,0) - def getUpdateChannelID(self): + def getUpdateChannels(self): ids = self.getPropertyList('updateChannels') - id = ids.pop(0) - self.setPropertyList('updateChannels',list(set(ids))) - self.log('getUpdateChannelID, id = %s, remaining = %s'%(id,len(ids))) - return id + self.clearProperty('updateChannels') + return ids def setUpdateChannels(self, id): ids = self.getPropertyList('updateChannels') ids.append(id) - return self.setPropertyList('updateChannels',list(set(ids))) - - - def clearUpdateChannels(self): - self.clearProperty('updateChannels') + self.setPropertyList('updateChannels',list(set(ids))) + return self.setEpochTimer('chkChannels') def setEpochTimer(self, key, state=True): diff --git a/plugin.video.pseudotv.live/resources/lib/overlay.py b/plugin.video.pseudotv.live/resources/lib/overlay.py index 953e4c8d..93255fea 100644 --- a/plugin.video.pseudotv.live/resources/lib/overlay.py +++ b/plugin.video.pseudotv.live/resources/lib/overlay.py @@ -26,11 +26,11 @@ class Background(xbmcgui.WindowXMLDialog): def __init__(self, *args, **kwargs): xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs) self.overlay = kwargs.get('overlay', None) - self.player = self.overlay.player - self.citem = self.player.sysInfo.get('citem',{}) - self.fitem = self.player.sysInfo.get('fitem',{}) - self.nitem = self.player.sysInfo.get('nitem',{}) self.visible = self.overlay.chkOnNextConditions() + self.sysInfo = self.overlay.player.sysInfo.copy() + self.citem = self.sysInfo.get('citem',{}) + self.fitem = self.sysInfo.get('fitem',{}) + self.nitem = self.sysInfo.get('nitem',{}) def onInit(self): @@ -42,7 +42,7 @@ def onInit(self): nowTitle = self.fitem.get('label' , BUILTIN.getInfoLabel('Title','VideoPlayer')) nextTitle = self.nitem.get('showlabel', BUILTIN.getInfoLabel('NextTitle','VideoPlayer')) onNow = '%s on %s'%(nowTitle,chname) if chname not in validString(nowTitle) else self.fitem.get('showlabel',nowTitle) - onNext = '%s @ %s'%(nextTitle ,BUILTIN.getInfoLabel('NextStartTime','VideoPlayer')) + onNext = '[B]@ %s[/B] %s'%(BUILTIN.getInfoLabel('NextStartTime','VideoPlayer'),nextTitle) self.getControl(40004).setImage(COLOR_FANART if land == FANART else land) self.getControl(40003).setText('%s %s[CR]%s %s'%(LANGUAGE(32104),onNow,LANGUAGE(32116),onNext)) @@ -69,11 +69,11 @@ class OnNext(xbmcgui.WindowXMLDialog): def __init__(self, *args, **kwargs): xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs) self.overlay = kwargs.get('overlay', None) - self.player = self.overlay.player - self.citem = self.player.sysInfo.get('citem',{}) - self.fitem = self.player.sysInfo.get('fitem',{}) - self.nitem = self.player.sysInfo.get('nitem',{}) self.visible = self.overlay.chkOnNextConditions() + self.sysInfo = self.overlay.player.sysInfo.copy() + self.citem = self.sysInfo.get('citem',{}) + self.fitem = self.sysInfo.get('fitem',{}) + self.nitem = self.sysInfo.get('nitem',{}) def onInit(self): @@ -435,7 +435,7 @@ def toggleOnNext(self, state: bool=True, cancel: bool=False): def __getOnNextInterval(interval, remaining): #split totalTime time into quarters, last quarter triggers nextup split by equal intervals of 3. ie. display 3 times in the last quarter of show totalTime = (int(self.player.getPlayerTime()) * (self.maxProgress / 100)) #total time minus max threshold - showTime = ((totalTime * .75) - (self.OSDTimer * interval)) + showTime = ((totalTime * .85) - (self.OSDTimer * interval)) intTime = roundupDIV(showTime,interval) if remaining < intTime: return __getOnNextInterval(interval+1, remaining) conditions = self.chkOnNextConditions() diff --git a/plugin.video.pseudotv.live/resources/lib/parsers/YTParser.py b/plugin.video.pseudotv.live/resources/lib/parsers/YTParser.py index 1f4a1ecd..60b6ffdb 100644 --- a/plugin.video.pseudotv.live/resources/lib/parsers/YTParser.py +++ b/plugin.video.pseudotv.live/resources/lib/parsers/YTParser.py @@ -23,8 +23,8 @@ def determineLength(self, filename: str) -> int and float: try: if hasAddon('script.module.youtube.dl'): from youtube_dl import YoutubeDL - if 'videoid' in filename: vID = (re.compile('videoid\=(.*)' , re.IGNORECASE).search(filename)).group(1) - elif 'video_id' in filename: vID = (re.compile('video_id\=(.*)', re.IGNORECASE).search(filename)).group(1) + if 'videoid' in filename: vID = (re.compile(r'videoid\=(.*)' , re.IGNORECASE).search(filename)).group(1) + elif 'video_id' in filename: vID = (re.compile(r'video_id\=(.*)', re.IGNORECASE).search(filename)).group(1) else: raise Exception('No video_id found.') log("YTParser: determineLength, file = %s, id = %s"%(filename,vID)) ydl = YoutubeDL({'no_color': True, 'format': 'best', 'outtmpl': '%(id)s.%(ext)s', 'no-mtime': True, 'add-header': HEADER}) diff --git a/plugin.video.pseudotv.live/resources/lib/predefined.py b/plugin.video.pseudotv.live/resources/lib/predefined.py index 85834d36..f611718a 100644 --- a/plugin.video.pseudotv.live/resources/lib/predefined.py +++ b/plugin.video.pseudotv.live/resources/lib/predefined.py @@ -22,7 +22,7 @@ class Predefined: def __init__(self): - ... + self.defaultMethod = SETTINGS.getSetting('Sort_Method').lower() def log(self, msg, level=xbmc.LOGDEBUG): @@ -32,7 +32,7 @@ def log(self, msg, level=xbmc.LOGDEBUG): def getParams(self) -> dict: params = {} params["order"] = {"direction" :"ascending", - "method" :SETTINGS.getSetting('Sort_Method').lower(), + "method" :self.defaultMethod, "ignorearticle" :True, "useartistsortname":True} return params.copy() @@ -70,7 +70,7 @@ def createShowPlaylist(self, show: str, method: str='episode') -> list: param["type"] = "episodes" param["order"]["method"] = method try: - match = re.compile('(.*) \((.*)\)', re.IGNORECASE).search(show) + match = re.compile(r'(.*) \((.*)\)', re.IGNORECASE).search(show) year, title = int(match.group(2)), match.group(1) param.setdefault("rules",{}).setdefault("and",[]).extend([{"field":"year","operator":"is","value":[year]},{"field":"tvshow","operator":"is","value":[quoteString(title)]}]) except: diff --git a/plugin.video.pseudotv.live/resources/lib/resources.py b/plugin.video.pseudotv.live/resources/lib/resources.py index 7e367e5e..704e9ede 100644 --- a/plugin.video.pseudotv.live/resources/lib/resources.py +++ b/plugin.video.pseudotv.live/resources/lib/resources.py @@ -131,9 +131,11 @@ def matchName(self, chname: str, name: str, type: str='Custom', auto: bool=False renames = list(set([name, slugify(name), validString(name)])) patterns = [getChannelSuffix, cleanChannelSuffix, stripRegion, splitYear] for chname in chnames: - if chname.lower() == name.lower(): return True + if not chname or not name: continue + elif chname.lower() == name.lower(): return True for rename in renames: - if chname.lower() == rename.lower(): return True + if not rename: continue + elif chname.lower() == rename.lower(): return True for pattern in patterns: try: rrename = pattern(rename,type) @@ -142,9 +144,10 @@ def matchName(self, chname: str, name: str, type: str='Custom', auto: bool=False rrename = pattern(rename) rchname = pattern(chname) finally: - if isinstance(rrename,(list,tuple)) and len(rrename) > 1: rrename = rrename[0] if isinstance(rchname,(list,tuple)) and len(rchname) > 1: rchname = rchname[0] - if chname.lower() == rrename.lower() or rename.lower() == rchname.lower() or rchname.lower() == rrename.lower(): return True + if isinstance(rrename,(list,tuple)) and len(rrename) > 1: rrename = rrename[0] + if not rchname or not rrename: continue + elif chname.lower() == rrename.lower() or rename.lower() == rchname.lower() or rchname.lower() == rrename.lower(): return True def buildWebImage(self, image: str) -> str: diff --git a/plugin.video.pseudotv.live/resources/lib/rules.py b/plugin.video.pseudotv.live/resources/lib/rules.py index dab090d0..253eeb69 100644 --- a/plugin.video.pseudotv.live/resources/lib/rules.py +++ b/plugin.video.pseudotv.live/resources/lib/rules.py @@ -516,8 +516,8 @@ def getPosition(self, optionindex):#todo vin utility to adjust zoom,vshift,prati def getImage(self, image=''): self.log('getImage, In image = %s'%(image)) - day = re.compile('\_Day(.*?)', re.IGNORECASE).search(image) - night = re.compile('\_Night(.*?)', re.IGNORECASE).search(image) + day = re.compile(r'\_Day(.*?)', re.IGNORECASE).search(image) + night = re.compile(r'\_Night(.*?)', re.IGNORECASE).search(image) mytime = time.localtime() if mytime.tm_hour < 6 or mytime.tm_hour > 18: if day: diff --git a/plugin.video.pseudotv.live/resources/lib/service.py b/plugin.video.pseudotv.live/resources/lib/service.py index d1731436..b627bcfe 100644 --- a/plugin.video.pseudotv.live/resources/lib/service.py +++ b/plugin.video.pseudotv.live/resources/lib/service.py @@ -84,7 +84,8 @@ def onAVChange(self): def onAVStarted(self): self.isPseudoTV = self.isPseudoTVPlaying() self.log('onAVStarted, pendingStop = %s, isPseudoTV = %s'%(self.pendingStop,self.isPseudoTV)) - if self.isPseudoTV: self._onPlay() + if self.isPseudoTV: self._onPlay() + else: self.service.monitor.toggleOverlay(False) def onPlayBackSeek(self, seek_time=None, seek_offset=None): #Kodi bug? `OnPlayBackSeek` no longer called by player during seek, issue limited to pvr? @@ -207,6 +208,7 @@ def _onPlay(self): if sysInfo.get('chid') == oldInfo.get('chid',random.random()): self.toggleInfo(self.infoOnChange) else: + self.service.monitor.toggleOverlay(False) self.sysInfo = self.runActions(RULES_ACTION_PLAYER_START, self.sysInfo.get('citem',{}), sysInfo, inherited=self) self.setRuntime(self.saveDuration,self.sysInfo.get('fitem',{}),self.sysInfo.get('runtime')) self.setSubtitles(self.lastSubState) #todo allow rules to set sub preference per channel. @@ -297,6 +299,7 @@ def __init__(self, service=None): self.jsonRPC = service.jsonRPC self.pendingSuspend = False self.pendingInterrupt = False + self.OSDTimer = SETTINGS.getSettingInt('OSD_Timer') def log(self, msg, level=xbmc.LOGDEBUG): @@ -309,7 +312,7 @@ def __getIdle(): except: #Kodi raises error after sleep. self.log('__getIdle, Kodi waking up from sleep...') idleTime = 0 - idleState = (idleTime > SETTINGS.getSettingInt('OSD_Timer')) + idleState = (idleTime > self.OSDTimer) return idleState, idleTime def __chkResumeTime(): diff --git a/plugin.video.pseudotv.live/resources/lib/tasks.py b/plugin.video.pseudotv.live/resources/lib/tasks.py index bf045913..0e1a591a 100644 --- a/plugin.video.pseudotv.live/resources/lib/tasks.py +++ b/plugin.video.pseudotv.live/resources/lib/tasks.py @@ -51,7 +51,7 @@ def _que(self, func, priority=-1, *args, **kwargs):# priority -1 autostack, 1 Hi def _initialize(self): tasks = [self.chkInstanceID, - self.chkFiles, + self.chkDirs, self.chkWelcome, self.chkDebugging, self.chkBackup, @@ -107,18 +107,18 @@ def _chkQueTimer(self): self.log('_chkQueTimer') self._chkEpochTimer('chkVersion' , self.chkVersion , 900) self._chkEpochTimer('chkKodiSettings' , self.chkKodiSettings , 900) - self._chkEpochTimer('chkFiles' , self.chkFiles , 300) self._chkEpochTimer('chkHTTP' , self.chkHTTP , 900) self._chkEpochTimer('chkDiscovery' , self.chkDiscovery , 300) self._chkEpochTimer('chkRecommended' , self.chkRecommended , 900) self._chkEpochTimer('chkLibrary' , self.chkLibrary , (MAX_GUIDEDAYS*3600)) self._chkEpochTimer('chkChannels' , self.chkChannels , (MAX_GUIDEDAYS*3600)) self._chkEpochTimer('chkJSONQUE' , self.chkJSONQUE , 300) + self._chkEpochTimer('chkFiles' , self.chkFiles , 300) - self._chkPropTimer('chkPVRRefresh' , self.chkPVRRefresh) - self._chkPropTimer('chkFillers' , self.chkFillers) - self._chkPropTimer('chkAutoTune' , self.chkAutoTune) - self._chkChannelUpdate() + self._chkPropTimer('chkPVRRefresh' , self.chkPVRRefresh , 1) + self._chkPropTimer('chkFillers' , self.chkFillers , 2) + self._chkPropTimer('chkAutoTune' , self.chkAutoTune , 2) + self._chkPropTimer('chkChannels' , self.chkChannels , 3, **{'proper':False}) def _chkEpochTimer(self, key, func, runevery, nextrun=None, *args, **kwargs): @@ -127,27 +127,17 @@ def _chkEpochTimer(self, key, func, runevery, nextrun=None, *args, **kwargs): if epoch >= nextrun: self.log('_chkEpochTimer, key = %s'%(key)) PROPERTIES.setPropertyInt(key,(epoch+runevery)) - return self._que(func) + return self._que(func, -1, *args, **kwargs) - def _chkPropTimer(self, key, func): + def _chkPropTimer(self, key, func, priority=-1, *args, **kwargs): key = '%s.%s'%(ADDON_ID,key) if PROPERTIES.getEXTPropertyBool(key): self.log('_chkPropTimer, key = %s'%(key)) PROPERTIES.clearEXTProperty(key) - self._que(func) - - - def _chkChannelUpdate(self): - id = PROPERTIES.getUpdateChannelID() - if id: - builder = Builder(self.service) - citem = builder.sortChannels([citem for citem in builder.verify() if citem.get('id') == id]) - del builder - self.log('_chkChannelUpdate, id = %s, citem = %s'%(id,citem)) - return self._que(self.chkChannels,3,citem) + self._que(func, priority , *args, **kwargs) - + @cacheit(expiration=datetime.timedelta(minutes=10)) def getOnlineVersion(self): try: ONLINE_VERSON = re.compile('" version="(.+?)" name="%s"'%(ADDON_NAME)).findall(str(requestURL(ADDON_URL)))[0] @@ -178,12 +168,16 @@ def chkKodiSettings(self): SETTINGS.setSetting('ZeroConf_Status',LANGUAGE(32211)%({True:'green',False:'red'}[zeroconf],{True:'Online',False:'Offline'}[zeroconf])) + def chkDirs(self): + self.log('chkDirs') + [FileAccess.makedirs(folder) for folder in [LOGO_LOC,FILLER_LOC,TEMP_LOC] if not FileAccess.exists(os.path.join(folder,''))] + + def chkFiles(self): self.log('chkFiles') - if PROPERTIES.hasFirstrun(): - if not FileAccess.exists(LIBRARYFLEPATH): self._que(self.chkLibrary,2) - if not (FileAccess.exists(CHANNELFLEPATH) & FileAccess.exists(M3UFLEPATH) & FileAccess.exists(XMLTVFLEPATH) & FileAccess.exists(GENREFLEPATH)): self._que(self.chkChannels,3) - [FileAccess.makedirs(folder) for folder in [LOGO_LOC,FILLER_LOC,TEMP_LOC] if not FileAccess.exists(os.path.join(folder,''))] + self.chkDirs() + if not FileAccess.exists(LIBRARYFLEPATH): self._que(self.chkLibrary,2) + if not (FileAccess.exists(CHANNELFLEPATH) & FileAccess.exists(M3UFLEPATH) & FileAccess.exists(XMLTVFLEPATH) & FileAccess.exists(GENREFLEPATH)): self._que(self.chkChannels,3) def chkHTTP(self): @@ -217,29 +211,35 @@ def chkLibrary(self, force=False): except Exception as e: self.log('chkLibrary failed! %s'%(e), xbmc.LOGERROR) - def chkChannels(self, channels: list=[]): + def chkChannels(self, channels: list=[], proper=True): + def __match(id, channels): + for citem in channels: + if citem['id'] == id: + return id try: builder = Builder(self.service) if not channels: - channels = builder.sortChannels(builder.verify()) - SETTINGS.setSetting('Select_Channels','[B]%s[/B] Channels'%(len(channels))) - PROPERTIES.setChannels(len(channels) > 0) - PROPERTIES.clearUpdateChannels() #updating all channels clear any pending individual channel updates - self.service.currentChannels = channels #update service channels + ids = PROPERTIES.getUpdateChannels() + if ids and not proper: + channels = list(builder.sortChannels(poolit(__match)(ids, **{'channels':list(builder.verify())}))) + else: + channels = list(builder.sortChannels(builder.verify())) + SETTINGS.setSetting('Select_Channels','[B]%s[/B] Channels'%(len(channels))) + PROPERTIES.setChannels(len(channels) > 0) + self.service.currentChannels = channels #update service channels - self.log('chkChannels, channels = %s'%(len(channels))) if len(channels) > 0: complete, updated = builder.build(channels) - if not complete and PROPERTIES.hasFirstrun(): self._que(self.chkChannels,3,channels) - elif updated: PROPERTIES.setEpochTimer('chkPVRRefresh') - if SETTINGS.getSettingBool('Build_Filler_Folders'): self._que(self.chkFillers,-1,channels) + self.log('chkChannels, channels = %s, proper = %s, complete = %s, updated = %s'%(len(channels),proper,complete,updated)) + if complete: + if updated: PROPERTIES.setEpochTimer('chkPVRRefresh') + if SETTINGS.getSettingBool('Build_Filler_Folders'): self._que(self.chkFillers,-1,channels) + else: self._que(self.chkChannels,3,channels) del builder - - if not PROPERTIES.hasFirstrun(): PROPERTIES.setFirstrun(state=True) except Exception as e: self.log('chkChannels failed! %s'%(e), xbmc.LOGERROR) - + def chkJSONQUE(self): if not PROPERTIES.isRunning('chkJSONQUE'): with PROPERTIES.setRunning('chkJSONQUE'): @@ -322,7 +322,7 @@ def getGenreNames(self): def getChannels(self): try: builder = Builder(self.service) - channels = builder.sortChannels(builder.verify()) + channels = list(builder.sortChannels(builder.verify())) del builder self.log('getChannels, channels = %s'%(len(channels))) return channels diff --git a/plugin.video.pseudotv.live/resources/lib/utilities.py b/plugin.video.pseudotv.live/resources/lib/utilities.py index 31744ff5..a8f3e8be 100644 --- a/plugin.video.pseudotv.live/resources/lib/utilities.py +++ b/plugin.video.pseudotv.live/resources/lib/utilities.py @@ -188,11 +188,8 @@ def deleteFiles(self, msg, full: bool=False): with BUILTIN.busy_dialog(): for key in keys: if FileAccess.delete(files[key]): DIALOG.notificationDialog(LANGUAGE(32127)%(key.replace(':',''))) - - if full: - startChannelBuild() - else: - PROPERTIES.forceUpdateTime('chkChannels') + if full: startChannelBuild() + else: PROPERTIES.forceUpdateTime('chkChannels') def sortMethod(self): diff --git a/plugin.video.pseudotv.live/resources/lib/xmltvs.py b/plugin.video.pseudotv.live/resources/lib/xmltvs.py index 8258207f..c02cab7c 100644 --- a/plugin.video.pseudotv.live/resources/lib/xmltvs.py +++ b/plugin.video.pseudotv.live/resources/lib/xmltvs.py @@ -87,7 +87,7 @@ def _error(self, name, file, e): #hacky; try to log malformed xml's by printing error position.. if not 'no element found: line 1, column 0' in str(e): try: - match = re.compile('line\ (.*?),\ column\ (.*)', re.IGNORECASE).search(str(e)) + match = re.compile(r'line\ (.*?),\ column\ (.*)', re.IGNORECASE).search(str(e)) if match: fle = FileAccess.open(file,'r') file = fle.readlines() diff --git a/plugin.video.pseudotv.live/resources/lib/xsp.py b/plugin.video.pseudotv.live/resources/lib/xsp.py index 32688783..5e217a13 100644 --- a/plugin.video.pseudotv.live/resources/lib/xsp.py +++ b/plugin.video.pseudotv.live/resources/lib/xsp.py @@ -54,7 +54,7 @@ def getName(self, fle: str) -> str: xml = FileAccess.open(fle, "r") string = xml.read() xml.close() - match = re.compile('<%s>(.*?)\'%(key,key), re.IGNORECASE).search(string) + match = re.compile(r'<%s>(.*?)\'%(key,key), re.IGNORECASE).search(string) if match: name = unescapeString(match.group(1)) self.log("getName, fle = %s, name = %s"%(fle,name)) except: self.log("getName, return unable to parse %s"%(fle), xbmc.LOGERROR) diff --git a/plugin.video.pseudotv.live/resources/skins/default/1080i/plugin.video.pseudotv.live.background.xml b/plugin.video.pseudotv.live/resources/skins/default/1080i/plugin.video.pseudotv.live.background.xml index 8a9b9f0c..3cca1a5c 100644 --- a/plugin.video.pseudotv.live/resources/skins/default/1080i/plugin.video.pseudotv.live.background.xml +++ b/plugin.video.pseudotv.live/resources/skins/default/1080i/plugin.video.pseudotv.live.background.xml @@ -77,9 +77,10 @@ - + 130 735 + 960/ 15 vertical @@ -95,6 +96,7 @@ 70 960/ + 145 font27 true white diff --git a/plugin.video.pseudotv.live/resources/skins/default/1080i/plugin.video.pseudotv.live.onnext.xml b/plugin.video.pseudotv.live/resources/skins/default/1080i/plugin.video.pseudotv.live.onnext.xml index 262c7e03..729a3be9 100644 --- a/plugin.video.pseudotv.live/resources/skins/default/1080i/plugin.video.pseudotv.live.onnext.xml +++ b/plugin.video.pseudotv.live/resources/skins/default/1080i/plugin.video.pseudotv.live.onnext.xml @@ -19,12 +19,12 @@ - + 130 735 + 960/ 15 vertical - Window.IsActive(fullscreenvideo) + [!Window.IsActive(videoosd)] OnNext Image 135 @@ -38,6 +38,7 @@ 70 960/ + 145 font27 true white diff --git a/zips/plugin.video.pseudotv.live/plugin.video.pseudotv.live-0.5.7b.zip b/zips/plugin.video.pseudotv.live/plugin.video.pseudotv.live-0.5.7b.zip new file mode 100644 index 00000000..bb822b9c Binary files /dev/null and b/zips/plugin.video.pseudotv.live/plugin.video.pseudotv.live-0.5.7b.zip differ