- Migliorie Videoteca

- Finestra selezione server
 - Fix Autorenumber (sincronizzazione fra videoteca a canali)
 - Fix Autoplay
This commit is contained in:
Alhaziel01
2021-05-29 18:17:40 +02:00
parent dc2140f2ca
commit 01059eb373
10 changed files with 564 additions and 488 deletions

View File

@@ -49,16 +49,22 @@ def start(itemlist, item):
if not blacklisted_servers: blacklisted_servers = []
from core import servertools
favorite_servers = config.get_setting('favorites_servers_list', server='servers')
servers_list = list(servertools.get_servers_list().items())
for server, server_parameters in servers_list:
if config.get_setting('favorites_servers_list', server=server):
if config.get_setting('favorites_servers_list', server=server) and server.lower() not in favorite_servers:
favorite_servers.append(server.lower())
if not favorite_servers:
config.set_setting('favorites_servers_list', [], server='servers')
favorite_servers = []
else:
favorite_servers = list(set(favorite_servers) - set(blacklisted_servers))
s_list = []
for s in favorite_servers:
if s not in blacklisted_servers:
s_list.append(s)
favorite_servers = s_list
# Save the current value of "Action and Player Mode" in preferences
user_config_setting_action = config.get_setting("default_action")
@@ -75,6 +81,7 @@ def start(itemlist, item):
# 2: Servers only
# 3: Only qualities
# 4: Do not order
if config.get_setting('favorites_servers') and favorite_servers and config.get_setting('default_action'):
priority = 0 # 0: Servers and qualities or 1: Qualities and servers
elif config.get_setting('favorites_servers') and favorite_servers:
@@ -87,7 +94,6 @@ def start(itemlist, item):
if config.get_setting('default_action') == 1:
quality_list.reverse()
favorite_quality = quality_list
for item in itemlist:
autoplay_elem = dict()
b_dict = dict()
@@ -109,7 +115,7 @@ def start(itemlist, item):
# if the server and the quality are not in the favorites lists or the url is repeated, we discard the item
if item.server.lower() not in favorite_servers or item.quality.lower() not in favorite_quality or item.url in url_list_valid:
item.type_b = True
item.play_from = base_item.play_from
item.window = base_item.window
b_dict['videoitem']= item
autoplay_b.append(b_dict)
continue
@@ -121,7 +127,7 @@ def start(itemlist, item):
# if the server is not in the favorites list or the url is repeated, we discard the item
if item.server.lower() not in favorite_servers or item.url in url_list_valid:
item.type_b = True
item.play_from = base_item.play_from
item.window = base_item.window
b_dict['videoitem'] = item
autoplay_b.append(b_dict)
continue
@@ -132,7 +138,7 @@ def start(itemlist, item):
# if the quality is not in the favorites list or the url is repeated, we discard the item
if item.quality.lower() not in favorite_quality or item.url in url_list_valid:
item.type_b = True
item.play_from = base_item.play_from
item.window = base_item.window
b_dict['videoitem'] = item
autoplay_b.append(b_dict)
continue
@@ -141,14 +147,14 @@ def start(itemlist, item):
else: # Do not order
# if the url is repeated, we discard the item
item.play_from = base_item.play_from
item.window = base_item.window
if item.url in url_list_valid:
continue
# If the item reaches here we add it to the list of valid urls and to autoplay_list
url_list_valid.append(item.url)
item.plan_b=True
item.play_from = base_item.play_from
item.window = base_item.window
autoplay_elem['videoitem'] = item
autoplay_list.append(autoplay_elem)
@@ -241,6 +247,7 @@ def start(itemlist, item):
play_item = base_item.clone(**videoitem.__dict__)
platformtools.play_video(play_item, autoplay=True)
else:
videoitem.window = base_item.window
# If it doesn't come from the video library, just play
platformtools.play_video(videoitem, autoplay=True)
except:
@@ -266,6 +273,7 @@ def start(itemlist, item):
if autoplay_elem == autoplay_list[-1]:
platformtools.dialog_notification('AutoPlay', config.get_localized_string(60072) % name)
itemlist = [s['videoitem'] for s in autoplay_list]
else:
platformtools.dialog_notification(config.get_localized_string(60074), config.get_localized_string(60075))

View File

@@ -74,7 +74,7 @@ class InfoLabels(dict):
# Complete with the rest of the codes
for scr in ['tmdb_id', 'tvdb_id', 'noscrap_id']:
if scr in list(super(InfoLabels, self).keys()) and super(InfoLabels, self).__getitem__(scr):
value = "%s%s" % (scr[:-2], super(InfoLabels, self).__getitem__(scr))
value = "%s" % (super(InfoLabels, self).__getitem__(scr))
code.append(value)
# Option to add a code of the random type

View File

@@ -1255,7 +1255,7 @@ def server(item, data='', itemlist=[], headers='', AutoPlay=True, CheckLinks=Tru
try:
if AutoPlay and item.contentChannel not in ['downloads', 'videolibrary']:
autoplay.start(verifiedItemlist, item)
verifiedItemlist = autoplay.start(verifiedItemlist, item)
except:
import traceback
logger.error(traceback.format_exc())
@@ -1265,7 +1265,7 @@ def server(item, data='', itemlist=[], headers='', AutoPlay=True, CheckLinks=Tru
videolibrary(verifiedItemlist, item)
if Download:
download(verifiedItemlist, item, function_level=3)
# if item.contentChannel == 'videolibrary' or not config.get_setting('autoplay'):
return verifiedItemlist

View File

@@ -5,14 +5,15 @@
#from builtins import str
# from specials import videolibrary
from specials import videolibrary
from platformcode.dbconverter import addVideo
from platformcode.xbmc_videolibrary import execute_sql_kodi
import sys
PY3 = False
if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
if PY3:
from concurrent import futures
else:
from concurrent_py2 import futures
if PY3: from concurrent import futures
else: from concurrent_py2 import futures
import errno, math, traceback, re, os
@@ -22,6 +23,7 @@ from lib import generictools
from platformcode import config, logger, platformtools
from platformcode.autorenumber import RENUMBER
from core.videolibrarydb import videolibrarydb
from platformcode.dbconverter import add_video
FOLDER_MOVIES = config.get_setting("folder_movies")
FOLDER_TVSHOWS = config.get_setting("folder_tvshows")
@@ -41,7 +43,8 @@ quality_order = ['4k', '2160p', '2160', '4k2160p', '4k2160', '4k 2160p', '4k 216
video_extensions = ['3g2', '3gp', '3gp2', 'asf', 'avi', 'divx', 'flv', 'iso', 'm4v', 'mk2', 'mk3d', 'mka', 'mkv', 'mov', 'mp4', 'mp4a', 'mpeg', 'mpg', 'ogg', 'ogm', 'ogv', 'qt', 'ra', 'ram', 'rm', 'ts', 'vob', 'wav', 'webm', 'wma', 'wmv']
subtitle_extensions = ['srt', 'idx', 'sub', 'ssa', 'ass']
immage_extensions = ['jpg', 'png']
image_extensions = ['.jpg', '.jpeg', '.png']
library_extension = ['.nfo', '.strm', '.json']
def read_nfo(path_nfo, item=None):
@@ -174,6 +177,8 @@ def save_movie(item, silent=False):
base_name = set_base_name(item, _id)
path = filetools.join(MOVIES_PATH, base_name)
local_files = get_local_files(path, item)
# check if path already exist
if not filetools.exists(path):
logger.debug("Creating movie directory:" + path)
@@ -181,7 +186,7 @@ def save_movie(item, silent=False):
logger.debug("Could not create directory")
videolibrarydb.close()
return 0, 0, -1, path
# try:
try:
# set nfo and strm paths
nfo_path = filetools.join(base_name, "{}.nfo".format(base_name))
strm_path = filetools.join(base_name, "{}.strm".format(base_name))
@@ -290,7 +295,7 @@ def save_movie(item, silent=False):
filetools.write(filetools.join(MOVIES_PATH, movie_item.nfo_path), head_nfo)
# create strm file if it does not exist
if not strm_exists:
if not strm_exists and not local_files:
logger.debug("Creating .strm: " + strm_path)
item_strm = Item(channel='videolibrary', action='play_from_library', strm_path=movie_item.strm_path, contentType='movie', contentTitle=item.contentTitle, videolibrary_id=movie_item.videolibrary_id)
strm_exists = filetools.write(filetools.join(MOVIES_PATH, movie_item.strm_path), '{}?{}'.format(addon_name, item_strm.tourl()))
@@ -315,24 +320,30 @@ def save_movie(item, silent=False):
else:
channels[item.channel] = [item]
if local_files.get('db') or local_files.get('internal'):
if local_files.get('db'):
channels['local'] = local_files['db'][0]
elif local_files.get('internal'):
channels['local'] = local_files['internal'][0]
moviedb['item'] = movie_item
moviedb['channels'] = channels
videolibrarydb['movie'][_id] = moviedb
# except:
# failed += 1
except:
failed += 1
videolibrarydb.close()
# Only if movie_item and .strm exist we continue
if movie_item and strm_exists:
if failed == 0:
if not silent:
p_dialog.update(100, item.contentTitle)
p_dialog.close()
# Update Kodi Library
from platformcode.dbconverter import add_video
add_video(movie_item)
# from platformcode.dbconverter import add_video
# add_video(movie_item)
# if config.is_xbmc() and config.get_setting("videolibrary_kodi") and not silent and inserted:
# from platformcode.xbmc_videolibrary import update
# update(MOVIES_PATH)
@@ -359,10 +370,11 @@ def update_renumber_options(item):
def add_renumber_options(item):
from core import jsontools
# from core.support import dbg;dbg()
ret = None
filename = filetools.join(config.get_data_path(), "settings_channels", item.channel + '_data.json')
json_file = jsontools.load(filetools.read(filename))
if item.renumber and not json_file.get(RENUMBER,{}).get(item.fulltitle):
check_renumber_options(item)
if RENUMBER in json_file:
json = json_file[RENUMBER]
if item.fulltitle in json:
@@ -371,12 +383,10 @@ def add_renumber_options(item):
def check_renumber_options(item):
from platformcode.autorenumber import load, write
for key in item.channel_prefs:
if RENUMBER in item.channel_prefs[key]:
item.channel = key
if item.renumber:
json = load(item)
if not json or item.fulltitle not in json:
json[item.fulltitle] = item.channel_prefs[key][RENUMBER]
json[item.fulltitle] = item.renumber
write(item, json)
# head_nfo, tvshow_item = read_nfo(filetools.join(item.context[0]['nfo']))
@@ -404,7 +414,7 @@ def save_tvshow(item, episodelist, silent=False):
overwritten = 0
failed = 0
path = ""
# support.dbg()
# If at this point we do not have a title or code, we leave
if not (item.contentSerieName or item.infoLabels['code']) or not item.channel:
logger.debug("NOT FOUND contentSerieName or code")
@@ -443,6 +453,8 @@ def save_tvshow(item, episodelist, silent=False):
base_name = set_base_name(item, _id)
path = filetools.join(TVSHOWS_PATH, base_name)
local_files = get_local_files(path, item)
# check if path already exist
if not filetools.exists(path):
logger.debug("Creating tv show directory:" + path)
@@ -496,7 +508,9 @@ def save_tvshow(item, episodelist, silent=False):
if not tvshow_item.lang_list: tvshow_item.lang_list = []
remove_host(item)
item.renumber = add_renumber_options(item)
# write on db
if item.channel in channels and item.channel != 'download':
channels_url = [u.url for u in channels[item.channel]]
@@ -520,7 +534,7 @@ def save_tvshow(item, episodelist, silent=False):
# Save the episodes
logger.debug()
inserted, overwritten, failed = save_episodes(tvshow_item, episodelist, extra_info, item.host, silent=silent)
inserted, overwritten, failed = save_episodes(tvshow_item, episodelist, extra_info, item.host, local_files, silent=silent)
videolibrarydb.close()
# if config.is_xbmc() and config.get_setting("videolibrary_kodi") and not silent and inserted:
# # from platformcode.dbconverter import add_video
@@ -531,27 +545,9 @@ def save_tvshow(item, episodelist, silent=False):
return inserted, overwritten, failed, path
def save_episodes(item, episodelist, extra_info, host, silent=False):
"""
saves in the indicated path all the chapters included in the episodelist
@type Item: str
@param path: path to save the episodes
@type episodelist: list
@param episodelist: list of items that represent the episodes to be saved.
@type serie: item
@param serie: series from which to save the episodes
@type silent: bool
@param silent: sets whether notification is displayed
@param overwrite: allows to overwrite existing files
@type overwrite: bool
@rtype inserted: int
@return: the number of episodes inserted
@rtype overwritten: int
@return: the number of overwritten episodes
@rtype failed: int
@return: the number of failed episodes
"""
# support.dbg()
def save_episodes(item, episodelist, extra_info, host, local_files, silent=False):
logger.debug()
def save_episode(item, episodes, e):
inserted = 0
overwritten = 0
@@ -561,7 +557,6 @@ def save_episodes(item, episodelist, extra_info, host, silent=False):
season_episode = scrapertools.get_season_and_episode(e.title)
if season_episode:
strm_path = filetools.join(item.base_name, "{}.strm".format(season_episode))
@@ -619,20 +614,40 @@ def save_episodes(item, episodelist, extra_info, host, silent=False):
epchannels[e.channel] = [e]
overwritten += 1
# add local files
if list(local_files.values()):
epchannels['local'] = {}
if season_episode in list(local_files.get('db',{}).keys()):
epchannels['local']['db'] = local_files['db'][season_episode]
if season_episode in list(local_files.get('internal',{}).keys()):
epchannels['local']['internal'] = local_files['db'][season_episode]
logger.debug('LOCALS', epchannels)
# if season_episode in list(local_files.get('external',{}).keys()):
# epchannels['external'] = local_files['db'][season_episode]
# Delete the local key if local files no longer exist
elif 'local' in epchannels:
del epchannels['local']
episode['channels'] = epchannels
except:
logger.error(traceback.format_exc())
failed += 1
# add strm_file if episode is not present in db or inside videolibrary path
if not filetools.exists(filetools.join(TVSHOWS_PATH, strm_path)):
logger.debug("Creating .strm: " + strm_path)
item_strm = Item(channel='videolibrary', action='play_from_library', strm_path=strm_path, contentType='episode', videolibrary_id=episode_item.videolibrary_id, contentSeason = episode_item.contentSeason, contentEpisodeNumber = episode_item.contentEpisodeNumber,)
filetools.write(filetools.join(TVSHOWS_PATH, strm_path), '{}?{}'.format(addon_name, item_strm.tourl()))
# if not filetools.exists(filetools.join(TVSHOWS_PATH, nfo_path)):
# filetools.write(filetools.join(TVSHOWS_PATH, nfo_path), head_nfo)
except:
logger.error(traceback.format_exc())
failed += 1
# update db if episode added
if failed == 0 and config.get_setting('kod_scraper'):
add_video(episode_item)
return item, episode, season_episode, e.contentLanguage, inserted, overwritten, failed
def save_season(item, seasons, s, w):
def save_season(item, s, w):
tmdb_info = tmdb.Tmdb(id_Tmdb = item.infoLabels['tmdb_id'], search_type='tv')
seasoninfo = tmdb.get_season_dic(tmdb_info.get_season(s))
infoLabels = {}
@@ -664,9 +679,14 @@ def save_episodes(item, episodelist, extra_info, host, silent=False):
return s, season_item
logger.debug()
def watched_season(s):
w = 0
s_ep = [e['item'] for e in episodes.values() if e['item'].contentSeason == s]
w_ep = [e for e in s_ep if e.infoLabels.get('playcount') > 0]
if len(s_ep) == len(w_ep): w = 1
return s, w
# from core import tmdb
# No episode list, nothing to save
if not len(episodelist):
logger.debug("There is no episode list, we go out without creating strm")
@@ -688,22 +708,8 @@ def save_episodes(item, episodelist, extra_info, host, silent=False):
try: t = float(100) / len(episodelist)
except: t = 0
# support.dbg()
# for i, e in enumerate(episodelist):
# item, episode, season_episode, lang, I, O, F = save_episode(item, episodes, e)
# inserted += I
# overwritten += O
# failed += F
# if episode:
# episodes[season_episode] = episode
# e = episode['item']
# if not e.contentSeason in current_seasons: current_seasons.append(e.contentSeason)
# if not lang: lang = item.contentLanguage if item.contentLanguage else 'ITA'
# if not lang in item.lang_list: item.lang_list.append(lang)
# if not silent:
# p_dialog.update(int(math.ceil(i * t)), message=e.title)
i = 0
# save episodes Thread
with futures.ThreadPoolExecutor() as executor:
itlist = [executor.submit(save_episode, item, episodes, e) for e in episodelist]
for res in futures.as_completed(itlist):
@@ -722,40 +728,33 @@ def save_episodes(item, episodelist, extra_info, host, silent=False):
i += 1
p_dialog.update(int(math.ceil(i * t)), message=e.title)
def watched_season(s):
w = 0
s_ep = [e['item'] for e in episodes.values() if e['item'].contentSeason == s]
w_ep = [e for e in s_ep if e.infoLabels.get('playcount') > 0]
if len(s_ep) == len(w_ep): w = 1
return s, w
# set seasons as watched
add_seasons = {}
with futures.ThreadPoolExecutor() as executor:
itlist = [executor.submit(watched_season, s) for s in current_seasons]
for res in futures.as_completed(itlist):
add_seasons[res.result()[0]] = res.result()[1]
for s in current_seasons:
watched = 0
s_ep = [e['item'] for e in episodes.values() if e['item'].contentSeason == s]
w_ep = [e for e in s_ep if e.infoLabels.get('playcount') > 0]
if len(s_ep) == len(w_ep): watched = 1
add_seasons[s] = watched
# save seasons
with futures.ThreadPoolExecutor() as executor:
itlist = [executor.submit(save_season, item, seasons, s, w) for s, w in add_seasons.items()]
itlist = [executor.submit(save_season, item, s, w) for s, w in add_seasons.items()]
for res in futures.as_completed(itlist):
if res.result():
s, season_item = res.result()
seasons[s] = season_item
# Add to Kodi DB if Kod is set to add information
if config.get_setting('kod_scraper'):
add_video(season_item)
if not silent:
# update tvshow info if forced
if len(item.lang_list) > 1:
item.prefered_lang = item.lang_list[platformtools.dialog_select(config.get_localized_string(70246), item.lang_list)]
else:
item.prefered_lang = item.lang_list[0]
tvshowdb = videolibrarydb['tvshow'][item.videolibrary_id]
tvshowdb['item'] = item
videolibrarydb['tvshow'][item.videolibrary_id] = tvshowdb
@@ -772,89 +771,7 @@ def save_episodes(item, episodelist, extra_info, host, silent=False):
def config_local_episodes_path(path, item, silent=False):
logger.debug(item)
from platformcode.xbmc_videolibrary import search_local_path
local_episodes_path=search_local_path(item)
if not local_episodes_path:
title = item.contentSerieName if item.contentSerieName else item.fulltitle
if not silent:
silent = platformtools.dialog_yesno(config.get_localized_string(30131), config.get_localized_string(80044) % title)
if silent:
if config.is_xbmc() and not config.get_setting("videolibrary_kodi"):
platformtools.dialog_ok(config.get_localized_string(30131), config.get_localized_string(80043))
local_episodes_path = platformtools.dialog_browse(0, config.get_localized_string(80046))
if local_episodes_path == '':
logger.debug("User has canceled the dialog")
return -2, local_episodes_path
elif path in local_episodes_path:
platformtools.dialog_ok(config.get_localized_string(30131), config.get_localized_string(80045))
logger.debug("Selected folder is the same of the TV show one")
return -2, local_episodes_path
if local_episodes_path:
# import artwork
artwork_extensions = ['.jpg', '.jpeg', '.png']
files = filetools.listdir(local_episodes_path)
for file in files:
if os.path.splitext(file)[1] in artwork_extensions:
filetools.copy(filetools.join(local_episodes_path, file), filetools.join(path, file))
return 0, local_episodes_path
def process_local_episodes(local_episodes_path, path):
logger.debug()
sub_extensions = ['.srt', '.sub', '.sbv', '.ass', '.idx', '.ssa', '.smi']
artwork_extensions = ['.jpg', '.jpeg', '.png']
extensions = sub_extensions + artwork_extensions
local_episodes_list = []
files_list = []
for root, folders, files in filetools.walk(local_episodes_path):
for file in files:
if os.path.splitext(file)[1] in extensions:
continue
season_episode = scrapertools.get_season_and_episode(file)
if season_episode == "":
continue
local_episodes_list.append(season_episode)
files_list.append(file)
nfo_path = filetools.join(path, "tvshow.nfo")
head_nfo, item_nfo = read_nfo(nfo_path)
# if a local episode has been added, overwrites the strm
for season_episode, file in zip(local_episodes_list, files_list):
if not season_episode in item_nfo.local_episodes_list:
filetools.write(filetools.join(path, season_episode + '.strm'), filetools.join(root, file))
# if a local episode has been removed, deletes the strm
for season_episode in set(item_nfo.local_episodes_list).difference(local_episodes_list):
filetools.remove(filetools.join(path, season_episode + '.strm'))
# updates the local episodes path and list in the nfo
if not local_episodes_list:
item_nfo.local_episodes_path = ''
item_nfo.local_episodes_list = sorted(set(local_episodes_list))
filetools.write(nfo_path, head_nfo + item_nfo.tojson())
def get_local_content(path):
logger.debug()
local_episodelist = []
for root, folders, files in filetools.walk(path):
for file in files:
season_episode = scrapertools.get_season_and_episode(file)
if season_episode == "" or filetools.exists(filetools.join(path, "%s.strm" % season_episode)):
continue
local_episodelist.append(season_episode)
local_episodelist = sorted(set(local_episodelist))
return local_episodelist
def add_movie(item):
@@ -881,21 +798,24 @@ def add_movie(item):
# If you do it in "Enter another name", TMDB will automatically search for the new title
# If you do it in "Complete Information", it partially changes to the new title, but does not search TMDB. We have to do it
# If the second screen is canceled, the variable "scraper_return" will be False. The user does not want to continue
item = generictools.update_title(item) # We call the method that updates the title with tmdb.find_and_set_infoLabels
#if item.tmdb_stat:
# del item.tmdb_stat # We clean the status so that it is not recorded in the Video Library
if item:
new_item = item.clone(action="findvideos")
inserted, overwritten, failed, path = save_movie(new_item)
if failed == 0:
platformtools.dialog_notification(config.get_localized_string(30131),
config.get_localized_string(30135) % new_item.contentTitle) # 'has been added to the video library'
platformtools.dialog_notification(config.get_localized_string(30131), config.get_localized_string(30135) % new_item.contentTitle) # 'has been added to the video library'
else:
filetools.rmdirtree(path)
platformtools.dialog_ok(config.get_localized_string(30131),
config.get_localized_string(60066) % new_item.contentTitle) # "ERROR, the movie has NOT been added to the video library")
platformtools.dialog_ok(config.get_localized_string(30131), config.get_localized_string(60066) % new_item.contentTitle) # "ERROR, the movie has NOT been added to the video library")
movies = videolibrarydb['movie']
_id = get_id(item)
if _id in list(movies.keys()):
del movies[_id]
videolibrarydb['movie'] = movies
videolibrarydb.close()
def add_tvshow(item, channel=None):
"""
@@ -1026,18 +946,6 @@ def get_id(item):
return item.infoLabels.get('tmdb_id')
def get_local_files(item):
included_files = {}
# search media files in Videolibrary Folder
for root, folder, files in filetools.walk(filetools.join(TVSHOWS_PATH,item.base_name)):
# for folder in folders:
for f in files:
if f.split('.')[-1] in video_extensions:
s, e = scrapertools.find_single_match(f, r'[Ss]?(\d+)(?:x|_|\s+)[Ee]?[Pp]?(\d+)')
included_files['{}x{}'.format(s,e.zfill(2))] = f
if included_files:
return included_files, 1
def get_fanart_tv(item, set='', ret={}):
def set_dict(l):
d = {}
@@ -1078,3 +986,40 @@ def get_fanart_tv(item, set='', ret={}):
get_fanart_tv(it, 'set', ret)
return ret
def get_local_files(path, item):
# check if movie or season already exist in path or db
excluded_extensions = subtitle_extensions + image_extensions + library_extension
local_files = {}
if item.contentType == 'movies':
# search on path:
internal = [f for f in filetools.listdir(path) if not (f.endswith('nfo') or f.endswith('strm') or f.endswith('json'))]
if internal:
local_files['internal'] = internal
# search on db:
sql = 'SELECT c22, uniqueid_value FROM movie_view WHERE uniqueid_type != "kod"'
n, records = execute_sql_kodi(sql)
if records:
local_files['db']= [r[0] for r in records if r[1] in item.infoLabels['code']]
else:
# search on path:
internal = {scrapertools.get_season_and_episode[f]:f for f in filetools.listdir(path) if os.path.splitext(f)[1] not in excluded_extensions}
if internal:
local_files['internal'] = internal
# search on db:
sql = 'SELECT idShow, uniqueid_value FROM tvshow_view WHERE uniqueid_type != "kod"'
n, records = execute_sql_kodi(sql)
if records:
for r in records:
if r[1] in item.infoLabels['code']:
sql = 'SELECT strPath, strFilename From episode_view WHERE idShow = {}'.format(r[0])
n, ep_records = execute_sql_kodi(sql)
if ep_records:
local_files['db'] = {scrapertools.get_season_and_episode(e[1]):e[0]+e[1] for e in ep_records if not e[1].endswith('strm')}
break
return local_files

View File

@@ -94,7 +94,7 @@ def start(itemlist, item=None):
if item.channel in ['autorenumber']:
item.channel = item.from_channel
item.action = item.from_action
item.renumber = True
item.setrenumber = True
busy(True)
itemlist = find_episodes(item)
busy(False)
@@ -114,11 +114,12 @@ class autorenumber():
if match(self.itemlist[0].title, patron=r'[Ss]?(\d+)(?:x|_|\s+)[Ee]?[Pp]?(\d+)').match:
item.exit = True
return
elif self.item.channel in self.item.channel_prefs and RENUMBER in self.item.channel_prefs[item.channel] and self.title not in self.renumberdict:
elif (self.item.channel in self.item.channel_prefs and RENUMBER in self.item.channel_prefs[item.channel] and self.title not in self.renumberdict) or self.item.renumber:
from core.videolibrarytools import check_renumber_options
from specials.videolibrary import update_videolibrary
check_renumber_options(self.item)
update_videolibrary(self.item)
self.series = self.renumberdict.get(self.title,{})
self.id = self.series.get(ID, 0)
self.episodes = self.series.get(EPISODES,{})
@@ -128,9 +129,9 @@ class autorenumber():
self.manual = self.series.get(MANUALMODE, False)
self.specials = self.series.get(SPECIALEPISODES, {})
if self.id and self.episodes and self.season >= 0 and self.episode >= 0:
if self.item.renumber: self.config()
if self.item.setrenumber: self.config()
else:self.renumber()
elif self.auto or self.item.renumber:
elif self.auto or self.item.setrenumber:
self.episodes = {}
self.config()
else:
@@ -161,7 +162,7 @@ class autorenumber():
else:self.item = platformtools.dialog_info(self.item, 'tmdb')
# Rinumerazione Automatica
if (not self.id and self.auto) or self.item.renumber:
if (not self.id and self.auto) or self.item.setrenumber:
self.id = self.item.infoLabels['tmdb_id'] if 'tmdb_id' in self.item.infoLabels else 0
if self.id:
self.series = {ID: self.id}
@@ -183,7 +184,7 @@ class autorenumber():
item.title = '{} - {}'.format(typo(self.episodes[number], 'bold'), item.title)
item.contentSeason = int(self.episodes[number].split('x')[0])
item.contentEpisodeNumber = int(self.episodes[number].split('x')[1])
if not self.item.renumber and self.itemlist:
if not self.item.setrenumber and self.itemlist:
with futures.ThreadPoolExecutor() as executor:
renumber_list = [executor.submit(sub_thread, item,) for item in self.itemlist]
@@ -225,8 +226,8 @@ class autorenumber():
count += 1
self.epdict[count] = '{}x{:02d}'.format(s, e + fe - 1)
if self.item.renumber or self.manual:
self.item.renumber = False
if self.item.setrenumber or self.manual:
self.item.setrenumber = False
self.season, self.episode, self.manual, self.specials, Manual, Exit = SelectreNumeration(self, itemlist)
if Exit:
self.item.exit = True

View File

@@ -446,13 +446,11 @@ def play_from_library(item):
# logger.debug("item: \n" + item.tostring('\n'))
# from core.support import dbg; dbg()
import xbmc
import xbmc, xbmcgui, xbmcplugin
item.window_type = config.get_setting("window_type", "videolibrary") if config.get_setting('next_ep') < 3 and item.contentType != 'movie' else 1
if xbmc.getCondVisibility('Window.IsMedia') and not item.window_type == 1:
import xbmcgui, xbmcplugin
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, xbmcgui.ListItem(path=os.path.join(config.get_runtime_path(), "resources", "kod.mp4")))
xbmc.Player().stop()
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, xbmcgui.ListItem(path=os.path.join(config.get_runtime_path(), "resources", "kod.mp4")))
if xbmc.getCondVisibility('Window.IsMedia') and not item.window_type == 1:
if item.contentType == 'episode':
it = videolibrarydb.videolibrarydb[item.contentType][item.videolibrary_id]['{}x{:02d}'.format(item.infoLabels['season'], item.infoLabels['episode'])]
else:
@@ -461,82 +459,3 @@ def play_from_library(item):
videolibrarydb.videolibrarydb.close()
else:
return videolibrary.findvideos(item)
# else:
# xbmc.executebuiltin('ActivateWindow(10025,' + sys.argv[0] + "?" + item.tourl() + ")")
# itemlist = videolibrary.findvideos(it)
# platformtools.render_items(itemlist, item)
# itemlist=[]
# item.fromLibrary = True
# item.window = True
# logger.debug()
# # Modify the action (currently the video library needs "findvideos" since this is where the sources are searched
# item.action = "findvideos"
# window_type = config.get_setting("window_type", "videolibrary") if config.get_setting('next_ep') < 3 and item.contentType != 'movie' else 1
# # and launch kodi again
# if xbmc.getCondVisibility('Window.IsMedia') and not window_type == 1:
# xbmc.executebuiltin("Container.Update(" + sys.argv[0] + "?" + item.tourl() + ")")
# else:
# # Pop-up window
# from specials import videolibrary
# from core.channeltools import get_channel_parameters
# p_dialog = platformtools.dialog_progress_bg(config.get_localized_string(20000), config.get_localized_string(60683))
# p_dialog.update(0, '')
# item.play_from = 'window'
# itemlist = videolibrary.findvideos(item)
# p_dialog.update(100, ''); sleep(0.5); p_dialog.close()
# played = False
# # The number of links to show is limited
# if config.get_setting("max_links", "videolibrary") != 0: itemlist = limit_itemlist(itemlist)
# # The list of links is slightly "cleaned"
# if config.get_setting("replace_VD", "videolibrary") == 1: itemlist = reorder_itemlist(itemlist)
# # from core.support import dbg;dbg()
# if len(itemlist) > 0:
# reopen = False
# # from core.support import dbg;dbg()
# while not xbmc.Monitor().abortRequested():
# played = True
# # if config.get_setting('next_ep') == 3 and xbmc.Player().playnext:
# # return
# # The user chooses the mirror
# if not platformtools.is_playing():
# if config.get_setting('next_ep') == 3:
# xbmc.sleep(500)
# if platformtools.is_playing():
# return
# # if config.get_setting('autoplay') or reopen:
# # played_time = get_played_time(item)
# # if not played_time and played:
# # return
# options = []
# selection_implementation = 0
# for item in itemlist:
# item.thumbnail = config.get_online_server_thumb(item.server)
# quality = '[B][' + item.quality + '][/B]' if item.quality else ''
# if item.server:
# path = filetools.join(config.get_runtime_path(), 'servers', item.server.lower() + '.json')
# name = jsontools.load(open(path, "rb").read())['name']
# if name.startswith('@'): name = config.get_localized_string(int(name.replace('@','')))
# it = xbmcgui.ListItem('\n[B]%s[/B] %s - %s [%s]' % (name, quality, item.contentTitle, get_channel_parameters(item.channel).get('title', '')))
# it.setArt({'thumb':item.thumbnail})
# options.append(it)
# else:
# selection_implementation += 1
# # The selection window opens
# if (item.contentSerieName and item.contentSeason and item.contentEpisodeNumber): head = ("%s - %sx%s | %s" % (item.contentSerieName, item.contentSeason, item.contentEpisodeNumber, config.get_localized_string(30163)))
# else: head = config.get_localized_string(30163)
# selection = platformtools.dialog_select(head, options, preselect= -1, useDetails=True)
# if selection == -1:
# return
# else:
# item = videolibrary.play(itemlist[selection + selection_implementation])[0]
# platformtools.play_video(item)
# reopen = True
# if (platformtools.is_playing() and item.action) or item.server == 'torrent' or config.get_setting('autoplay'): break

View File

@@ -744,7 +744,7 @@ def play_video(item, strm=False, force_direct=False, autoplay=False):
xlistitem.setProperty("inputstream.adaptive.license_key", item.license)
xlistitem.setMimeType('application/dash+xml')
if force_direct: item.play_from = 'window'
if force_direct: item.window = True
set_player(item, xlistitem, mediaurl, view, strm)
return True
@@ -1085,7 +1085,6 @@ def get_video_seleccionado(item, seleccion, video_urls, autoplay=False):
def set_player(item, xlistitem, mediaurl, view, strm):
logger.debug()
# from core.support import dbg;dbg()
item.options = {'strm':False}
# logger.debug("item:\n" + item.tostring('\n'))

View File

@@ -95,10 +95,12 @@ def mark_auto_as_watched(item):
while platformtools.is_playing():
xbmc.sleep(100)
if not show_server and item.play_from != 'window' and not item.no_return:
if not show_server and not item.window and not item.no_return:
xbmc.sleep(700)
xbmc.executebuiltin('Action(ParentDir)')
# xbmc.sleep(500)
else:
videolibrary.serverwindow.close()
if marked:
from specials import videolibrary
@@ -1384,7 +1386,7 @@ def next_ep(item):
contentType= 'episode',
infoLabels= {'episode': episode, 'mediatype': 'episode', 'season': season, 'title': next_ep},
strm_path= filetools.join(base_path, next_file),
play_from = item.play_from)
window = item.window)
global INFO
INFO = filetools.join(path, next_file.replace("strm", "nfo"))

View File

@@ -0,0 +1,185 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<window>
<zorder>0.52</zorder>
<coordinates>
<left>0</left>
<top>0</top>
</coordinates>
<controls>
<control type="group">
<description>Servers Group</description>
<animation type="WindowOpen" reversible="false">
<effect type="fade" delay="160" end="100" time="200" />
</animation>
<animation type="WindowClose" reversible="false">
<effect type="fade" delay="300" start="100" end="0" time="200" />
</animation>
<control type="image">
<description>Window Background</description>
<width>100%</width>
<height>100%</height>
<texture colordiffuse="FF232323">white.png</texture>
</control>
<control type="image">
<description>Fanart</description>
<width>100%</width>
<height>100%</height>
<aspectratio>scale</aspectratio>
<texture colordiffuse="FF555555">$INFO[Container(100).ListItem.Art(fanart)]</texture>
</control>
<control type="image">
<description>Poster</description>
<top>0</top>
<left>0</left>
<width>480</width>
<height>720</height>
<texture>$INFO[Container(100).ListItem.Art(poster)]</texture>
<animation type="WindowOpen" reversible="false">
<effect type="slide" delay="160" start="-100,0" end="0,0" time="200" />
<effect type="fade" delay="160" start="0" end="100" time="200" />
</animation>
<animation type="WindowOpen" reversible="false">
<effect type="slide" delay="160" start="0,0" end="-100,0" time="200" />
<effect type="fade" delay="160" start="100" end="0" time="200" />
</animation>
</control>
<control type="textbox">
<description>Main Title</description>
<left>520</left>
<top>40</top>
<width>1150</width>
<height>30</height>
<font>font13</font>
<textcolor>FFFFFFFF</textcolor>
<shadowcolor>00000000</shadowcolor>
<align>left</align>
<aligny>center</aligny>
<label>[B]$INFO[Container(100).ListItem.Property(name)][/B]</label>
</control>
<control type="list" id="100">
<description>Servers List</description>
<bottom>40</bottom>
<left>520</left>
<width>700</width>
<height>570</height>
<onleft>101</onleft>
<onright>101</onright>
<animation type="WindowOpen" reversible="false">
<effect type="slide" delay="160" start="100,0" end="0,0" time="200" />
<effect type="fade" delay="160" start="0" end="100" time="200" />
</animation>
<animation type="WindowOpen" reversible="false">
<effect type="slide" delay="160" start="0,0" end="100,0" time="200" />
<effect type="fade" delay="160" start="100" end="0" time="200" />
</animation>
<scrolltime tween="cubic" easing="out">300</scrolltime>
<itemlayout height="140" width="700">
<control type="image">
<description>Servers Icon</description>
<top>5</top>
<left>5</left>
<width>120</width>
<height>120</height>
<texture>$INFO[ListItem.Art(thumb)]</texture>
<aspectratio>scale</aspectratio>
</control>
<control type="textbox">
<description>Server Title</description>
<left>150</left>
<top>30</top>
<width>450</width>
<height>30</height>
<font>font13</font>
<textcolor>FFFFFFFF</textcolor>
<shadowcolor>00000000</shadowcolor>
<align>left</align>
<aligny>center</aligny>
<label>[B]$INFO[ListItem.Label][/B]</label>
</control>
<control type="textbox">
<description>Channel</description>
<left>150</left>
<top>60</top>
<width>450</width>
<height>30</height>
<font>font13</font>
<textcolor>FFFFFFFF</textcolor>
<shadowcolor>00000000</shadowcolor>
<align>left</align>
<aligny>center</aligny>
<label>[B][COLOR FFAAAAAA]$INFO[ListItem.Property(channel)][/COLOR][/B]</label>
</control>
</itemlayout>
<focusedlayout height="140" width="700">
<control type="image">
<description>Selection Background</description>
<width>700</width>
<height>130</height>
<texture colordiffuse="88000000">white.png</texture>
<aspectratio>scale</aspectratio>
</control>
<control type="image">
<description>Servers Color</description>
<top>0</top>
<left>0</left>
<width>130</width>
<height>130</height>
<texture colordiffuse="$INFO[ListItem.Property(color)]">white.png</texture>
<aspectratio>scale</aspectratio>
</control>
<control type="image">
<description>Servers Icon</description>
<top>5</top>
<left>5</left>
<width>120</width>
<height>120</height>
<texture>$INFO[ListItem.Art(thumb)]</texture>
<aspectratio>scale</aspectratio>
</control>
<control type="textbox">
<description>Server Title</description>
<left>150</left>
<top>30</top>
<width>450</width>
<height>30</height>
<font>font13</font>
<textcolor>FFFFFFFF</textcolor>
<shadowcolor>00000000</shadowcolor>
<align>left</align>
<aligny>center</aligny>
<label>[B]$INFO[ListItem.Label][/B]</label>
</control>
<control type="textbox">
<description>Channel</description>
<left>150</left>
<top>60</top>
<width>450</width>
<height>30</height>
<font>font13</font>
<textcolor>FFFFFFFF</textcolor>
<shadowcolor>00000000</shadowcolor>
<align>left</align>
<aligny>center</aligny>
<label>[B][COLOR FFAAAAAA]$INFO[ListItem.Property(channel)][/COLOR][/B]</label>
</control>
</focusedlayout>
</control>
<!-- END Servers List -->
<control type="button" id="101">
<description>Close</description>
<top>30</top>
<right>30</right>
<height>40</height>
<width>40</width>
<onup>100</onup>
<ondown>100</ondown>
<onleft>100</onleft>
<onright>100</onright>
<texturefocus colordiffuse="FFFFFFFF">close.png</texturefocus>
<texturenofocus colordiffuse="80FFFFFF">close.png</texturenofocus>
<onclick>Action(close)</onclick>
</control>
</control>
<!-- END SERVERS GROUP -->
</controls>
</window>

View File

@@ -8,10 +8,10 @@ PY3 = False
if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
from core import filetools, scrapertools, videolibrarytools
from core.support import typo, thumb
from core.support import typo, thumb, videolibrary
from core.item import Item
from platformcode import config, logger, platformtools
from core.videolibrarytools import videolibrarydb
from core.videolibrarytools import MOVIES_PATH, videolibrarydb
if PY3:
from concurrent import futures
@@ -21,12 +21,13 @@ else:
import urlparse
def mainlist(item):
logger.debug()
itemlist = [item.clone(title=config.get_localized_string(60509), contentType='movie', action='list_movies', thumbnail=thumb('videolibrary_movie')),
item.clone(title=typo(config.get_localized_string(70741) % config.get_localized_string(30122) + '...', 'submenu'), contentType='movie',action='search_list', thumbnail=thumb('search_movie')),
item.clone(title=config.get_localized_string(60600), contentType='tvshow', action='list_tvshows', thumbnail=thumb('videolibrary_tvshow'),
context=[{'channel':'videolibrary', 'action':'update_videolibrary', 'title':config.get_localized_string(70269), 'forced':True}]),
context=[{'channel':'videolibrary', 'action':'update_videolibrary', 'title':config.get_localized_string(70269)}]),
item.clone(title=typo(config.get_localized_string(70741) % config.get_localized_string(30123) + '...', 'submenu'),contentType='tvshow', action='search_list', thumbnail=thumb('search_tvshow')),
item.clone(channel='shortcuts', title=typo(config.get_localized_string(70287),'bold color kod'), action='SettingOnPosition',
category=2, setting=1, thumbnail = thumb('setting_0'),folder=False)]
@@ -210,7 +211,7 @@ def list_tvshows(item):
add_context(itemlist)
itemlist += [Item(channel=item.channel, action='update_videolibrary', thumbnail=item.thumbnail,
fanart=item.thumbnail, landscape=item.thumbnail, forced=True,
fanart=item.thumbnail, landscape=item.thumbnail,
title=typo(config.get_localized_string(70269), 'bold color kod'), folder=False)]
videolibrarydb.close()
return itemlist
@@ -276,6 +277,8 @@ def get_episodes(item):
if config.get_setting('no_pile_on_seasons', 'videolibrary') == 2 or item.all:
it.title = '{}x{}'.format(it.contentSeason, it.title)
it = get_host(it)
if item.window_type == 1 or (config.get_setting("window_type", "videolibrary") == 1):
it.folder = False
it.from_library = item.from_library
return it
return
@@ -296,9 +299,16 @@ def findvideos(item):
from core import autoplay
from platformcode import platformtools
logger.debug()
popup = True if item.window_type == 1 or (config.get_setting("window_type", "videolibrary") == 1) else False
if popup:
p_dialog = platformtools.dialog_progress_bg(config.get_localized_string(20000), config.get_localized_string(60683))
p_dialog.update(0, '')
videolibrarytools.check_renumber_options(item)
itemlist = []
if not item.strm_path:
logger.debug('Unable to search for videos due to lack of parameters')
return []
@@ -312,11 +322,23 @@ def findvideos(item):
videolibrary_items = videolibrarydb['episode'][item.videolibrary_id][ep]['channels']
prefered_lang = videolibrarydb['tvshow'].get(item.videolibrary_id, {}).get('item', Item()).prefered_lang
disabled = videolibrarydb['tvshow'].get(item.videolibrary_id, {}).get('item', Item()).disabled
if not item.infoLabels.get('tmdb_id'):
if item.contentType == 'movie':
item.infoLabels = videolibrarydb['movie'][item.videolibrary_id]['item'].infoLabels
else:
ep = '{:d}x{:02d}'.format(item.contentSeason, item.contentEpisodeNumber)
item.infoLabels = videolibrarydb['episode'][item.videolibrary_id][ep]['item'].infoLabels
videolibrarydb.close()
if 'local' in videolibrary_items:
try:
item.url = videolibrary_items['local']
if not '/' in item.url and not '\\' in item.url:
path = videolibrarytools.MOVIES_PATH if item.contentType == 'movie' else videolibrarytools.TVSHOWS_PATH
item.url = filetools.join(path, item.url)
item.channel = 'local'
item.url = filetools.join(videolibrarytools.TVSHOWS_PATH, videolibrary_items['local'])
if filetools.exists(item.url):
return play(item)
except: pass
else:
@@ -349,60 +371,23 @@ def findvideos(item):
for it in itemlist:
it.title = '[{}] {}'.format(it.ch_name, it.title)
if autoplay.play_multi_channel(item, itemlist): # hideserver
return []
if config.get_setting('autoplay'):
if popup:
item.window = True
itemlist = autoplay.start(itemlist, item)
else:
itemlist.sort(key=lambda it: (videolibrarytools.quality_order.index(it.quality.lower()) if it.quality and it.quality.lower() in videolibrarytools.quality_order else 999, it.server))
if config.get_setting('checklinks') and not config.get_setting('autoplay'):
from core import servertools
itemlist = servertools.check_list_links(itemlist, config.get_setting('checklinks_number'))
if item.window_type == 1 or (config.get_setting("window_type", "videolibrary") == 1):
p_dialog = platformtools.dialog_progress_bg(config.get_localized_string(20000), config.get_localized_string(60683))
p_dialog.update(0, '')
item.play_from = 'window'
if popup:
item.folder=False
item.window = True
p_dialog.update(100, ''); xbmc.sleep(500); p_dialog.close()
played = False
if len(itemlist) > 0:
reopen = False
while not xbmc.Monitor().abortRequested():
played = True
if not platformtools.is_playing():
if config.get_setting('next_ep') == 3:
xbmc.sleep(500)
if platformtools.is_playing():
return
if config.get_setting('autoplay') or reopen:
played_time = platformtools.get_played_time(item)
if not played_time and played:
return
options = []
selection_implementation = 0
for videoitem in itemlist:
videoitem.thumbnail = config.get_online_server_thumb(videoitem.server)
quality = ' [B][' + videoitem.quality + '][/B]' if videoitem.quality else ''
if videoitem.server:
path = filetools.join(config.get_runtime_path(), 'servers', videoitem.server.lower() + '.json')
name = jsontools.load(open(path, "rb").read())['name']
if name.startswith('@'): name = config.get_localized_string(int(name.replace('@','')))
it = xbmcgui.ListItem('\n[B]%s[/B]%s [%s]' % (name, quality, videoitem.ch_name))
it.setArt({'thumb':videoitem.thumbnail})
options.append(it)
else:
selection_implementation += 1
head = ('{} - '.format(item.contentSerieName) if item.contentSerieName else '') + item.title
selection = platformtools.dialog_select(head, options, preselect= -1, useDetails=True)
if selection == -1:
return
else:
item = play(itemlist[selection + selection_implementation])[0].clone(play_from='window')
platformtools.play_video(item)
reopen = True
xbmc.executebuiltin('Dialog.Close(all)')
serverwindow.start(item, itemlist)
else:
add_download_items(item, itemlist)
@@ -422,12 +407,10 @@ def servers(item, ch, items):
it.infoLabels = item.infoLabels
it.videolibrary_id = item.videolibrary_id
it.contentTitle = it.fulltitle = item.title
it.contentChannel = 'videolibrary'
for item in getattr(channel, it.action)(it):
if item.server and item.channel:
item.ch_name = ch_name
# item.contentChannel = item.channel
# item.play_from = 'videolibrary'
# item.channel = 'videolibrary'
serverlist.append(item)
return serverlist
@@ -495,6 +478,7 @@ def update_videolibrary(item=None):
p_dialog = None
update_when_finished = False
now = datetime.date.today()
try:
config.set_setting('updatelibrary_last_check', now.strftime('%Y-%m-%d'), 'videolibrary')
@@ -854,7 +838,7 @@ class subcontext(object):
# update
self.context.append(self.title('update'))
self.commands.append(self.item.clone(action='update_videolibrary'))
self.commands.append(self.item.clone(action='update_videolibrary', forced=True))
self.context.append(self.title('images'))
self.commands.append(self.item.clone(action='set_images'))
@@ -1324,3 +1308,36 @@ def get_results(nfo_path, root, Type, local=False):
# platformtools.itemlist_refresh()
class ServerWindow(xbmcgui.WindowXML):
def start(self, item, itemlist):
self.itemlist = itemlist
self.item = item
self.servers = []
for videoitem in self.itemlist:
videoitem.thumbnail = config.get_online_server_thumb(videoitem.server)
quality = ' [' + videoitem.quality + ']' if videoitem.quality else ''
if videoitem.server:
color = scrapertools.find_single_match(videoitem.alive, r'(FF[^\]]+)')
path = filetools.join(config.get_runtime_path(), 'servers', videoitem.server.lower() + '.json')
name = jsontools.load(open(path, "rb").read())['name']
if name.startswith('@'): name = config.get_localized_string(int(name.replace('@','')))
it = xbmcgui.ListItem('{}{}'.format(name, quality))
it.setProperties({'name': self.item.title, 'channel': videoitem.ch_name, 'color': color if color else 'FF0082C2'})
it.setArt({'poster':self.item.contentThumbnail, 'thumb':videoitem.thumbnail, 'fanart':self.item.infoLabels.get('fanart','')})
self.servers.append(it)
self.doModal()
def onInit(self):
self.SERVERS = self.getControl(100)
self.SERVERS.reset()
self.SERVERS.addItems(self.servers)
self.setFocusId(100)
def onClick(self, control_id):
if control_id == 100:
from platformcode.launcher import run
run(self.itemlist[self.SERVERS.getSelectedPosition()])
serverwindow = ServerWindow('Servers.xml', config.get_runtime_path())