Files
DevOps/Kodi/Lenovo/addons/plugin.video.pseudotv.live/resources/lib/multiroom.py

211 lines
10 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 server import Discovery
class Service:
from jsonrpc import JSONRPC
player = PLAYER()
monitor = MONITOR()
jsonRPC = JSONRPC()
def _interrupt(self) -> bool:
return PROPERTIES.isPendingInterrupt()
def _suspend(self) -> bool:
return PROPERTIES.isPendingSuspend()
class Multiroom:
def __init__(self, sysARG=sys.argv, service=None):
self.log('__init__, sysARG = %s'%(sysARG))
if service is None: service = Service()
self.service = service
self.jsonRPC = service.jsonRPC
self.cache = service.jsonRPC.cache
self.sysARG = sysARG
self.uuid = SETTINGS.getMYUUID()
self.friendly = SETTINGS.getFriendlyName()
self.remoteHost = PROPERTIES.getRemoteHost()
def log(self, msg, level=xbmc.LOGDEBUG):
return log('%s: %s'%(self.__class__.__name__,msg),level)
@cacheit(checksum=PROPERTIES.getInstanceID(), expiration=datetime.timedelta(minutes=FIFTEEN))
def _getStatus(self):
return self.jsonRPC.getSettingValue("services.zeroconf",default=False)
def _chkDiscovery(self):
self.log('_chkDiscovery')
Discovery(service=self.service, multiroom=self)
def chkServers(self, servers={}):
def __chkSettings(settings):
[hasAddon(id,install=True,enable=True) for k,addons in list(settings.items()) for id in addons if id.startswith(('resource','plugin'))]
if isinstance(servers,bool): servers = {} #temp fix remove after a by next build
if not servers: servers = self.getDiscovery()
PROPERTIES.setServers(len(servers) > 0)
for server in list(servers.values()):
online = server.get('online',False)
response = self.getRemote(server.get('remotes',{}).get('bonjour'))
if response: server['online'] = True
else: server['online'] = False
if server.get('enabled',False):
if online != server.get('online',False): DIALOG.notificationDialog('%s: %s'%(server.get('name'),LANGUAGE(32211)%({True:'green',False:'red'}[server.get('online',False)],{True:LANGUAGE(32158),False:LANGUAGE(32253)}[server.get('online',False)])))
__chkSettings(loadJSON(server.get('settings')))
SETTINGS.setSetting('Select_server','|'.join([LANGUAGE(32211)%({True:'green',False:'red'}[server.get('online',False)],server.get('name')) for server in self.getEnabled(servers)]))
self.log('chkServers, servers = %s'%(len(servers)))
self.setDiscovery(servers)
return servers
def getDiscovery(self):
servers = getJSON(SERVER_LOC).get('servers',{})
if isinstance(servers,bool): servers = {} #temp fix remove after a by next build
return servers
def setDiscovery(self, servers={}):
return setJSON(SERVER_LOC,{"servers":servers})
def getEnabled(self, servers={}):
if not servers: servers = self.getDiscovery()
enabled = [server for server in list(servers.values()) if server.get('enabled',False)]
PROPERTIES.setEnabledServers(len(enabled) > 0)
return enabled
@cacheit(expiration=datetime.timedelta(minutes=FIFTEEN), json_data=True)
def getRemote(self, remote):
self.log("getRemote, remote = %s"%(remote))
cacheName = 'getRemote.%s'%(remote)
return requestURL(remote, header={'Accept':'application/json'}, json_data=True, cache=self.cache, checksum=self.uuid, life=datetime.timedelta(days=MAX_GUIDEDAYS))
def addServer(self, payload={}):
self.log('addServer, name = %s'%(payload.get('name')))
if payload and payload.get('name') and payload.get('host'):
payload['online'] = True
servers = self.getDiscovery()
server = servers.get(payload.get('name'),{})
if not server:
payload['enabled'] = not bool(SETTINGS.getSettingBool('Debug_Enable')) #set enabled by default when not debugging.
self.log('addServer, adding server = %s'%(payload))
DIALOG.notificationDialog('%s: %s'%(LANGUAGE(32047),payload.get('name')))
servers[payload['name']] = payload
else:
payload['enabled'] = server.get('enabled',False)
if payload.get('md5',server.get('md5')) != server.get('md5'):
self.log('addServer, updating server = %s'%(server))
servers.update({payload['name']:payload})
if self.setDiscovery(self.chkServers(servers)):
instancePath = SETTINGS.hasPVRInstance(server.get('name'))
if payload.get('enabled',False) and not instancePath: changed = SETTINGS.setPVRRemote(payload.get('host'),payload.get('name'))
elif not payload.get('enabled',False) and instancePath: changed = FileAccess.delete(instancePath)
else: changed = False
if changed: PROPERTIES.setPropTimer('chkPVRRefresh')
self.log('addServer, payload changed, chkPVRRefresh = %s'%(changed))
return True
def delServer(self, servers={}):
self.log('delServer')
def __build(idx, payload):
return LISTITEMS.buildMenuListItem(payload.get('name'),'%s - %s: Channels (%s)'%(LANGUAGE(32211)%({True:'green',False:'red'}[payload.get('online',False)],{True:LANGUAGE(32158),False:LANGUAGE(32253)}[payload.get('online',False)]),payload.get('host'),len(payload.get('channels',[]))),icon=DUMMY_ICON.format(text=str(idx+1)),url=dumpJSON(payload))
with BUILTIN.busy_dialog():
if not servers: servers = self.getDiscovery()
lizlst = [__build(idx, server) for idx, server in enumerate(list(servers.values()))]
selects = DIALOG.selectDialog(lizlst,LANGUAGE(32183))
if not selects is None:
[servers.pop(liz.getLabel()) for idx, liz in enumerate(lizlst) if idx in selects]
if self.setDiscovery(self.chkServers(servers)):
return DIALOG.notificationDialog(LANGUAGE(30046))
def selServer(self):
self.log('selServer')
def __build(idx, payload):
return LISTITEMS.buildMenuListItem(payload.get('name'),'%s - %s: Channels (%s)'%(LANGUAGE(32211)%({True:'green',False:'red'}[payload.get('online',False)],{True:LANGUAGE(32158),False:LANGUAGE(32253)}[payload.get('online',False)]),payload.get('host'),len(payload.get('channels',[]))),icon=DUMMY_ICON.format(text=str(idx+1)),url=dumpJSON(payload))
with BUILTIN.busy_dialog():
servers = self.getDiscovery()
lizlst = [__build(idx, server) for idx, server in enumerate(list(servers.values()))]
if len(lizlst) > 0: lizlst.insert(0,LISTITEMS.buildMenuListItem('[COLOR=white][B]- %s[/B][/COLOR]'%(LANGUAGE(30046)),LANGUAGE(33046)))
else: return
selects = DIALOG.selectDialog(lizlst,LANGUAGE(30130),preselect=[idx for idx, listitem in enumerate(lizlst) if loadJSON(listitem.getPath()).get('enabled',False)])
if not selects is None:
if 0 in selects: return self.delServer(servers)
else:
for idx, liz in enumerate(lizlst):
if idx == 0: continue
instancePath = SETTINGS.hasPVRInstance(liz.getLabel())
if idx in selects:
if not servers[liz.getLabel()].get('enabled',False):
DIALOG.notificationDialog(LANGUAGE(30099)%(liz.getLabel()))
servers[liz.getLabel()]['enabled'] = True
if not instancePath:
if SETTINGS.setPVRRemote(servers[liz.getLabel()].get('host'),liz.getLabel()): PROPERTIES.setPropTimer('chkPVRRefresh')
else:
if servers[liz.getLabel()].get('enabled',False):
DIALOG.notificationDialog(LANGUAGE(30100)%(liz.getLabel()))
servers[liz.getLabel()]['enabled'] = False
if instancePath: FileAccess.delete(instancePath)
with BUILTIN.busy_dialog():
return self.setDiscovery(self.chkServers(servers))
def enableZeroConf(self):
self.log('enableZeroConf')
if SETTINGS.getSetting('ZeroConf_Status') == '[COLOR=red][B]%s[/B][/COLOR]'%(LANGUAGE(32253)):
if BUILTIN.getInfoLabel('Platform.Windows','System'):
BUILTIN.executescript('special://home/addons/%s/resources/lib/utilities.py, Show_ZeroConf_QR'%(ADDON_ID))
if DIALOG.yesnoDialog(message=LANGUAGE(30129)):
with PROPERTIES.interruptActivity():
if self.jsonRPC.setSettingValue("services.zeroconf",True,queue=False):
DIALOG.notificationDialog(LANGUAGE(32219)%(LANGUAGE(30035)))
PROPERTIES.setEpochTimer('chkKodiSettings')
else: DIALOG.notificationDialog(LANGUAGE(32219)%(LANGUAGE(30034)))
def run(self):
try: param = self.sysARG[1]
except: param = None
if param == 'Enable_ZeroConf':
ctl = (5,1)
self.enableZeroConf()
elif param == 'Select_Server':
ctl = (5,11)
self.selServer()
elif param == 'Remove_server':
ctl = (5,12)
return SETTINGS.openSettings(ctl)
if __name__ == '__main__': timerit(Multiroom(sys.argv).run)(0.1)