# -*- coding: utf-8 -*- """Keeps an IPTV Simple instance that plays this add-on's radio.m3u. Runs when Kodi starts and again after every add-on update. Writes the instance settings, then restarts IPTV Simple (once nothing is playing) if the settings or the station list changed since the last run. """ import glob import hashlib import io import json import os import xbmc import xbmcaddon import xbmcvfs ADDON = xbmcaddon.Addon() ADDON_ID = ADDON.getAddonInfo('id') HOME = 'special://home/addons/{}/resources/'.format(ADDON_ID) FIRST_INSTANCE = 95 # KodiMov+ uses 91 (VAIO) and 93 (.49) SETTINGS = ''' Radios de Vigo true 0 {home}radio.m3u true 1 false 0 0 0 {home}logos/ false 0 true false '''.format(home=HOME) def log(msg): xbmc.log('[{}] {}'.format(ADDON_ID, msg), xbmc.LOGINFO) def rpc(method, **params): return json.loads(xbmc.executeJSONRPC(json.dumps( {'jsonrpc': '2.0', 'id': 1, 'method': method, 'params': params}))) def read(path): try: with io.open(path, 'r', encoding='utf-8') as f: return f.read() except (IOError, OSError): return None def write(path, content): tmp = path + '.tmp' with io.open(tmp, 'w', encoding='utf-8', newline='') as f: f.write(content) os.replace(tmp, path) def instance_file(pvr_dir): """Our instance file: the one that already reads radio.m3u, else the first free number from FIRST_INSTANCE on.""" for path in glob.glob(os.path.join(pvr_dir, 'instance-settings-*.xml')): if HOME + 'radio.m3u' in (read(path) or ''): return path n = FIRST_INSTANCE while os.path.exists(os.path.join(pvr_dir, 'instance-settings-{}.xml'.format(n))): n += 1 return os.path.join(pvr_dir, 'instance-settings-{}.xml'.format(n)) def restart_iptv_simple(): for enabled in (False, True): rpc('Addons.SetAddonEnabled', addonid='pvr.iptvsimple', enabled=enabled) xbmc.sleep(3000) def main(): monitor, player = xbmc.Monitor(), xbmc.Player() profile = xbmcvfs.translatePath(ADDON.getAddonInfo('profile')) pvr_dir = xbmcvfs.translatePath('special://profile/addon_data/pvr.iptvsimple/') for d in (profile, pvr_dir): if not os.path.isdir(d): os.makedirs(d) path = instance_file(pvr_dir) if read(path) != SETTINGS: write(path, SETTINGS) log('wrote ' + path) numbers_set = os.path.join(profile, 'numbers-set') if not os.path.exists(numbers_set): # Show the stations' own numbers (Vigo ones are their FM frequency). # With more than one IPTV Simple instance Kodi ignores them unless # "always" is on too; that also keeps KodiMov+'s TV numbers. for setting in ('pvrmanager.usebackendchannelnumbers', 'pvrmanager.usebackendchannelnumbersalways'): rpc('Settings.SetSettingValue', setting=setting, value=True) write(numbers_set, '') log('turned on backend channel numbers') m3u = read(xbmcvfs.translatePath(HOME + 'radio.m3u')) or '' state = hashlib.sha1((SETTINGS + m3u).encode('utf-8')).hexdigest() if read(os.path.join(profile, 'state')) == state: return while player.isPlaying(): # restarting IPTV Simple stops the radio or TV playing if monitor.waitForAbort(10): return if monitor.waitForAbort(5): return log('station list or settings changed, restarting IPTV Simple') restart_iptv_simple() write(os.path.join(profile, 'state'), state) if __name__ == '__main__': main()