128 lines
4.4 KiB
Python
128 lines
4.4 KiB
Python
# -*- 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 = '''<settings version="2">
|
|
<setting id="kodi_addon_instance_name">Radios de Vigo</setting>
|
|
<setting id="kodi_addon_instance_enabled">true</setting>
|
|
<setting id="m3uPathType">0</setting>
|
|
<setting id="m3uPath">{home}radio.m3u</setting>
|
|
<setting id="m3uUrl" default="true" />
|
|
<setting id="m3uCache" default="true">true</setting>
|
|
<setting id="startNum" default="true">1</setting>
|
|
<setting id="numberByOrder" default="true">false</setting>
|
|
<setting id="m3uRefreshMode" default="true">0</setting>
|
|
<setting id="epgPathType">0</setting>
|
|
<setting id="epgPath" default="true" />
|
|
<setting id="epgUrl" default="true" />
|
|
<setting id="logoPathType">0</setting>
|
|
<setting id="logoPath">{home}logos/</setting>
|
|
<setting id="useLogosLocalPathOnly" default="true">false</setting>
|
|
<setting id="logoFromEpg">0</setting>
|
|
<setting id="useFFmpegReconnect" default="true">true</setting>
|
|
<setting id="useInputstreamAdaptiveforHls" default="true">false</setting>
|
|
</settings>
|
|
'''.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()
|