Skip to content

Commit

Permalink
v.0.4.6b
Browse files Browse the repository at this point in the history
  • Loading branch information
Lunatixz committed Mar 21, 2024
1 parent e9451a3 commit d08e19d
Show file tree
Hide file tree
Showing 14 changed files with 123 additions and 51 deletions.
3 changes: 2 additions & 1 deletion addons.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addons>
<addon id="plugin.video.pseudotv.live" version="0.4.6a" name="PseudoTV Live" provider-name="Lunatixz">
<addon id="plugin.video.pseudotv.live" version="0.4.6b" name="PseudoTV Live" provider-name="Lunatixz">
<requires>
<import addon="xbmc.python" version="3.0.1"/>
<import addon="pvr.iptvsimple" version="21.8.0"/>
Expand All @@ -12,6 +12,7 @@
<import addon="resource.images.studios.white" version="0.0.1"/>
<import addon="resource.images.musicgenreicons.text" version="0.0.1"/>
<import addon="resource.images.moviegenreicons.transparent" version="0.0.1"/>
<import addon="resource.videos.ratings.mpaa.classic" optional="true" version="0.0.4"/>
<import addon="script.module.pil" optional="true" version="5.1.0"/>
</requires>
<extension point="xbmc.python.pluginsource" library="resources/lib/default.py">
Expand Down
2 changes: 1 addition & 1 deletion addons.xml.md5
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3e63f2ba1de138e9ccc81c1260e3c3d5
c114e588b689314a3e71fca10db045fb
3 changes: 2 additions & 1 deletion plugin.video.pseudotv.live/addon.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon id="plugin.video.pseudotv.live" version="0.4.6a" name="PseudoTV Live" provider-name="Lunatixz">
<addon id="plugin.video.pseudotv.live" version="0.4.6b" name="PseudoTV Live" provider-name="Lunatixz">
<requires>
<import addon="xbmc.python" version="3.0.1"/>
<import addon="pvr.iptvsimple" version="21.8.0"/>
Expand All @@ -11,6 +11,7 @@
<import addon="resource.images.studios.white" version="0.0.1"/>
<import addon="resource.images.musicgenreicons.text" version="0.0.1"/>
<import addon="resource.images.moviegenreicons.transparent" version="0.0.1"/>
<import addon="resource.videos.ratings.mpaa.classic" optional="true" version="0.0.4"/>
<import addon="script.module.pil" optional="true" version="5.1.0"/>
</requires>
<extension point="xbmc.python.pluginsource" library="resources/lib/default.py">
Expand Down
2 changes: 1 addition & 1 deletion plugin.video.pseudotv.live/changelog.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
v.0.4.7

-Fixed misc. playback issues.

v.0.4.6
-Refactored Seasonal & Provisional Autotuning.
Expand Down
17 changes: 13 additions & 4 deletions plugin.video.pseudotv.live/resources/lib/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ def __init__(self, service=None):
self.sort = {} #{"ignorearticle":true,"method":"random","order":"ascending","useartistsortname":true}
self.limits = {} #{"end":0,"start":0,"total":0}

self.incRatings = SETTINGS.getSettingInt('Fillers_Ratings')
self.resRatings = SETTINGS.getSetting('Resource_Ratings').split('|')
self.incBumpers = SETTINGS.getSettingInt('Fillers_Bumpers')
self.resBumpers = SETTINGS.getSetting('Resource_Bumpers').split('|')
self.incAdverts = SETTINGS.getSettingInt('Fillers_Commercials')
self.resAdverts = SETTINGS.getSetting('Resource_Commericals').split('|')
self.incTrailer = SETTINGS.getSettingInt('Fillers_Trailers')
self.resTrailer = SETTINGS.getSetting('Resource_Trailers').split('|')

self.minDuration = SETTINGS.getSettingInt('Seek_Tolerance')
self.maxDays = MAX_GUIDEDAYS
self.minEPG = 10800 #Secs., Min. EPG guidedata
Expand All @@ -66,10 +75,10 @@ def __init__(self, service=None):
self.jsonRPC = JSONRPC()
self.xsp = XSP()
self.m3u = M3U()
self.fillers = Fillers(self)
self.resources = Resources(self.jsonRPC,self.cache)




def log(self, msg, level=xbmc.LOGDEBUG):
return log('%s: %s'%(self.__class__.__name__,msg),level)

Expand Down Expand Up @@ -149,8 +158,8 @@ def getFileList(self, citem, now, start):
else: cacheResponse = self.buildChannel(citem)

if cacheResponse:
if self.fillBCTs and not radio: cacheResponse = Fillers(self).injectBCTs(citem, cacheResponse)
cacheResponse = self.addScheduling(citem, cacheResponse, start)
if self.fillBCTs and not radio: cacheResponse = self.fillers.injectBCTs(citem, cacheResponse)
return sorted(cacheResponse, key=lambda k: k['start'])
else: raise Exception('cacheResponse in-valid!\n%s'%(cacheResponse))
except Exception as e: self.log("getFileList, failed! %s"%(e), xbmc.LOGERROR)
Expand Down Expand Up @@ -425,7 +434,7 @@ def is3D(self, item):
elif not 'streamdetails' in item: item['streamdetails'] = self.jsonRPC.getStreamDetails(item.get('file'), item.get('media','video'))
details = item.get('streamdetails',{})
if 'video' in details and details.get('video') != [] and len(details.get('video')) > 0:
stereomode = (details['video'][0]['stereomode'] or '')
stereomode = (details['video'][0]['stereomode'] or [])
if len(stereomode) > 0: return True
return False

Expand Down
90 changes: 74 additions & 16 deletions plugin.video.pseudotv.live/resources/lib/fillers.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@
from globals import *
from resources import Resources

RATING_DESC = {"G" :"General audiences – All ages admitted.\nNothing that would offend parents for viewing by children.",
"PG" :"Parental guidance suggested – Some material may not be suitable for children.\nParents urged to give “parental guidance.” May contain some material parents might not like for their young children",
"PG-13":"Parents strongly cautioned – Some material may be inappropriate for children under 13.\nParents are urged to be cautious. Some material may be inappropriate for pre-teenagers.",
"R" :"Restricted – Under 17 requires accompanying parent or adult guardian.\nContains some adult material. Parents are urged to learn more about the film before taking their young children with them.",
"NC-17":"Adults only – No one 17 and under admitted.\nClearly adult. Children are not admitted.",
"NR" :"Film has not been submitted for a rating or it's rating is unknown."}

class Fillers:
def __init__(self, builder):
self.builder = builder
Expand All @@ -29,37 +36,88 @@ def __init__(self, builder):
self.resources = Resources(self.jsonRPC,self.cache)

#default global rules:
self.bctTypes = {"ratings" :{"min":1,"max":1,"auto":SETTINGS.getSettingInt('Fillers_Ratings') == 1,"enabled":SETTINGS.getSettingInt('Fillers_Ratings') > 0,"paths":(SETTINGS.getSetting('Resource_Ratings')).split('|')},
"bumpers" :{"min":1,"max":1,"auto":SETTINGS.getSettingInt('Fillers_Bumpers') == 1,"enabled":SETTINGS.getSettingInt('Fillers_Bumpers') > 0,"paths":(SETTINGS.getSetting('Resource_Bumpers')).split('|')},}
self.bctTypes = {"ratings" :{"min":1,"max":1,"auto":builder.incRatings == 1,"enabled":bool(builder.incRatings),"paths":builder.resRatings,"resources":{}},
"bumpers" :{"min":1,"max":1,"auto":builder.incBumpers == 1,"enabled":bool(builder.incBumpers),"paths":builder.resBumpers,"resources":{}},}

# "commercials":{"min":SETTINGS.getSettingInt('Fillers_Commercials'),"max":4,
# "enabled":SETTINGS.getSettingInt('Fillers_Commercials') > 0,"paths":(SETTINGS.getSetting('Resource_Commericals')).split('|')},

# "trailers" :{"min":SETTINGS.getSettingInt('Fillers_Trailers') ,"max":SETTINGS.getSettingInt('Fillers_Trailers') - 2,
# "enabled":SETTINGS.getSettingInt('Fillers_Trailers') > 0,"paths":(SETTINGS.getSetting('Resource_Trailers')).split('|')}}

# self.buildResourceByType('ratings',self.bctTypes['ratings']['paths'])


def log(self, msg, level=xbmc.LOGDEBUG):
return log('%s: %s'%(self.__class__.__name__,msg),level)


def buildResource(self, type, path):
cacheName = 'buildResource.%s'%(getMD5(path))
# if not hasAddon(id): continue
# addonMeta = self.jsonRPC.getAddonDetails(addonid)
# self.cache.get(cacheName, checksum=addonMeta.get('version',ADDON_VERSION), json_data=True)
# self.cache.set(cacheName, payload, checksum=addonMeta.get('version',ADDON_VERSION), expiration=datetime.timedelta(days=MAX_GUIDEDAYS), json_data=True)


def buildResourceByType(self, type):
...

@cacheit(expiration=datetime.timedelta(minutes=15),json_data=True)
def buildResourceByType(self, type, ids):
def _parse(ids):
for id in ids:
if not hasAddon(id): continue
yield self.resources.walkResource(id,exts=VIDEO_EXTS)

for resource in list(_parse(ids)):
for path in resource:
for file in resource[path]:
key = file.split('.')[0].replace(' (3DSBS)','')
if '(3DSBS)' in file: self.bctTypes['ratings'].get('resources',{}).setdefault('3D',{}).setdefault(key,[]).append(os.path.join(path,file))
else: self.bctTypes['ratings'].get('resources',{}).setdefault(key,[]).append(os.path.join(path,file))
print('buildResourceByType',self.bctTypes.get(type,{}))


def getRating(self, fileItem, mpaa):
def _convert(rating):
#https://www.spherex.com/tv-ratings-vs-movie-ratings
#https://www.spherex.com/which-is-more-regulated-film-or-tv
return rating.replace('TV-Y','G').replace('TV-Y7','G').replace('TV-G','G').replace('NA','NR').replace('TV-PG','PG').replace('TV-14','PG-13').replace('TV-MA','R')

try:
mpaa = mpaa.upper()
mpaa = re.compile(":(.*?)/", re.IGNORECASE).search(mpaa).group(1)
except: pass

files = []
print('getRating',mpaa)
if self.builder.is3D(fileItem): files = self.bctTypes['ratings']['resources'].get('3D',{}).get(mpaa,[])
if not files: files = self.bctTypes['ratings'].get('resources',{}).get(mpaa,[])
if not files:
mpaa = _convert(mpaa)
files = self.bctTypes['ratings'].get('resources',{}).get(mpaa,[])
if files: return mpaa, random.choice(files)
return mpaa, files


def injectBCTs(self, citem, fileList):
return fileList

# if self.fillBCTs and not citem.get('radio',False): cacheResponse =
# nfileList = []
# for idx, fileItem in enumerate(fileList):
# if not fileItem: continue
# elif self.builder.service._interrupt() or self.builder.service._suspend(): break
# else:
# try:
# #pre roll - ratings
# if fileItem.get('type').startswith(tuple(MOVIE_TYPES)):
# if self.bctTypes['ratings']['enabled']:
# mpaa = fileItem.get('mpaa','NR')
# mpaa, file = self.getRating(fileItem, mpaa)
# print('injectBCTs',mpaa,file)
# if file:
# dur = self.jsonRPC.getDuration(file, accurate=True)
# if dur > 0:
# self.log('injectBCTs, adding ratings %s\n%s - %s'%(fileItem.get('title'),file,dur))
# nfileList.append(self.builder.buildCells(citem,dur,entries=1,info={'title':mpaa,'genre':['ratings'],'plot':RATING_DESC.get(mpaa,''),'path':file})[0])
# # #pre roll - bumpers
# # elif fileItem.get('type').startswith(tuple(TV_TYPES)):
# # ...
# except Exception as e: self.log('injectBCTs, pre roll failed! %s'%(e), xbmc.LOGERROR)
# nfileList.append(fileItem)
# #post roll - commercials/trailers
# return nfileList


return fileList
# if not fileList: return fileList
# self.log("injectBCTs, channel = %s, fileList = %s"%(citem.get('id'),len(fileList)))
# ratings = self.buildResourceByType('ratings')
Expand Down
2 changes: 1 addition & 1 deletion plugin.video.pseudotv.live/resources/lib/overlay.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def onInit(self):
citem = self.player.sysInfo.get('citem',{})
self.runActions(RULES_ACTION_BACKGROUND_OPEN, citem, inherited=self)
self.getControl(40001).setVisible(self.showStatic)
self.getControl(40002).setImage(citem.get('icon',COLOR_LOGO))
self.getControl(40002).setImage(citem.get('logo',COLOR_LOGO))
self.getControl(40003).setText(LANGUAGE(32104)%(citem.get('name',ADDON_NAME)))
except:
self.runActions(RULES_ACTION_BACKGROUND_CLOSE, citem, inherited=self)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,7 @@ def __init__(self):

def determineLength(self, filename):
log("MP4Parser: determineLength " + filename)

try:
# self.File = xbmcvfs.File(filename, "r")
self.File = FileAccess.open(filename, "rb", None)
try: self.File = FileAccess.open(filename, "rb", None)
except:
log("MP4Parser: Unable to open the file")
return
Expand Down Expand Up @@ -129,7 +126,6 @@ def readBlock(self):
if box.size == 1:
box.size = struct.unpack('>q', self.File.readBytes(8))[0]
box.size -= 8

box.size -= 8

if box.boxtype == 'uuid':
Expand Down
11 changes: 5 additions & 6 deletions plugin.video.pseudotv.live/resources/lib/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def __init__(self, sysARG=sys.argv):
self.sysInfo.update({"name" : (unquoteString(self.sysInfo.get('name','')) or BUILTIN.getInfoLabel('ChannelName')),
"title" : (unquoteString(self.sysInfo.get('title','')) or BUILTIN.getInfoLabel('label')),
"vid" : decodeString(self.sysInfo.get('vid','')),
"duration" : int(self.sysInfo.get('duration',str(timeString2Seconds(BUILTIN.getInfoLabel('Duration(hh:mm:ss)'))))),
"duration" : (timeString2Seconds(BUILTIN.getInfoLabel('Duration(hh:mm:ss)')) or int(self.sysInfo.get('duration',0))),
"progress" : (BUILTIN.getInfoLabel('Progress'),BUILTIN.getInfoLabel('PercentPlayed')),
"chlabel" : BUILTIN.getInfoLabel('ChannelNumberLabel'),
"chpath" : BUILTIN.getInfoLabel('FileNameAndPath'),
Expand All @@ -64,11 +64,13 @@ def __init__(self, sysARG=sys.argv):
self.sysInfo["starttime"] = datetime.datetime.fromtimestamp((datetime.datetime.timestamp(strpTime(self.sysInfo['start'], DTJSONFORMAT)) - getTimeoffset())).strftime(DTJSONFORMAT)
self.sysInfo['endtime'] = datetime.datetime.fromtimestamp(datetime.datetime.timestamp(strpTime(self.sysInfo['starttime'], DTJSONFORMAT) + datetime.timedelta(seconds=self.sysInfo['duration']))).strftime(DTJSONFORMAT)
self.sysInfo["seek"] = (getUTCstamp() - datetime.datetime.timestamp(strpTime(self.sysInfo['starttime'], DTJSONFORMAT)))
self.sysInfo["now"] = datetime.datetime.fromtimestamp(getUTCstamp()).strftime(DTJSONFORMAT)
except:
self.sysInfo['epoch'] = None
self.sysInfo["starttime"] = None
self.sysInfo["endtime"] = None
self.sysInfo["seek"] = None
self.sysInfo["now"] = None

self.log('__init__, sysARG = %s\nsysInfo = %s'%(sysARG,self.sysInfo))

Expand Down Expand Up @@ -101,13 +103,10 @@ def playLive(self, name, chid, vid):
def playBroadcast(self, name, chid, vid):
with self.preparingPlayback():
self.log('playBroadcast, id = %s, start = %s, seek = %s'%(chid,self.sysInfo['start'],self.sysInfo['seek']))
if self.sysInfo['seek'] <= self.seekTOL: self.sysInfo['seek'] = 0
liz = xbmcgui.ListItem(name,path=vid)
liz.setProperty("IsPlayable","true")
liz.setProperty('sysInfo',dumpJSON(self.sysInfo))
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)})
self.resolveURL(True, liz)


Expand Down Expand Up @@ -290,10 +289,10 @@ def playCHK(self, oldInfo={}):
if self.sysInfo['duration'] > self.sysInfo['runtime']:
self.log('playCHK, failed! Duration error between player (%s) and pvr (%s).'%(self.sysInfo['duration'],self.sysInfo['runtime']))
return False
elif int(oldInfo['seek']) >= oldInfo['duration']:
if int(oldInfo['seek']) >= oldInfo['duration']:
self.log('playCHK, failed! Seeking past duration.')
return False
elif oldInfo['seek'] == self.sysInfo['seek']:
if oldInfo['seek'] == self.sysInfo['seek']:
self.log('playCHK, failed! Seeking to same position.')
return False
return True
Expand Down
12 changes: 5 additions & 7 deletions plugin.video.pseudotv.live/resources/lib/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def openFile(fle):
openAddonSettings((7,1))
#todo generate qrcode to server file location.
#todo change xmltv to display statistics not raw file.
try: DIALOG.textviewer(openFile(file), heading=('%s - %s')%(ADDON_NAME,os.path.basename(file)),usemono=True,usethread=True)
try: DIALOG.textviewer(openFile(file), heading=('%s - %s')%(ADDON_NAME,os.path.basename(file)),usemono=True,usethread=False)
except Exception as e: self.log('showFile failed! %s'%(e), xbmc.LOGERROR)


Expand Down Expand Up @@ -88,7 +88,7 @@ def convertMD2TXT(md):
fle = FileAccess.open(README_FLE, "r")
txt = fle.read()
fle.close()
try: DIALOG.textviewer(convertMD2TXT(txt), heading=(LANGUAGE(32043)%(ADDON_NAME,ADDON_VERSION)),usemono=True,usethread=True)
try: DIALOG.textviewer(convertMD2TXT(txt), heading=(LANGUAGE(32043)%(ADDON_NAME,ADDON_VERSION)),usemono=True,usethread=False)
except Exception as e: self.log('showReadme failed! %s'%(e), xbmc.LOGERROR)


Expand All @@ -111,7 +111,7 @@ def addColor(text):
fle = FileAccess.open(CHANGELOG_FLE, "r")
txt = fle.read()
fle.close()
try: DIALOG.textviewer(addColor(txt), heading=(LANGUAGE(32045)%(ADDON_NAME,ADDON_VERSION)),usemono=True, autoclose=30, usethread=True)
try: DIALOG.textviewer(addColor(txt), heading=(LANGUAGE(32045)%(ADDON_NAME,ADDON_VERSION)),usemono=True, autoclose=30, usethread=False)
except Exception as e: self.log('showChangelog failed! %s'%(e), xbmc.LOGERROR)


Expand Down Expand Up @@ -216,11 +216,9 @@ def run(self):
ctl = (5,5)
self.openChannelBug()
elif param == 'Show_Welcome':
with busy_dialog():
return self.showWelcome()
return self.showWelcome()
elif param == 'Show_Readme':
with busy_dialog():
return self.showReadme()
return self.showReadme()
elif param == 'Show_Changelog':
return self.showChangelog()
elif param == 'User_Groups':
Expand Down
Loading

0 comments on commit d08e19d

Please sign in to comment.