merged from develop
This commit is contained in:
12
mediaserver/platformcode/__init__.py
Normal file
12
mediaserver/platformcode/__init__.py
Normal file
@@ -0,0 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Appends the main plugin dir to the PYTHONPATH if an internal package cannot be imported.
|
||||
# Examples: In Plex Media Server all modules are under "Code.*" package, and in Enigma2 under "Plugins.Extensions.*"
|
||||
try:
|
||||
# from core import logger
|
||||
import core
|
||||
except:
|
||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")))
|
||||
393
mediaserver/platformcode/config.py
Normal file
393
mediaserver/platformcode/config.py
Normal file
@@ -0,0 +1,393 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------------------------------
|
||||
# Parámetros de configuración (mediaserver)
|
||||
# ------------------------------------------------------------
|
||||
|
||||
import os
|
||||
import re
|
||||
import threading
|
||||
|
||||
PLATFORM_NAME = "mediaserver"
|
||||
PLUGIN_NAME = "alfa"
|
||||
|
||||
settings_dic = {}
|
||||
settings_types = {}
|
||||
adult_setting = {}
|
||||
|
||||
|
||||
def get_platform(full_version=False):
|
||||
# full_version solo es util en xbmc/kodi
|
||||
ret = {
|
||||
'num_version': 1.0,
|
||||
'name_version': PLATFORM_NAME,
|
||||
'video_db': "",
|
||||
'plaform': PLATFORM_NAME
|
||||
}
|
||||
|
||||
if full_version:
|
||||
return ret
|
||||
else:
|
||||
return PLATFORM_NAME
|
||||
|
||||
|
||||
def is_xbmc():
|
||||
return False
|
||||
|
||||
|
||||
def get_videolibrary_support():
|
||||
return True
|
||||
|
||||
|
||||
def get_system_platform():
|
||||
""" fonction: pour recuperer la platform que xbmc tourne """
|
||||
platform = "unknown"
|
||||
if sys.platform == "linux" or sys.platform == "linux2":
|
||||
platform = "linux"
|
||||
elif sys.platform == "darwin":
|
||||
platform = "osx"
|
||||
elif sys.platform == "win32":
|
||||
platform = "windows"
|
||||
|
||||
return platform
|
||||
|
||||
|
||||
def open_settings():
|
||||
Opciones = []
|
||||
from xml.dom import minidom
|
||||
settings = open(menufilepath, 'rb').read()
|
||||
xmldoc = minidom.parseString(settings)
|
||||
for category in xmldoc.getElementsByTagName("category"):
|
||||
for setting in category.getElementsByTagName("setting"):
|
||||
Opciones.append(dict(setting.attributes.items() + [(u"category", category.getAttribute("label")),
|
||||
(u"value", get_setting(setting.getAttribute("id")))]))
|
||||
|
||||
from platformcode import platformtools
|
||||
global adult_setting
|
||||
adult_password = get_setting('adult_password')
|
||||
if not adult_password:
|
||||
adult_password = set_setting('adult_password', '0000')
|
||||
adult_mode = get_setting('adult_mode')
|
||||
adult_request_password = get_setting('adult_request_password')
|
||||
|
||||
platformtools.open_settings(Opciones)
|
||||
|
||||
# Hemos accedido a la seccion de Canales para adultos
|
||||
if get_setting('adult_aux_intro_password'):
|
||||
# La contraseña de acceso es correcta
|
||||
if get_setting('adult_aux_intro_password') == adult_password:
|
||||
|
||||
# Cambio de contraseña
|
||||
if get_setting('adult_aux_new_password1'):
|
||||
if get_setting('adult_aux_new_password1') == get_setting('adult_aux_new_password2'):
|
||||
set_setting('adult_password', get_setting('adult_aux_new_password1'))
|
||||
else:
|
||||
platformtools.dialog_ok("Canales para adultos",
|
||||
"Los campos 'Nueva contraseña' y 'Confirmar nueva contraseña' no coinciden.",
|
||||
"Entre de nuevo en 'Preferencias' para cambiar la contraseña")
|
||||
|
||||
# Fijar adult_pin
|
||||
adult_pin = ""
|
||||
if get_setting("adult_request_password") == True:
|
||||
adult_pin = get_setting("adult_password")
|
||||
set_setting("adult_pin", adult_pin)
|
||||
|
||||
# Solo esta sesion:
|
||||
id = threading.current_thread().name
|
||||
if get_setting("adult_mode") == 2:
|
||||
adult_setting[id] = True
|
||||
set_setting("adult_mode", "0")
|
||||
else:
|
||||
adult_setting = {}
|
||||
|
||||
else:
|
||||
platformtools.dialog_ok("Canales para adultos", "La contraseña no es correcta.",
|
||||
"Los cambios realizados en esta sección no se guardaran.")
|
||||
# Deshacer cambios
|
||||
set_setting("adult_mode", adult_mode)
|
||||
set_setting("adult_request_password", adult_request_password)
|
||||
|
||||
# Borramos settings auxiliares
|
||||
set_setting('adult_aux_intro_password', '')
|
||||
set_setting('adult_aux_new_password1', '')
|
||||
set_setting('adult_aux_new_password2', '')
|
||||
|
||||
|
||||
def get_setting(name, channel="", server=""):
|
||||
"""
|
||||
Retorna el valor de configuracion del parametro solicitado.
|
||||
|
||||
Devuelve el valor del parametro 'name' en la configuracion global o en la configuracion propia del canal 'channel'.
|
||||
|
||||
Si se especifica el nombre del canal busca en la ruta \addon_data\plugin.video.alfa\settings_channels el
|
||||
archivo channel_data.json y lee el valor del parametro 'name'. Si el archivo channel_data.json no existe busca en la
|
||||
carpeta channels el archivo channel.xml y crea un archivo channel_data.json antes de retornar el valor solicitado.
|
||||
Si el parametro 'name' no existe en channel_data.json lo busca en la configuracion global y si ahi tampoco existe
|
||||
devuelve un str vacio.
|
||||
|
||||
Parametros:
|
||||
name -- nombre del parametro
|
||||
channel [opcional] -- nombre del canal
|
||||
|
||||
Retorna:
|
||||
value -- El valor del parametro 'name'
|
||||
|
||||
"""
|
||||
|
||||
# Specific channel setting
|
||||
if channel:
|
||||
|
||||
# logger.info("config.get_setting reading channel setting '"+name+"' from channel json")
|
||||
from core import channeltools
|
||||
value = channeltools.get_channel_setting(name, channel)
|
||||
# logger.info("config.get_setting -> '"+repr(value)+"'")
|
||||
|
||||
return value
|
||||
|
||||
elif server:
|
||||
# logger.info("config.get_setting reading server setting '"+name+"' from server json")
|
||||
from core import servertools
|
||||
value = servertools.get_server_setting(name, server)
|
||||
# logger.info("config.get_setting -> '"+repr(value)+"'")
|
||||
|
||||
return value
|
||||
|
||||
# Global setting
|
||||
else:
|
||||
# logger.info("config.get_setting reading main setting '"+name+"'")
|
||||
global settings_dic
|
||||
value = settings_dic.get(name, "")
|
||||
|
||||
if name == "adult_mode":
|
||||
global adult_setting
|
||||
id = threading.current_thread().name
|
||||
if adult_setting.get(id) == True:
|
||||
value = "2"
|
||||
|
||||
# hack para devolver el tipo correspondiente
|
||||
global settings_types
|
||||
|
||||
if settings_types.get(name) in ['enum', 'number']:
|
||||
value = int(value)
|
||||
|
||||
elif settings_types.get(name) == 'bool':
|
||||
value = value == 'true'
|
||||
|
||||
elif not settings_types.has_key(name):
|
||||
try:
|
||||
t = eval(value)
|
||||
value = t[0](t[1])
|
||||
except:
|
||||
value = None
|
||||
|
||||
return value
|
||||
|
||||
|
||||
def set_setting(name, value, channel="", server=""):
|
||||
"""
|
||||
Fija el valor de configuracion del parametro indicado.
|
||||
|
||||
Establece 'value' como el valor del parametro 'name' en la configuracion global o en la configuracion propia del
|
||||
canal 'channel'.
|
||||
Devuelve el valor cambiado o None si la asignacion no se ha podido completar.
|
||||
|
||||
Si se especifica el nombre del canal busca en la ruta \addon_data\plugin.video.alfa\settings_channels el
|
||||
archivo channel_data.json y establece el parametro 'name' al valor indicado por 'value'. Si el archivo
|
||||
channel_data.json no existe busca en la carpeta channels el archivo channel.xml y crea un archivo channel_data.json
|
||||
antes de modificar el parametro 'name'.
|
||||
Si el parametro 'name' no existe lo añade, con su valor, al archivo correspondiente.
|
||||
|
||||
|
||||
Parametros:
|
||||
name -- nombre del parametro
|
||||
value -- valor del parametro
|
||||
channel [opcional] -- nombre del canal
|
||||
|
||||
Retorna:
|
||||
'value' en caso de que se haya podido fijar el valor y None en caso contrario
|
||||
|
||||
"""
|
||||
if channel:
|
||||
from core import channeltools
|
||||
return channeltools.set_channel_setting(name, value, channel)
|
||||
elif server:
|
||||
from core import servertools
|
||||
return servertools.set_server_setting(name, value, server)
|
||||
else:
|
||||
global settings_dic
|
||||
global settings_types
|
||||
|
||||
if settings_types.get(name) == 'bool':
|
||||
if value:
|
||||
new_value = "true"
|
||||
else:
|
||||
new_value = "false"
|
||||
|
||||
elif settings_types.get(name):
|
||||
new_value = str(value)
|
||||
|
||||
else:
|
||||
if isinstance(value, basestring):
|
||||
new_value = "(%s, %s)" % (type(value).__name__, repr(value))
|
||||
else:
|
||||
new_value = "(%s, %s)" % (type(value).__name__, value)
|
||||
|
||||
settings_dic[name] = new_value
|
||||
|
||||
from xml.dom import minidom
|
||||
# Crea un Nuevo XML vacio
|
||||
new_settings = minidom.getDOMImplementation().createDocument(None, "settings", None)
|
||||
new_settings_root = new_settings.documentElement
|
||||
|
||||
for key in settings_dic:
|
||||
nodo = new_settings.createElement("setting")
|
||||
nodo.setAttribute("value", settings_dic[key])
|
||||
nodo.setAttribute("id", key)
|
||||
new_settings_root.appendChild(nodo)
|
||||
|
||||
fichero = open(configfilepath, "w")
|
||||
fichero.write(new_settings.toprettyxml(encoding='utf-8'))
|
||||
fichero.close()
|
||||
return value
|
||||
|
||||
|
||||
def get_localized_string(code):
|
||||
translationsfile = open(TRANSLATION_FILE_PATH, "r")
|
||||
translations = translationsfile.read()
|
||||
translationsfile.close()
|
||||
cadenas = re.findall('<string id="%s">([^<]+)<' % code, translations)
|
||||
if len(cadenas) > 0:
|
||||
dev = cadenas[0]
|
||||
else:
|
||||
dev = "%d" % code
|
||||
|
||||
try:
|
||||
dev = dev.encode("utf-8")
|
||||
except:
|
||||
pass
|
||||
|
||||
return dev
|
||||
|
||||
|
||||
def get_videolibrary_path():
|
||||
value = get_setting("videolibrarypath")
|
||||
if value == "":
|
||||
verify_directories_created()
|
||||
value = get_setting("videolibrarypath")
|
||||
|
||||
return value
|
||||
|
||||
|
||||
def get_temp_file(filename):
|
||||
import tempfile
|
||||
return os.path.join(tempfile.gettempdir(), filename)
|
||||
|
||||
|
||||
def get_runtime_path():
|
||||
return os.getcwd()
|
||||
|
||||
|
||||
def get_data_path():
|
||||
dev = os.path.join(os.path.expanduser("~"), ".alfa")
|
||||
|
||||
# Crea el directorio si no existe
|
||||
if not os.path.exists(dev):
|
||||
os.makedirs(dev)
|
||||
|
||||
return dev
|
||||
|
||||
|
||||
def get_cookie_data():
|
||||
import os
|
||||
ficherocookies = os.path.join(get_data_path(), 'cookies.dat')
|
||||
|
||||
cookiedatafile = open(ficherocookies, 'r')
|
||||
cookiedata = cookiedatafile.read()
|
||||
cookiedatafile.close()
|
||||
|
||||
return cookiedata
|
||||
|
||||
|
||||
# Test if all the required directories are created
|
||||
def verify_directories_created():
|
||||
from platformcode import logger
|
||||
from core import filetools
|
||||
|
||||
config_paths = [["videolibrarypath", "library"],
|
||||
["downloadpath", "downloads"],
|
||||
["downloadlistpath", "downloads/list"],
|
||||
["bookmarkpath", "favorites"],
|
||||
["settings_path", "settings_channels"]]
|
||||
|
||||
for path, default in config_paths:
|
||||
saved_path = get_setting(path)
|
||||
if not saved_path:
|
||||
saved_path = filetools.join(get_data_path(), *default.split("/"))
|
||||
set_setting(path, saved_path)
|
||||
|
||||
if not filetools.exists(saved_path):
|
||||
logger.debug("Creating %s: %s" % (path, saved_path))
|
||||
filetools.mkdir(saved_path)
|
||||
|
||||
|
||||
def get_local_ip():
|
||||
import socket
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.connect(('8.8.8.8', 53)) # connecting to a UDP address doesn't send packets
|
||||
myip = s.getsockname()[0]
|
||||
return myip
|
||||
|
||||
|
||||
def load_settings():
|
||||
global settings_dic
|
||||
global settings_types
|
||||
defaults = {}
|
||||
from xml.etree import ElementTree
|
||||
|
||||
encontrado = False
|
||||
# Lee el archivo XML (si existe)
|
||||
if os.path.exists(configfilepath):
|
||||
settings = open(configfilepath, 'rb').read()
|
||||
root = ElementTree.fromstring(settings)
|
||||
for target in root.findall("setting"):
|
||||
settings_dic[target.get("id")] = target.get("value")
|
||||
|
||||
defaultsettings = open(menufilepath, 'rb').read()
|
||||
root = ElementTree.fromstring(defaultsettings)
|
||||
for category in root.findall("category"):
|
||||
for target in category.findall("setting"):
|
||||
if target.get("id"):
|
||||
defaults[target.get("id")] = target.get("default")
|
||||
settings_types[target.get("id")] = target.get("type")
|
||||
|
||||
for key in defaults:
|
||||
if not key in settings_dic:
|
||||
settings_dic[key] = defaults[key]
|
||||
set_settings(settings_dic)
|
||||
|
||||
|
||||
def set_settings(JsonRespuesta):
|
||||
for Ajuste in JsonRespuesta:
|
||||
settings_dic[Ajuste] = JsonRespuesta[Ajuste].encode("utf8")
|
||||
from xml.dom import minidom
|
||||
# Crea un Nuevo XML vacio
|
||||
new_settings = minidom.getDOMImplementation().createDocument(None, "settings", None)
|
||||
new_settings_root = new_settings.documentElement
|
||||
|
||||
for key in settings_dic:
|
||||
nodo = new_settings.createElement("setting")
|
||||
nodo.setAttribute("value", settings_dic[key])
|
||||
nodo.setAttribute("id", key)
|
||||
new_settings_root.appendChild(nodo)
|
||||
|
||||
fichero = open(configfilepath, "w")
|
||||
fichero.write(new_settings.toprettyxml(encoding='utf-8'))
|
||||
fichero.close()
|
||||
|
||||
|
||||
# Fichero de configuración
|
||||
menufilepath = os.path.join(get_runtime_path(), "resources", "settings.xml")
|
||||
configfilepath = os.path.join(get_data_path(), "settings.xml")
|
||||
if not os.path.exists(get_data_path()): os.mkdir(get_data_path())
|
||||
# Literales
|
||||
TRANSLATION_FILE_PATH = os.path.join(get_runtime_path(), "resources", "language", "Spanish", "strings.xml")
|
||||
load_settings()
|
||||
41
mediaserver/platformcode/controllers/__init__.py
Normal file
41
mediaserver/platformcode/controllers/__init__.py
Normal file
@@ -0,0 +1,41 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------------------------------
|
||||
# Módulo para acciones en el cliente HTML
|
||||
# ------------------------------------------------------------
|
||||
|
||||
import os
|
||||
from inspect import isclass
|
||||
|
||||
from controller import Controller
|
||||
from platformcode import logger
|
||||
|
||||
|
||||
def load_controllers():
|
||||
controllers = []
|
||||
path = os.path.split(__file__)[0]
|
||||
for fname in os.listdir(path):
|
||||
mod, ext = os.path.splitext(fname)
|
||||
fname = os.path.join(path, fname)
|
||||
if os.path.isfile(fname) and ext == '.py' and not mod.startswith('_'):
|
||||
try:
|
||||
exec "import " + mod + " as controller"
|
||||
except:
|
||||
import traceback
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
for c in dir(controller):
|
||||
cls = getattr(controller, c)
|
||||
|
||||
if not c.startswith('_') and isclass(cls) and issubclass(cls, Controller) and Controller != cls:
|
||||
controllers.append(cls)
|
||||
return controllers
|
||||
|
||||
|
||||
controllers = load_controllers()
|
||||
|
||||
|
||||
def find_controller(url):
|
||||
result = []
|
||||
for c in controllers:
|
||||
if c().match(url):
|
||||
return c
|
||||
129
mediaserver/platformcode/controllers/controller.py
Normal file
129
mediaserver/platformcode/controllers/controller.py
Normal file
@@ -0,0 +1,129 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------------------------------
|
||||
# Mediaserver Base controller
|
||||
# ------------------------------------------------------------
|
||||
|
||||
import threading
|
||||
|
||||
from platformcode import config, platformtools
|
||||
|
||||
|
||||
class Controller(object):
|
||||
pattern = ""
|
||||
name = None
|
||||
|
||||
def __init__(self, handler=None, ID=None):
|
||||
|
||||
self.handler = handler
|
||||
self.id = ID
|
||||
|
||||
if not self.id:
|
||||
self.id = threading.current_thread().name
|
||||
|
||||
if self.handler:
|
||||
self.platformtools = Platformtools()
|
||||
self.host = "http://%s:%s" % (config.get_local_ip(), config.get_setting("server.port"))
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
super(Controller, self).__setattr__(name, value)
|
||||
|
||||
if name == "platformtools":
|
||||
platformtools.controllers[self.id] = self.platformtools
|
||||
|
||||
def __del__(self):
|
||||
from platformcode import platformtools
|
||||
if self.id in platformtools.controllers:
|
||||
del platformtools.controllers[self.id]
|
||||
|
||||
def run(self, path):
|
||||
pass
|
||||
|
||||
def match(self, path):
|
||||
if self.pattern.findall(path):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
class Platformtools(object):
|
||||
def dialog_ok(self, heading, line1, line2="", line3=""):
|
||||
pass
|
||||
|
||||
def dialog_notification(self, heading, message, icon=0, time=5000, sound=True):
|
||||
pass
|
||||
|
||||
def dialog_yesno(self, heading, line1, line2="", line3="", nolabel="No", yeslabel="Si", autoclose=""):
|
||||
return True
|
||||
|
||||
def dialog_select(self, heading, list):
|
||||
pass
|
||||
|
||||
def dialog_progress(self, heading, line1, line2="", line3=""):
|
||||
class Dialog(object):
|
||||
def __init__(self, heading, line1, line2, line3, PObject):
|
||||
self.PObject = PObject
|
||||
self.closed = False
|
||||
self.heading = heading
|
||||
text = line1
|
||||
if line2: text += "\n" + line2
|
||||
if line3: text += "\n" + line3
|
||||
|
||||
def iscanceled(self):
|
||||
return self.closed
|
||||
|
||||
def update(self, percent, line1, line2="", line3=""):
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
self.closed = True
|
||||
|
||||
return Dialog(heading, line1, line2, line3, None)
|
||||
|
||||
def dialog_progress_bg(self, heading, message=""):
|
||||
class Dialog(object):
|
||||
def __init__(self, heading, message, PObject):
|
||||
self.PObject = PObject
|
||||
self.closed = False
|
||||
self.heading = heading
|
||||
|
||||
def isFinished(self):
|
||||
return not self.closed
|
||||
|
||||
def update(self, percent=0, heading="", message=""):
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
self.closed = True
|
||||
|
||||
return Dialog(heading, message, None)
|
||||
|
||||
def dialog_input(self, default="", heading="", hidden=False):
|
||||
return default
|
||||
|
||||
def dialog_numeric(self, type, heading, default=""):
|
||||
return None
|
||||
|
||||
def itemlist_refresh(self):
|
||||
pass
|
||||
|
||||
def itemlist_update(self, item):
|
||||
pass
|
||||
|
||||
def render_items(self, itemlist, parentitem):
|
||||
pass
|
||||
|
||||
def is_playing(self):
|
||||
return False
|
||||
|
||||
def play_video(self, item):
|
||||
pass
|
||||
|
||||
def show_channel_settings(self, list_controls=None, dict_values=None, caption="", callback=None, item=None,
|
||||
custom_button=None, channelpath=None):
|
||||
pass
|
||||
|
||||
def show_video_info(self, data, caption="Información del vídeo", callback=None, item=None):
|
||||
pass
|
||||
|
||||
def show_recaptcha(self, key, url):
|
||||
pass
|
||||
104
mediaserver/platformcode/controllers/fileserver.py
Normal file
104
mediaserver/platformcode/controllers/fileserver.py
Normal file
@@ -0,0 +1,104 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------------------------------
|
||||
# Controlador para acceso a archivos locales
|
||||
# ------------------------------------------------------------
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
|
||||
from controller import Controller
|
||||
from platformcode import config, logger
|
||||
|
||||
|
||||
class fileserver(Controller):
|
||||
pattern = re.compile("^/(?:media/.*?)?(?:local/.*?)?$")
|
||||
|
||||
def run(self, path):
|
||||
if path == "/":
|
||||
f = open(os.path.join(config.get_runtime_path(), "platformcode", "template", "page.html"), "rb")
|
||||
self.handler.send_response(200)
|
||||
self.handler.send_header('Content-type', 'text/html')
|
||||
self.handler.end_headers()
|
||||
respuesta = f.read()
|
||||
respuesta = respuesta.replace("{$WSPORT}", str(config.get_setting("websocket.port")))
|
||||
self.handler.wfile.write(respuesta)
|
||||
f.close()
|
||||
|
||||
elif path.startswith("/local/"):
|
||||
import base64
|
||||
import urllib
|
||||
Path = path.replace("/local/", "").split("/")[0]
|
||||
Path = base64.b64decode(urllib.unquote_plus(Path))
|
||||
Size = int(os.path.getsize(Path.decode("utf8")))
|
||||
f = open(Path.decode("utf8"), "rb")
|
||||
if not self.handler.headers.get("range") == None:
|
||||
if "=" in str(self.handler.headers.get("range")) and "-" in str(self.handler.headers.get("range")):
|
||||
Inicio = int(self.handler.headers.get("range").split("=")[1].split("-")[0])
|
||||
if self.handler.headers.get("range").split("=")[1].split("-")[1] <> "":
|
||||
Fin = int(self.handler.headers.get("range").split("=")[1].split("-")[1])
|
||||
else:
|
||||
Fin = Size - 1
|
||||
|
||||
else:
|
||||
Inicio = 0
|
||||
Fin = Size - 1
|
||||
|
||||
if not Fin > Inicio: Fin = Size - 1
|
||||
|
||||
if self.handler.headers.get("range") == None:
|
||||
logger.info("-------------------------------------------------------")
|
||||
logger.info("Solicitando archivo local: " + Path)
|
||||
logger.info("-------------------------------------------------------")
|
||||
|
||||
self.handler.send_response(200)
|
||||
self.handler.send_header("Content-Disposition", "attachment; filename=video.mp4")
|
||||
self.handler.send_header('Accept-Ranges', 'bytes')
|
||||
self.handler.send_header('Content-Length', str(Size))
|
||||
self.handler.send_header("Connection", "close")
|
||||
self.handler.end_headers()
|
||||
while True:
|
||||
time.sleep(0.2)
|
||||
buffer = f.read(1024 * 250)
|
||||
if not buffer:
|
||||
break
|
||||
self.handler.wfile.write(buffer)
|
||||
self.handler.wfile.close()
|
||||
f.close()
|
||||
else:
|
||||
logger.info("-------------------------------------------------------")
|
||||
logger.info("Solicitando archivo local: " + Path)
|
||||
logger.info("Rango: " + str(Inicio) + "-" + str(Fin) + "/" + str(Size))
|
||||
logger.info("-------------------------------------------------------")
|
||||
f.seek(Inicio)
|
||||
|
||||
self.handler.send_response(206)
|
||||
self.handler.send_header("Content-Disposition", "attachment; filename=video.mp4")
|
||||
self.handler.send_header('Accept-Ranges', 'bytes')
|
||||
self.handler.send_header('Content-Length', str(Fin - Inicio))
|
||||
self.handler.send_header('Content-Range', str(Inicio) + "-" + str(Fin) + "/" + str(Size))
|
||||
self.handler.send_header("Connection", "close")
|
||||
|
||||
self.handler.end_headers()
|
||||
while True:
|
||||
time.sleep(0.2)
|
||||
buffer = f.read(1024 * 250)
|
||||
if not buffer:
|
||||
break
|
||||
self.handler.wfile.write(buffer)
|
||||
self.handler.wfile.close()
|
||||
f.close()
|
||||
elif path.startswith("/media/"):
|
||||
file = os.path.join(config.get_runtime_path(), "platformcode", "template", path[7:])
|
||||
from mimetypes import MimeTypes
|
||||
mime = MimeTypes()
|
||||
mime_type = mime.guess_type(file)
|
||||
try:
|
||||
mim = mime_type[0]
|
||||
except:
|
||||
mim = ""
|
||||
f = open(file, "rb")
|
||||
self.handler.send_response(200)
|
||||
self.handler.send_header('Content-type', mim)
|
||||
self.handler.end_headers()
|
||||
self.handler.wfile.write(f.read())
|
||||
f.close()
|
||||
788
mediaserver/platformcode/controllers/html.py
Normal file
788
mediaserver/platformcode/controllers/html.py
Normal file
@@ -0,0 +1,788 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------------------------------
|
||||
# Controlador para HTML
|
||||
# ------------------------------------------------------------
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import threading
|
||||
import time
|
||||
|
||||
import channelselector
|
||||
from controller import Controller
|
||||
from controller import Platformtools
|
||||
from platformcode import config
|
||||
from core import versiontools
|
||||
from core.item import Item
|
||||
from core.tmdb import Tmdb
|
||||
from platformcode import launcher, logger
|
||||
|
||||
|
||||
class html(Controller):
|
||||
pattern = re.compile("##")
|
||||
name = "HTML"
|
||||
|
||||
def __init__(self, handler=None, ID=None):
|
||||
super(html, self).__init__(handler, ID)
|
||||
self.platformtools = platform(self)
|
||||
self.data = {}
|
||||
if self.handler:
|
||||
self.client_ip = handler.client.getpeername()[0]
|
||||
self.send_message({"action": "connect",
|
||||
"data": {"version": "Alfa %s" % versiontools.get_current_plugin_version_tag(),
|
||||
"date": versiontools.get_current_plugin_date()}})
|
||||
t = threading.Thread(target=launcher.start, name=ID)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
||||
def run(self, path):
|
||||
if path:
|
||||
item = Item().fromurl(path)
|
||||
else:
|
||||
item = Item(channel="channelselector", action="mainlist", viewmode="banner")
|
||||
|
||||
launcher.run(item)
|
||||
|
||||
def get_data(self, id):
|
||||
while not "id" in self.data or not self.data["id"] == id:
|
||||
time.sleep(0.1)
|
||||
data = self.data["result"]
|
||||
self.data = {}
|
||||
return data
|
||||
|
||||
def send_message(self, data):
|
||||
import random
|
||||
|
||||
ID = "%032x" % (random.getrandbits(128))
|
||||
data["id"] = ID
|
||||
|
||||
self.handler.sendMessage(json.dumps(data))
|
||||
return ID
|
||||
|
||||
|
||||
class platform(Platformtools):
|
||||
def __init__(self, controller):
|
||||
self.controller = controller
|
||||
self.handler = controller.handler
|
||||
self.get_data = controller.get_data
|
||||
self.send_message = controller.send_message
|
||||
|
||||
def render_items(self, itemlist, parent_item):
|
||||
"""
|
||||
Función encargada de mostrar el itemlist, se pasa como parametros el itemlist y el item del que procede
|
||||
@type itemlist: list
|
||||
@param itemlist: lista de elementos a mostrar
|
||||
|
||||
@type parent_item: item
|
||||
@param parent_item: elemento padre
|
||||
"""
|
||||
|
||||
# Si el itemlist no es un list salimos
|
||||
if not type(itemlist) == list:
|
||||
JsonData = {}
|
||||
JsonData["action"] = "HideLoading"
|
||||
JsonData["data"] = {}
|
||||
self.send_message(JsonData)
|
||||
return
|
||||
|
||||
# Si no hay ningun item, mostramos un aviso
|
||||
if not len(itemlist):
|
||||
itemlist.append(Item(title="No hay elementos que mostrar"))
|
||||
|
||||
if parent_item.channel == "channelselector" and not parent_item.action == "filterchannels":
|
||||
parent_item.viewmode = "banner"
|
||||
elif parent_item.channel == "channelselector" and parent_item.action == "filterchannels":
|
||||
parent_item.viewmode = "channel"
|
||||
if not parent_item.viewmode:
|
||||
parent_item.viewmode = "list"
|
||||
|
||||
# Item Atrás
|
||||
if not (parent_item.channel == "channelselector" and parent_item.action == "mainlist") and not \
|
||||
itemlist[0].action == "go_back":
|
||||
if parent_item.viewmode in ["banner", "channel"]:
|
||||
itemlist.insert(0, Item(title="Atrás", action="go_back",
|
||||
thumbnail=channelselector.get_thumb("back.png", "banner_")))
|
||||
else:
|
||||
itemlist.insert(0, Item(title="Atrás", action="go_back",
|
||||
thumbnail=channelselector.get_thumb("back.png")))
|
||||
|
||||
JsonData = {}
|
||||
JsonData["action"] = "EndItems"
|
||||
JsonData["data"] = {}
|
||||
JsonData["data"]["itemlist"] = []
|
||||
JsonData["data"]["viewmode"] = parent_item.viewmode
|
||||
JsonData["data"]["category"] = parent_item.category.capitalize()
|
||||
JsonData["data"]["host"] = self.controller.host
|
||||
|
||||
# Recorremos el itemlist
|
||||
for item in itemlist:
|
||||
|
||||
if not item.thumbnail and item.action == "search": item.thumbnail = channelselector.get_thumb("search.png")
|
||||
if not item.thumbnail and item.folder == True: item.thumbnail = channelselector.get_thumb("folder.png", "banner")
|
||||
if not item.thumbnail and item.folder == False: item.thumbnail = channelselector.get_thumb("nofolder.png")
|
||||
if "http://media.xxxxx/" in item.thumbnail and not item.thumbnail.startswith(
|
||||
"http://media.xxxxxxxx/thumb_"):
|
||||
|
||||
if parent_item.viewmode in ["banner", "channel"]:
|
||||
item.thumbnail = channelselector.get_thumbnail_path("banner") + os.path.basename(item.thumbnail)
|
||||
else:
|
||||
item.thumbnail = channelselector.get_thumbnail_path() + os.path.basename(item.thumbnail)
|
||||
|
||||
# Estas imagenes no estan en banner, asi que si queremos banner, para que no se vean mal las quitamos
|
||||
elif parent_item.viewmode in ["banner", "channel"] and item.thumbnail.startswith(
|
||||
"http://media.xxxxx/thumb_"):
|
||||
item.thumbnail = ""
|
||||
|
||||
# Si el item no contiene categoria,le ponemos la del item padre
|
||||
if item.category == "":
|
||||
item.category = parent_item.category
|
||||
|
||||
# Si el item no contiene fanart,le ponemos la del item padre
|
||||
if item.fanart == "":
|
||||
item.fanart = parent_item.fanart
|
||||
|
||||
title = item.title.replace(item.title.lstrip(), "").replace(" ", " ") + item.title.lstrip()
|
||||
|
||||
# Formatear titulo
|
||||
if item.text_color:
|
||||
title = '[COLOR %s]%s[/COLOR]' % (item.text_color, title)
|
||||
if item.text_bold:
|
||||
title = '[B]%s[/B]' % title
|
||||
if item.text_italic:
|
||||
title = '[I]%s[/I]' % title
|
||||
|
||||
title = self.kodi_labels_to_html(title)
|
||||
|
||||
# Añade headers a las imagenes si estan en un servidor con cloudflare
|
||||
from core import httptools
|
||||
item.thumbnail = httptools.get_url_headers(item.thumbnail)
|
||||
item.fanart = httptools.get_url_headers(item.fanart)
|
||||
|
||||
JsonItem = {}
|
||||
JsonItem["title"] = title
|
||||
JsonItem["thumbnail"] = item.thumbnail
|
||||
JsonItem["fanart"] = item.fanart
|
||||
JsonItem["plot"] = item.plot
|
||||
JsonItem["action"] = item.action
|
||||
JsonItem["url"] = item.tourl()
|
||||
JsonItem["context"] = []
|
||||
if not item.action == "go_back":
|
||||
for Comando in self.set_context_commands(item, parent_item):
|
||||
JsonItem["context"].append({"title": Comando[0], "url": Comando[1]})
|
||||
|
||||
JsonData["data"]["itemlist"].append(JsonItem)
|
||||
|
||||
ID = self.send_message(JsonData)
|
||||
self.get_data(ID)
|
||||
|
||||
def set_context_commands(self, item, parent_item):
|
||||
"""
|
||||
Función para generar los menus contextuales.
|
||||
1. Partiendo de los datos de item.context
|
||||
a. Metodo antiguo item.context tipo str separando las opciones por "|" (ejemplo: item.context = "1|2|3")
|
||||
(solo predefinidos)
|
||||
b. Metodo list: item.context es un list con las diferentes opciones del menu:
|
||||
- Predefinidos: Se cargara una opcion predefinida con un nombre.
|
||||
item.context = ["1","2","3"]
|
||||
|
||||
- dict(): Se cargara el item actual modificando los campos que se incluyan en el dict() en caso de
|
||||
modificar los campos channel y action estos serán guardados en from_channel y from_action.
|
||||
item.context = [{"title":"Nombre del menu", "action": "action del menu", "channel",
|
||||
"channel del menu"}, {...}]
|
||||
|
||||
2. Añadiendo opciones segun criterios
|
||||
Se pueden añadir opciones al menu contextual a items que cumplan ciertas condiciones
|
||||
|
||||
3. Añadiendo opciones a todos los items
|
||||
Se pueden añadir opciones al menu contextual para todos los items
|
||||
|
||||
@param item: elemento que contiene los menu contextuales
|
||||
@type item: item
|
||||
@param parent_item:
|
||||
@type parent_item: item
|
||||
"""
|
||||
context_commands = []
|
||||
|
||||
# Creamos un list con las diferentes opciones incluidas en item.context
|
||||
if type(item.context) == str:
|
||||
context = item.context.split("|")
|
||||
elif type(item.context) == list:
|
||||
context = item.context
|
||||
else:
|
||||
context = []
|
||||
|
||||
# Opciones segun item.context
|
||||
for command in context:
|
||||
# Predefinidos
|
||||
if type(command) == str:
|
||||
if command == "buscar_trailer":
|
||||
context_commands.append(("Buscar Trailer",
|
||||
item.clone(channel="trailertools", action="buscartrailer",
|
||||
contextual=True).tourl()))
|
||||
|
||||
# Formato dict
|
||||
if type(command) == dict:
|
||||
# Los parametros del dict, se sobreescriben al nuevo context_item en caso de sobreescribir "action" y
|
||||
# "channel", los datos originales se guardan en "from_action" y "from_channel"
|
||||
if "action" in command:
|
||||
command["from_action"] = item.action
|
||||
if "channel" in command:
|
||||
command["from_channel"] = item.channel
|
||||
context_commands.append(
|
||||
(command["title"], item.clone(**command).tourl()))
|
||||
|
||||
# Opciones segun criterios
|
||||
|
||||
# Ir al Menu Principal (channel.mainlist)
|
||||
if parent_item.channel not in ["news",
|
||||
"channelselector"] and item.action != "mainlist" and parent_item.action != "mainlist":
|
||||
context_commands.append(("Ir al Menu Principal", Item(channel=item.channel, action="mainlist").tourl()))
|
||||
|
||||
# Añadir a Favoritos
|
||||
if item.channel not in ["favorites", "videolibrary", "help", "setting",
|
||||
""] and not parent_item.channel == "favorites":
|
||||
context_commands.append((config.get_localized_string(30155),
|
||||
item.clone(channel="favorites", action="addFavourite", from_channel=item.channel,
|
||||
from_action=item.action).tourl()))
|
||||
|
||||
# Añadimos opción contextual para Añadir la serie completa a la videoteca
|
||||
if item.channel != "videolibrary" and item.action in ["episodios", "get_episodios"] \
|
||||
and (item.contentSerieName or item.show):
|
||||
context_commands.append(("Añadir Serie a Videoteca",
|
||||
item.clone(action="add_serie_to_library", from_action=item.action).tourl()))
|
||||
|
||||
# Añadir Pelicula a videoteca
|
||||
if item.channel != "videolibrary" and item.action in ["detail", "findvideos"] \
|
||||
and item.contentType == 'movie':
|
||||
context_commands.append(("Añadir Pelicula a Videoteca",
|
||||
item.clone(action="add_pelicula_to_library", from_action=item.action).tourl()))
|
||||
|
||||
# Descargar pelicula
|
||||
if item.contentType == "movie" and not item.channel == "downloads":
|
||||
context_commands.append(("Descargar Pelicula",
|
||||
item.clone(channel="downloads", action="save_download", from_channel=item.channel,
|
||||
from_action=item.action).tourl()))
|
||||
|
||||
# Descargar serie
|
||||
if item.contentType == "tvshow" and not item.channel == "downloads":
|
||||
context_commands.append(("Descargar Serie",
|
||||
item.clone(channel="downloads", action="save_download", from_channel=item.channel,
|
||||
from_action=item.action).tourl()))
|
||||
|
||||
# Descargar episodio
|
||||
if item.contentType == "episode" and not item.channel == "downloads":
|
||||
context_commands.append(("Descargar Episodio",
|
||||
item.clone(channel="downloads", action="save_download", from_channel=item.channel,
|
||||
from_action=item.action).tourl()))
|
||||
|
||||
# Descargar temporada
|
||||
if item.contentType == "season" and not item.channel == "downloads":
|
||||
context_commands.append(("Descargar Temporada",
|
||||
item.clone(channel="downloads", action="save_download", from_channel=item.channel,
|
||||
from_action=item.action).tourl()))
|
||||
|
||||
# Abrir configuración
|
||||
if parent_item.channel not in ["setting", "news", "search"]:
|
||||
context_commands.append(("Abrir Configuración", Item(channel="setting", action="mainlist").tourl()))
|
||||
|
||||
return sorted(context_commands, key=lambda comand: comand[0])
|
||||
|
||||
def dialog_ok(self, heading, line1, line2="", line3=""):
|
||||
text = line1
|
||||
if line2: text += "\n" + line2
|
||||
if line3: text += "\n" + line3
|
||||
text = self.kodi_labels_to_html(text)
|
||||
JsonData = {}
|
||||
JsonData["action"] = "Alert"
|
||||
JsonData["data"] = {}
|
||||
JsonData["data"]["title"] = heading
|
||||
JsonData["data"]["text"] = unicode(text, "utf8", "ignore").encode("utf8")
|
||||
ID = self.send_message(JsonData)
|
||||
self.get_data(ID)
|
||||
|
||||
def dialog_notification(self, heading, message, icon=0, time=5000, sound=True):
|
||||
JsonData = {}
|
||||
JsonData["action"] = "notification"
|
||||
JsonData["data"] = {}
|
||||
JsonData["data"]["title"] = self.kodi_labels_to_html(heading)
|
||||
JsonData["data"]["text"] = self.kodi_labels_to_html(message)
|
||||
JsonData["data"]["icon"] = icon
|
||||
JsonData["data"]["sound"] = sound
|
||||
JsonData["data"]["time"] = time
|
||||
self.send_message(JsonData)
|
||||
return
|
||||
|
||||
def dialog_yesno(self, heading, line1, line2="", line3="", nolabel="No", yeslabel="Si", autoclose=""):
|
||||
text = line1
|
||||
if line2: text += "\n" + line2
|
||||
if line3: text += "\n" + line3
|
||||
text = self.kodi_labels_to_html(text)
|
||||
heading = self.kodi_labels_to_html(heading)
|
||||
JsonData = {}
|
||||
JsonData["action"] = "AlertYesNo"
|
||||
JsonData["data"] = {}
|
||||
JsonData["data"]["title"] = heading
|
||||
JsonData["data"]["text"] = text
|
||||
ID = self.send_message(JsonData)
|
||||
response = self.get_data(ID)
|
||||
return response
|
||||
|
||||
def dialog_select(self, heading, list):
|
||||
JsonData = {}
|
||||
heading = self.kodi_labels_to_html(heading)
|
||||
JsonData["action"] = "List"
|
||||
JsonData["data"] = {}
|
||||
JsonData["data"]["title"] = heading
|
||||
JsonData["data"]["list"] = []
|
||||
for Elemento in list:
|
||||
JsonData["data"]["list"].append(self.kodi_labels_to_html(Elemento))
|
||||
ID = self.send_message(JsonData)
|
||||
response = self.get_data(ID)
|
||||
|
||||
return response
|
||||
|
||||
def dialog_progress(self, heading, line1, line2="", line3=""):
|
||||
class Dialog(object):
|
||||
def __init__(self, heading, line1, line2, line3, platformtools):
|
||||
self.platformtools = platformtools
|
||||
self.closed = False
|
||||
self.heading = self.platformtools.kodi_labels_to_html(heading)
|
||||
text = line1
|
||||
if line2: text += "\n" + line2
|
||||
if line3: text += "\n" + line3
|
||||
text = self.platformtools.kodi_labels_to_html(text)
|
||||
JsonData = {}
|
||||
JsonData["action"] = "Progress"
|
||||
JsonData["data"] = {}
|
||||
JsonData["data"]["title"] = heading
|
||||
JsonData["data"]["text"] = text
|
||||
JsonData["data"]["percent"] = 0
|
||||
|
||||
ID = self.platformtools.send_message(JsonData)
|
||||
self.platformtools.get_data(ID)
|
||||
|
||||
def iscanceled(self):
|
||||
JsonData = {}
|
||||
JsonData["action"] = "ProgressIsCanceled"
|
||||
JsonData["data"] = {}
|
||||
ID = self.platformtools.send_message(JsonData)
|
||||
response = self.platformtools.get_data(ID)
|
||||
|
||||
return response
|
||||
|
||||
def update(self, percent, line1, line2="", line3=""):
|
||||
text = line1
|
||||
if line2: text += "\n" + line2
|
||||
if line3: text += "\n" + line3
|
||||
text = self.platformtools.kodi_labels_to_html(text)
|
||||
JsonData = {}
|
||||
JsonData["action"] = "ProgressUpdate"
|
||||
JsonData["data"] = {}
|
||||
JsonData["data"]["title"] = self.heading
|
||||
JsonData["data"]["text"] = text
|
||||
JsonData["data"]["percent"] = percent
|
||||
self.platformtools.send_message(JsonData)
|
||||
|
||||
def close(self):
|
||||
JsonData = {}
|
||||
JsonData["action"] = "ProgressClose"
|
||||
JsonData["data"] = {}
|
||||
ID = self.platformtools.send_message(JsonData)
|
||||
self.platformtools.get_data(ID)
|
||||
self.closed = True
|
||||
|
||||
return Dialog(heading, line1, line2, line3, self)
|
||||
|
||||
def dialog_progress_bg(self, heading, message=""):
|
||||
class Dialog(object):
|
||||
def __init__(self, heading, message, platformtools):
|
||||
self.platformtools = platformtools
|
||||
self.closed = False
|
||||
self.heading = self.platformtools.kodi_labels_to_html(heading)
|
||||
message = self.platformtools.kodi_labels_to_html(message)
|
||||
JsonData = {}
|
||||
JsonData["action"] = "ProgressBG"
|
||||
JsonData["data"] = {}
|
||||
JsonData["data"]["title"] = heading
|
||||
JsonData["data"]["text"] = message
|
||||
JsonData["data"]["percent"] = 0
|
||||
|
||||
ID = self.platformtools.send_message(JsonData)
|
||||
self.platformtools.get_data(ID)
|
||||
|
||||
def isFinished(self):
|
||||
return not self.closed
|
||||
|
||||
def update(self, percent=0, heading="", message=""):
|
||||
JsonData = {}
|
||||
JsonData["action"] = "ProgressBGUpdate"
|
||||
JsonData["data"] = {}
|
||||
JsonData["data"]["title"] = self.platformtools.kodi_labels_to_html(heading)
|
||||
JsonData["data"]["text"] = self.platformtools.kodi_labels_to_html(message)
|
||||
JsonData["data"]["percent"] = percent
|
||||
self.platformtools.send_message(JsonData)
|
||||
|
||||
def close(self):
|
||||
JsonData = {}
|
||||
JsonData["action"] = "ProgressBGClose"
|
||||
JsonData["data"] = {}
|
||||
ID = self.platformtools.send_message(JsonData)
|
||||
self.platformtools.get_data(ID)
|
||||
self.closed = True
|
||||
|
||||
return Dialog(heading, message, self)
|
||||
|
||||
def dialog_input(self, default="", heading="", hidden=False):
|
||||
JsonData = {}
|
||||
JsonData["action"] = "Keyboard"
|
||||
JsonData["data"] = {}
|
||||
JsonData["data"]["title"] = self.kodi_labels_to_html(heading)
|
||||
JsonData["data"]["text"] = default
|
||||
JsonData["data"]["password"] = hidden
|
||||
ID = self.send_message(JsonData)
|
||||
response = self.get_data(ID)
|
||||
|
||||
return response
|
||||
|
||||
def dialog_numeric(self, type, heading, default=""):
|
||||
return self.dialog_input("", heading, False)
|
||||
|
||||
def itemlist_refresh(self):
|
||||
JsonData = {}
|
||||
JsonData["action"] = "Refresh"
|
||||
JsonData["data"] = {}
|
||||
ID = self.send_message(JsonData)
|
||||
self.get_data(ID)
|
||||
|
||||
def itemlist_update(self, item):
|
||||
JsonData = {}
|
||||
JsonData["action"] = "Update"
|
||||
JsonData["data"] = {}
|
||||
JsonData["data"]["url"] = item.tourl()
|
||||
ID = self.send_message(JsonData)
|
||||
|
||||
self.get_data(ID)
|
||||
|
||||
def is_playing(self):
|
||||
JsonData = {}
|
||||
JsonData["action"] = "isPlaying"
|
||||
JsonData["data"] = {}
|
||||
ID = self.send_message(JsonData)
|
||||
response = self.get_data(ID)
|
||||
return response
|
||||
|
||||
def play_video(self, item):
|
||||
if item.contentTitle:
|
||||
title = item.contentTitle
|
||||
elif item.fulltitle:
|
||||
title = item.fulltitle
|
||||
else:
|
||||
title = item.title
|
||||
|
||||
if item.contentPlot:
|
||||
plot = item.contentPlot
|
||||
else:
|
||||
plot = item.plot
|
||||
|
||||
if item.server == "torrent":
|
||||
self.play_torrent(item)
|
||||
else:
|
||||
JsonData = {}
|
||||
JsonData["action"] = "Play"
|
||||
JsonData["data"] = {}
|
||||
JsonData["data"]["title"] = title
|
||||
JsonData["data"]["plot"] = plot
|
||||
JsonData["data"]["video_url"] = item.video_url
|
||||
JsonData["data"]["url"] = item.url
|
||||
JsonData["data"]["host"] = self.controller.host
|
||||
ID = self.send_message(JsonData)
|
||||
self.get_data(ID)
|
||||
|
||||
def play_torrent(self, item):
|
||||
import time
|
||||
import os
|
||||
played = False
|
||||
|
||||
# Importamos el cliente
|
||||
from btserver import Client
|
||||
|
||||
# Iniciamos el cliente:
|
||||
c = Client(url=item.url, is_playing_fnc=self.is_playing, wait_time=None, timeout=5,
|
||||
temp_path=os.path.join(config.get_data_path(), "torrent"))
|
||||
|
||||
# Mostramos el progreso
|
||||
progreso = self.dialog_progress("Alfa - Torrent", "Iniciando...")
|
||||
|
||||
# Mientras el progreso no sea cancelado ni el cliente cerrado
|
||||
while not progreso.iscanceled() and not c.closed:
|
||||
try:
|
||||
# Obtenemos el estado del torrent
|
||||
s = c.status
|
||||
|
||||
# Montamos las tres lineas con la info del torrent
|
||||
txt = '%.2f%% de %.1fMB %s | %.1f kB/s' % \
|
||||
(s.progress_file, s.file_size, s.str_state, s._download_rate)
|
||||
txt2 = 'S: %d(%d) P: %d(%d) | DHT:%s (%d) | Trakers: %d' % \
|
||||
(
|
||||
s.num_seeds, s.num_complete, s.num_peers, s.num_incomplete, s.dht_state, s.dht_nodes,
|
||||
s.trackers)
|
||||
txt3 = 'Origen Peers TRK: %d DHT: %d PEX: %d LSD %d ' % \
|
||||
(s.trk_peers, s.dht_peers, s.pex_peers, s.lsd_peers)
|
||||
|
||||
progreso.update(s.buffer, txt, txt2, txt3)
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
# Si el buffer se ha llenado y la reproduccion no ha sido iniciada, se inicia
|
||||
if s.buffer == 100 and not played:
|
||||
|
||||
# Cerramos el progreso
|
||||
progreso.close()
|
||||
|
||||
# Obtenemos el playlist del torrent
|
||||
item.video_url = c.get_play_list()
|
||||
item.server = "directo"
|
||||
|
||||
self.play_video(item)
|
||||
|
||||
# Marcamos como reproducido para que no se vuelva a iniciar
|
||||
played = True
|
||||
|
||||
# Y esperamos a que el reproductor se cierre
|
||||
while self.is_playing():
|
||||
time.sleep(1)
|
||||
|
||||
# Cuando este cerrado, Volvemos a mostrar el dialogo
|
||||
progreso = self.dialog_progress("Alfa - Torrent", "Iniciando...")
|
||||
|
||||
except:
|
||||
import traceback
|
||||
logger.info(traceback.format_exc())
|
||||
break
|
||||
|
||||
progreso.update(100, "Terminando y eliminando datos", " ", " ")
|
||||
|
||||
# Detenemos el cliente
|
||||
if not c.closed:
|
||||
c.stop()
|
||||
|
||||
# Y cerramos el progreso
|
||||
progreso.close()
|
||||
|
||||
return
|
||||
|
||||
def open_settings(self, items):
|
||||
from platformcode import config
|
||||
JsonData = {}
|
||||
JsonData["action"] = "OpenConfig"
|
||||
JsonData["data"] = {}
|
||||
JsonData["data"]["title"] = "Opciones"
|
||||
JsonData["data"]["items"] = []
|
||||
|
||||
for item in items:
|
||||
if item.get('option') == 'hidden':
|
||||
item['hidden'] = True
|
||||
|
||||
for key in item:
|
||||
if key in ["lvalues", "label", "category"]:
|
||||
try:
|
||||
ops = item[key].split("|")
|
||||
for x, op in enumerate(ops):
|
||||
ops[x] = config.get_localized_string(int(ops[x]))
|
||||
item[key] = "|".join(ops)
|
||||
except:
|
||||
pass
|
||||
|
||||
JsonData["data"]["items"].append(item)
|
||||
ID = self.send_message(JsonData)
|
||||
|
||||
response = self.get_data(ID)
|
||||
|
||||
if response:
|
||||
from platformcode import config
|
||||
config.set_settings(response)
|
||||
JsonData = {}
|
||||
JsonData["action"] = "HideLoading"
|
||||
JsonData["data"] = {}
|
||||
self.send_message(JsonData)
|
||||
|
||||
def show_channel_settings(self, list_controls=None, dict_values=None, caption="", callback=None, item=None,
|
||||
custom_button=None, channelpath=None):
|
||||
from platformcode import config
|
||||
from core import channeltools
|
||||
from core import servertools
|
||||
import inspect
|
||||
if not os.path.isdir(os.path.join(config.get_data_path(), "settings_channels")):
|
||||
os.mkdir(os.path.join(config.get_data_path(), "settings_channels"))
|
||||
|
||||
title = caption
|
||||
|
||||
if type(custom_button) == dict:
|
||||
custom_button = {"label": custom_button.get("label", ""),
|
||||
"function": custom_button.get("function", ""),
|
||||
"visible": bool(custom_button.get("visible", True)),
|
||||
"close": bool(custom_button.get("close", False))}
|
||||
|
||||
else:
|
||||
custom_button = None
|
||||
|
||||
# Obtenemos el canal desde donde se ha echo la llamada y cargamos los settings disponibles para ese canal
|
||||
if not channelpath:
|
||||
channelpath = inspect.currentframe().f_back.f_back.f_code.co_filename
|
||||
channelname = os.path.basename(channelpath).replace(".py", "")
|
||||
ch_type = os.path.basename(os.path.dirname(channelpath))
|
||||
|
||||
# Si no tenemos list_controls, hay que sacarlos del json del canal
|
||||
if not list_controls:
|
||||
|
||||
# Si la ruta del canal esta en la carpeta "channels", obtenemos los controles y valores mediante chaneltools
|
||||
if os.path.join(config.get_runtime_path(), "channels") in channelpath:
|
||||
|
||||
# La llamada se hace desde un canal
|
||||
list_controls, default_values = channeltools.get_channel_controls_settings(channelname)
|
||||
kwargs = {"channel": channelname}
|
||||
|
||||
# Si la ruta del canal esta en la carpeta "servers", obtenemos los controles y valores mediante servertools
|
||||
elif os.path.join(config.get_runtime_path(), "servers") in channelpath:
|
||||
# La llamada se hace desde un server
|
||||
list_controls, default_values = servertools.get_server_controls_settings(channelname)
|
||||
kwargs = {"server": channelname}
|
||||
|
||||
# En caso contrario salimos
|
||||
else:
|
||||
return None
|
||||
|
||||
# Si no se pasan dict_values, creamos un dict en blanco
|
||||
if dict_values == None:
|
||||
dict_values = {}
|
||||
|
||||
# Ponemos el titulo
|
||||
if caption == "":
|
||||
caption = str(config.get_localized_string(30100)) + " -- " + channelname.capitalize()
|
||||
elif caption.startswith('@') and unicode(caption[1:]).isnumeric():
|
||||
caption = config.get_localized_string(int(caption[1:]))
|
||||
|
||||
JsonData = {}
|
||||
JsonData["action"] = "OpenConfig"
|
||||
JsonData["data"] = {}
|
||||
JsonData["data"]["title"] = self.kodi_labels_to_html(caption)
|
||||
JsonData["data"]["custom_button"] = custom_button
|
||||
JsonData["data"]["items"] = []
|
||||
|
||||
# Añadir controles
|
||||
for c in list_controls:
|
||||
if not "default" in c: c["default"] = ""
|
||||
if not "color" in c: c["color"] = "auto"
|
||||
if not "label" in c: continue
|
||||
|
||||
# Obtenemos el valor
|
||||
if not c["id"] in dict_values:
|
||||
if not callback:
|
||||
c["value"] = config.get_setting(c["id"], **kwargs)
|
||||
else:
|
||||
c["value"] = c["default"]
|
||||
|
||||
dict_values[c["id"]] = c["value"]
|
||||
|
||||
else:
|
||||
c["value"] = dict_values[c["id"]]
|
||||
|
||||
# Translation
|
||||
if c['label'].startswith('@') and unicode(c['label'][1:]).isnumeric():
|
||||
c['label'] = str(config.get_localized_string(c['label'][1:]))
|
||||
if c["label"].endswith(":"): c["label"] = c["label"][:-1]
|
||||
|
||||
if c['type'] == 'list':
|
||||
lvalues = []
|
||||
for li in c['lvalues']:
|
||||
if li.startswith('@') and unicode(li[1:]).isnumeric():
|
||||
lvalues.append(str(config.get_localized_string(li[1:])))
|
||||
else:
|
||||
lvalues.append(li)
|
||||
c['lvalues'] = lvalues
|
||||
|
||||
c["label"] = self.kodi_labels_to_html(c["label"])
|
||||
|
||||
JsonData["data"]["items"].append(c)
|
||||
|
||||
ID = self.send_message(JsonData)
|
||||
close = False
|
||||
|
||||
while True:
|
||||
data = self.get_data(ID)
|
||||
if type(data) == dict:
|
||||
JsonData["action"] = "HideLoading"
|
||||
JsonData["data"] = {}
|
||||
self.send_message(JsonData)
|
||||
|
||||
for v in data:
|
||||
if data[v] == "true": data[v] = True
|
||||
if data[v] == "false": data[v] = False
|
||||
if unicode(data[v]).isnumeric(): data[v] = int(data[v])
|
||||
|
||||
if callback and '.' in callback:
|
||||
package, callback = callback.rsplit('.', 1)
|
||||
else:
|
||||
package = '%s.%s' % (ch_type, channelname)
|
||||
|
||||
cb_channel = None
|
||||
try:
|
||||
cb_channel = __import__(package, None, None, [package])
|
||||
except ImportError:
|
||||
logger.error('Imposible importar %s' % package)
|
||||
|
||||
if callback:
|
||||
# Si existe una funcion callback la invocamos ...
|
||||
return getattr(cb_channel, callback)(item, data)
|
||||
else:
|
||||
# si no, probamos si en el canal existe una funcion 'cb_validate_config' ...
|
||||
try:
|
||||
return getattr(cb_channel, 'cb_validate_config')(item, data)
|
||||
except AttributeError:
|
||||
# ... si tampoco existe 'cb_validate_config'...
|
||||
for v in data:
|
||||
config.set_setting(v, data[v], **kwargs)
|
||||
|
||||
elif data == "custom_button":
|
||||
if '.' in callback:
|
||||
package, callback = callback.rsplit('.', 1)
|
||||
else:
|
||||
package = '%s.%s' % (ch_type, channelname)
|
||||
try:
|
||||
cb_channel = __import__(package, None, None, [package])
|
||||
except ImportError:
|
||||
logger.error('Imposible importar %s' % package)
|
||||
else:
|
||||
return_value = getattr(cb_channel, custom_button['function'])(item, dict_values)
|
||||
if custom_button["close"] == True:
|
||||
return return_value
|
||||
else:
|
||||
JsonData["action"] = "custom_button"
|
||||
JsonData["data"] = {}
|
||||
JsonData["data"]["values"] = dict_values
|
||||
JsonData["data"]["return_value"] = return_value
|
||||
ID = self.send_message(JsonData)
|
||||
|
||||
elif data == False:
|
||||
return None
|
||||
|
||||
def show_video_info(self, data, caption="", item=None, scraper=Tmdb):
|
||||
from platformcode import html_info_window
|
||||
return html_info_window.InfoWindow().start(self, data, caption, item, scraper)
|
||||
|
||||
def show_recaptcha(self, key, url):
|
||||
from platformcode import html_recaptcha
|
||||
return html_recaptcha.recaptcha().start(self, key, url)
|
||||
|
||||
def kodi_labels_to_html(self, text):
|
||||
text = re.sub(r"(?:\[I\])(.*?)(?:\[/I\])", r"<i>\1</i>", text)
|
||||
text = re.sub(r"(?:\[B\])(.*?)(?:\[/B\])", r"<b>\1</b>", text)
|
||||
text = re.sub(r"(?:\[COLOR (?:0x)?([0-f]{2})([0-f]{2})([0-f]{2})([0-f]{2})\])(.*?)(?:\[/COLOR\])",
|
||||
lambda m: "<span style='color: rgba(%s,%s,%s,%s)'>%s</span>" % (
|
||||
int(m.group(2), 16), int(m.group(3), 16), int(m.group(4), 16), int(m.group(1), 16) / 255.0,
|
||||
m.group(5)), text)
|
||||
text = re.sub(r"(?:\[COLOR (?:0x)?([0-f]{2})([0-f]{2})([0-f]{2})\])(.*?)(?:\[/COLOR\])",
|
||||
r"<span style='color: #\1\2\3'>\4</span>", text)
|
||||
text = re.sub(r"(?:\[COLOR (?:0x)?([a-z|A-Z]+)\])(.*?)(?:\[/COLOR\])", r"<span style='color: \1'>\2</span>",
|
||||
text)
|
||||
return text
|
||||
188
mediaserver/platformcode/controllers/jsonserver.py
Normal file
188
mediaserver/platformcode/controllers/jsonserver.py
Normal file
@@ -0,0 +1,188 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------------------------------
|
||||
# Controlador para RSS
|
||||
# ------------------------------------------------------------
|
||||
import json
|
||||
import random
|
||||
import re
|
||||
import threading
|
||||
import time
|
||||
|
||||
from controller import Controller
|
||||
from controller import Platformtools
|
||||
from core.item import Item
|
||||
|
||||
|
||||
class jsonserver(Controller):
|
||||
pattern = re.compile("^/json")
|
||||
data = {}
|
||||
|
||||
def __init__(self, handler=None):
|
||||
super(jsonserver, self).__init__(handler)
|
||||
self.platformtools = platformtools(self)
|
||||
|
||||
def extract_item(self, path):
|
||||
if path == "/json" or path == "/json/":
|
||||
item = Item(channel="channelselector", action="mainlist")
|
||||
else:
|
||||
item = Item().fromurl(path.replace("/json/", ""))
|
||||
return item
|
||||
|
||||
def run(self, path):
|
||||
item = self.extract_item(path)
|
||||
from platformcode import launcher
|
||||
launcher.run(item)
|
||||
|
||||
def set_data(self, data):
|
||||
self.data = data
|
||||
|
||||
def get_data(self, id):
|
||||
if "id" in self.data and self.data["id"] == id:
|
||||
data = self.data["result"]
|
||||
else:
|
||||
data = None
|
||||
return data
|
||||
|
||||
def send_data(self, data, headers={}, response=200):
|
||||
headers.setdefault("content-type", "application/json")
|
||||
headers.setdefault("connection", "close")
|
||||
self.handler.send_response(response)
|
||||
for header in headers:
|
||||
self.handler.send_header(header, headers[header])
|
||||
self.handler.end_headers()
|
||||
self.handler.wfile.write(data)
|
||||
|
||||
|
||||
class platformtools(Platformtools):
|
||||
def __init__(self, controller):
|
||||
self.controller = controller
|
||||
self.handler = controller.handler
|
||||
|
||||
def render_items(self, itemlist, parentitem):
|
||||
JSONResponse = {}
|
||||
JSONResponse["title"] = parentitem.title
|
||||
JSONResponse["date"] = time.strftime("%x")
|
||||
JSONResponse["time"] = time.strftime("%X")
|
||||
JSONResponse["count"] = len(itemlist)
|
||||
JSONResponse["list"] = []
|
||||
for item in itemlist:
|
||||
JSONItem = {}
|
||||
JSONItem["title"] = item.title
|
||||
JSONItem["url"] = "http://" + self.controller.host + "/json/" + item.tourl()
|
||||
if item.thumbnail: JSONItem["thumbnail"] = item.thumbnail
|
||||
if item.plot: JSONItem["plot"] = item.plot
|
||||
JSONResponse["list"].append(JSONItem)
|
||||
|
||||
self.controller.send_data(json.dumps(JSONResponse, indent=4, sort_keys=True))
|
||||
|
||||
def dialog_select(self, heading, list):
|
||||
ID = "%032x" % (random.getrandbits(128))
|
||||
response = '<?xml version="1.0" encoding="UTF-8" ?>\n'
|
||||
response += '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">\n'
|
||||
response += '<channel>\n'
|
||||
response += '<link>/rss</link>\n'
|
||||
response += '<title>' + heading + '</title>\n'
|
||||
for option in list:
|
||||
response += '<item>\n'
|
||||
response += '<title>' + option + '</title>\n'
|
||||
response += '<image>%s</image>\n'
|
||||
response += '<link>http://' + self.controller.host + '/data/' + threading.current_thread().name + '/' + ID + '/' + str(
|
||||
list.index(option)) + '</link>\n'
|
||||
response += '</item>\n\n'
|
||||
|
||||
response += '</channel>\n'
|
||||
response += '</rss>\n'
|
||||
self.controller.send_data(response)
|
||||
|
||||
self.handler.server.shutdown_request(self.handler.request)
|
||||
while not self.controller.get_data(ID):
|
||||
continue
|
||||
|
||||
return int(self.controller.get_data(ID))
|
||||
|
||||
def dialog_ok(self, heading, line1, line2="", line3=""):
|
||||
text = line1
|
||||
if line2: text += "\n" + line2
|
||||
if line3: text += "\n" + line3
|
||||
ID = "%032x" % (random.getrandbits(128))
|
||||
response = '<?xml version="1.0" encoding="UTF-8" ?>\n'
|
||||
response += '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">\n'
|
||||
response += '<channel>\n'
|
||||
response += '<link>/rss</link>\n'
|
||||
response += '<title>' + heading + '</title>\n'
|
||||
response += '<item>\n'
|
||||
response += '<title>' + text + '</title>\n'
|
||||
response += '<image>%s</image>\n'
|
||||
response += '<link></link>\n'
|
||||
response += '</item>\n\n'
|
||||
response += '<item>\n'
|
||||
response += '<title>Si</title>\n'
|
||||
response += '<image>%s</image>\n'
|
||||
response += '<link>http://' + self.controller.host + '/data/' + threading.current_thread().name + '/' + ID + '/1</link>\n'
|
||||
response += '</item>\n\n'
|
||||
response += '<item>\n'
|
||||
|
||||
response += '</channel>\n'
|
||||
response += '</rss>\n'
|
||||
self.controller.send_data(response)
|
||||
|
||||
self.handler.server.shutdown_request(self.handler.request)
|
||||
while not self.controller.get_data(ID):
|
||||
continue
|
||||
|
||||
def dialog_yesno(self, heading, line1, line2="", line3=""):
|
||||
text = line1
|
||||
if line2: text += "\n" + line2
|
||||
if line3: text += "\n" + line3
|
||||
ID = "%032x" % (random.getrandbits(128))
|
||||
response = '<?xml version="1.0" encoding="UTF-8" ?>\n'
|
||||
response += '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">\n'
|
||||
response += '<channel>\n'
|
||||
response += '<link>/rss</link>\n'
|
||||
response += '<title>' + heading + '</title>\n'
|
||||
response += '<item>\n'
|
||||
response += '<title>' + text + '</title>\n'
|
||||
response += '<image>%s</image>\n'
|
||||
response += '<link></link>\n'
|
||||
response += '</item>\n\n'
|
||||
response += '<item>\n'
|
||||
response += '<title>Si</title>\n'
|
||||
response += '<image>%s</image>\n'
|
||||
response += '<link>http://' + self.controller.host + '/data/' + threading.current_thread().name + '/' + ID + '/1</link>\n'
|
||||
response += '</item>\n\n'
|
||||
response += '<item>\n'
|
||||
response += '<title>No</title>\n'
|
||||
response += '<image>%s</image>\n'
|
||||
response += '<link>http://' + self.controller.host + '/data/' + threading.current_thread().name + '/' + ID + '/0</link>\n'
|
||||
response += '</item>\n\n'
|
||||
|
||||
response += '</channel>\n'
|
||||
response += '</rss>\n'
|
||||
self.controller.send_data(response)
|
||||
|
||||
self.handler.server.shutdown_request(self.handler.request)
|
||||
while not self.controller.get_data(ID):
|
||||
continue
|
||||
|
||||
return bool(int(self.controller.get_data(ID)))
|
||||
|
||||
def dialog_notification(self, heading, message, icon=0, time=5000, sound=True):
|
||||
# No disponible por ahora, muestra un dialog_ok
|
||||
self.dialog_ok(heading, message)
|
||||
|
||||
def play_video(self, item):
|
||||
response = '<?xml version="1.0" encoding="UTF-8" ?>\n'
|
||||
response += '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">\n'
|
||||
response += '<channel>\n'
|
||||
response += '<link>/rss</link>\n'
|
||||
response += '<title>' + item.title + '</title>\n'
|
||||
response += '<item>\n'
|
||||
response += '<title>' + item.title + '</title>\n'
|
||||
response += '<image>%s</image>\n'
|
||||
response += '<link>' + item.video_url + '</link>\n'
|
||||
response += '</item>\n\n'
|
||||
|
||||
response += '</channel>\n'
|
||||
response += '</rss>\n'
|
||||
|
||||
self.controller.send_data(response)
|
||||
58
mediaserver/platformcode/controllers/proxy.py
Normal file
58
mediaserver/platformcode/controllers/proxy.py
Normal file
@@ -0,0 +1,58 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------------------------------
|
||||
# Controlador para acceso indirecto a ficheros remotos
|
||||
# ------------------------------------------------------------
|
||||
import base64
|
||||
import re
|
||||
import urllib
|
||||
import urllib2
|
||||
|
||||
from controller import Controller
|
||||
|
||||
|
||||
class proxy(Controller):
|
||||
pattern = re.compile("^/proxy/")
|
||||
|
||||
def run(self, path):
|
||||
url = path.replace("/proxy/", "").split("/")[0]
|
||||
url = base64.b64decode(urllib.unquote_plus(url))
|
||||
|
||||
request_headers = self.handler.headers.dict
|
||||
|
||||
if "host" in request_headers: request_headers.pop("host")
|
||||
if "referer" in request_headers: request_headers.pop("referer")
|
||||
if "cookie" in request_headers: request_headers.pop("cookie")
|
||||
|
||||
if "|" in url:
|
||||
url_headers = dict(
|
||||
[[header.split("=")[0].lower(), urllib.unquote_plus("=".join(header.split("=")[1:]))] for header in
|
||||
url.split("|")[1].split("&")])
|
||||
url = url.split("|")[0]
|
||||
request_headers.update(url_headers)
|
||||
|
||||
req = urllib2.Request(url, headers=request_headers)
|
||||
opener = urllib2.build_opener(urllib2.HTTPHandler(debuglevel=0))
|
||||
|
||||
try:
|
||||
h = opener.open(req)
|
||||
except urllib2.HTTPError, e:
|
||||
h = e
|
||||
except:
|
||||
self.handler.send_response("503")
|
||||
self.handler.wfile.close()
|
||||
h.close()
|
||||
|
||||
self.handler.send_response(h.getcode())
|
||||
for header in h.info():
|
||||
self.handler.send_header(header, h.info()[header])
|
||||
|
||||
self.handler.end_headers()
|
||||
|
||||
blocksize = 1024
|
||||
bloqueleido = h.read(blocksize)
|
||||
while len(bloqueleido) > 0:
|
||||
self.handler.wfile.write(bloqueleido)
|
||||
bloqueleido = h.read(blocksize)
|
||||
|
||||
self.handler.wfile.close()
|
||||
h.close()
|
||||
199
mediaserver/platformcode/controllers/rss.py
Normal file
199
mediaserver/platformcode/controllers/rss.py
Normal file
@@ -0,0 +1,199 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------------------------------
|
||||
# Controlador para RSS
|
||||
# ------------------------------------------------------------
|
||||
import random
|
||||
import re
|
||||
import threading
|
||||
|
||||
from controller import Controller
|
||||
from controller import Platformtools
|
||||
from core.item import Item
|
||||
|
||||
|
||||
class rss(Controller):
|
||||
pattern = re.compile("^/rss")
|
||||
data = {}
|
||||
|
||||
def __init__(self, handler=None, ):
|
||||
super(rss, self).__init__(handler)
|
||||
self.platformtools = platformtools(self)
|
||||
|
||||
def extract_item(self, path):
|
||||
if path == "/rss" or path == "/rss/":
|
||||
item = Item(channel="channelselector", action="mainlist")
|
||||
else:
|
||||
item = Item().fromurl(path.replace("/rss/", ""))
|
||||
return item
|
||||
|
||||
def run(self, path):
|
||||
item = self.extract_item(path)
|
||||
from platformcode import launcher
|
||||
launcher.run(item)
|
||||
|
||||
def set_data(self, data):
|
||||
self.data = data
|
||||
|
||||
def get_data(self, id):
|
||||
if "id" in self.data and self.data["id"] == id:
|
||||
data = self.data["result"]
|
||||
else:
|
||||
data = None
|
||||
return data
|
||||
|
||||
def send_data(self, data, headers={}, response=200):
|
||||
headers.setdefault("content-type", "application/rss+xml")
|
||||
headers.setdefault("connection", "close")
|
||||
self.handler.send_response(response)
|
||||
for header in headers:
|
||||
self.handler.send_header(header, headers[header])
|
||||
self.handler.end_headers()
|
||||
self.handler.wfile.write(data)
|
||||
|
||||
|
||||
class platformtools(Platformtools):
|
||||
def __init__(self, controller):
|
||||
self.controller = controller
|
||||
self.handler = controller.handler
|
||||
|
||||
def create_rss(self, itemlist):
|
||||
resp = '<?xml version="1.0" encoding="UTF-8" ?>\n'
|
||||
resp += '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">\n'
|
||||
resp += '<channel>\n'
|
||||
resp += '<link>http://' + self.controller.host + '/rss</link>\n'
|
||||
resp += '<title>Menú Principal</title>\n'
|
||||
for item in itemlist:
|
||||
resp += '<item>\n'
|
||||
resp += '<title>' + item.title + '</title>\n'
|
||||
resp += '<image>' + item.thumbnail + '</image>\n'
|
||||
resp += '<link>' + self.controller.host + '/rss/' + item.tourl() + '</link>\n'
|
||||
resp += '</item>\n\n'
|
||||
|
||||
resp += '</channel>\n'
|
||||
resp += '</rss>\n'
|
||||
|
||||
return resp
|
||||
|
||||
def render_items(self, itemlist, parentitem):
|
||||
new_itemlist = []
|
||||
for item in itemlist:
|
||||
# if item.action == "search": continue
|
||||
# if item.channel=="search": continue
|
||||
# if item.channel=="setting": continue
|
||||
# if item.channel=="help": continue
|
||||
new_itemlist.append(item)
|
||||
|
||||
response = self.create_rss(new_itemlist)
|
||||
self.controller.send_data(response)
|
||||
|
||||
def dialog_select(self, heading, list):
|
||||
ID = "%032x" % (random.getrandbits(128))
|
||||
response = '<?xml version="1.0" encoding="UTF-8" ?>\n'
|
||||
response += '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">\n'
|
||||
response += '<channel>\n'
|
||||
response += '<link>/rss</link>\n'
|
||||
response += '<title>' + heading + '</title>\n'
|
||||
for option in list:
|
||||
response += '<item>\n'
|
||||
response += '<title>' + option + '</title>\n'
|
||||
response += '<image>%s</image>\n'
|
||||
response += '<link>http://' + self.controller.host + '/data/' + threading.current_thread().name + '/' + ID + '/' + str(
|
||||
list.index(option)) + '</link>\n'
|
||||
response += '</item>\n\n'
|
||||
|
||||
response += '</channel>\n'
|
||||
response += '</rss>\n'
|
||||
self.controller.send_data(response)
|
||||
|
||||
self.handler.server.shutdown_request(self.handler.request)
|
||||
while not self.controller.get_data(ID):
|
||||
continue
|
||||
|
||||
return int(self.controller.get_data(ID))
|
||||
|
||||
def dialog_ok(self, heading, line1, line2="", line3=""):
|
||||
text = line1
|
||||
if line2: text += "\n" + line2
|
||||
if line3: text += "\n" + line3
|
||||
ID = "%032x" % (random.getrandbits(128))
|
||||
response = '<?xml version="1.0" encoding="UTF-8" ?>\n'
|
||||
response += '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">\n'
|
||||
response += '<channel>\n'
|
||||
response += '<link>/rss</link>\n'
|
||||
response += '<title>' + heading + '</title>\n'
|
||||
response += '<item>\n'
|
||||
response += '<title>' + text + '</title>\n'
|
||||
response += '<image>%s</image>\n'
|
||||
response += '<link></link>\n'
|
||||
response += '</item>\n\n'
|
||||
response += '<item>\n'
|
||||
response += '<title>Si</title>\n'
|
||||
response += '<image>%s</image>\n'
|
||||
response += '<link>http://' + self.controller.host + '/data/' + threading.current_thread().name + '/' + ID + '/1</link>\n'
|
||||
response += '</item>\n\n'
|
||||
response += '<item>\n'
|
||||
|
||||
response += '</channel>\n'
|
||||
response += '</rss>\n'
|
||||
self.controller.send_data(response)
|
||||
|
||||
self.handler.server.shutdown_request(self.handler.request)
|
||||
while not self.controller.get_data(ID):
|
||||
continue
|
||||
|
||||
def dialog_yesno(self, heading, line1, line2="", line3=""):
|
||||
text = line1
|
||||
if line2: text += "\n" + line2
|
||||
if line3: text += "\n" + line3
|
||||
ID = "%032x" % (random.getrandbits(128))
|
||||
response = '<?xml version="1.0" encoding="UTF-8" ?>\n'
|
||||
response += '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">\n'
|
||||
response += '<channel>\n'
|
||||
response += '<link>/rss</link>\n'
|
||||
response += '<title>' + heading + '</title>\n'
|
||||
response += '<item>\n'
|
||||
response += '<title>' + text + '</title>\n'
|
||||
response += '<image>%s</image>\n'
|
||||
response += '<link></link>\n'
|
||||
response += '</item>\n\n'
|
||||
response += '<item>\n'
|
||||
response += '<title>Si</title>\n'
|
||||
response += '<image>%s</image>\n'
|
||||
response += '<link>http://' + self.controller.host + '/data/' + threading.current_thread().name + '/' + ID + '/1</link>\n'
|
||||
response += '</item>\n\n'
|
||||
response += '<item>\n'
|
||||
response += '<title>No</title>\n'
|
||||
response += '<image>%s</image>\n'
|
||||
response += '<link>http://' + self.controller.host + '/data/' + threading.current_thread().name + '/' + ID + '/0</link>\n'
|
||||
response += '</item>\n\n'
|
||||
|
||||
response += '</channel>\n'
|
||||
response += '</rss>\n'
|
||||
self.controller.send_data(response)
|
||||
|
||||
self.handler.server.shutdown_request(self.handler.request)
|
||||
while not self.controller.get_data(ID):
|
||||
continue
|
||||
|
||||
return bool(int(self.controller.get_data(ID)))
|
||||
|
||||
def dialog_notification(self, heading, message, icon=0, time=5000, sound=True):
|
||||
# No disponible por ahora, muestra un dialog_ok
|
||||
self.dialog_ok(heading, message)
|
||||
|
||||
def play_video(self, item):
|
||||
response = '<?xml version="1.0" encoding="UTF-8" ?>\n'
|
||||
response += '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">\n'
|
||||
response += '<channel>\n'
|
||||
response += '<link>/rss</link>\n'
|
||||
response += '<title>' + item.title + '</title>\n'
|
||||
response += '<item>\n'
|
||||
response += '<title>' + item.title + '</title>\n'
|
||||
response += '<image>%s</image>\n'
|
||||
response += '<link>' + item.video_url + '</link>\n'
|
||||
response += '</item>\n\n'
|
||||
|
||||
response += '</channel>\n'
|
||||
response += '</rss>\n'
|
||||
|
||||
self.controller.send_data(response)
|
||||
173
mediaserver/platformcode/html_info_window.py
Normal file
173
mediaserver/platformcode/html_info_window.py
Normal file
@@ -0,0 +1,173 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from core.tmdb import Tmdb
|
||||
from platformcode import logger
|
||||
|
||||
|
||||
class InfoWindow(object):
|
||||
otmdb = None
|
||||
item_title = ""
|
||||
item_serie = ""
|
||||
item_temporada = 0
|
||||
item_episodio = 0
|
||||
result = {}
|
||||
|
||||
@staticmethod
|
||||
def get_language(lng):
|
||||
# Cambiamos el formato del Idioma
|
||||
languages = {
|
||||
'aa': 'Afar', 'ab': 'Abkhazian', 'af': 'Afrikaans', 'ak': 'Akan', 'sq': 'Albanian', 'am': 'Amharic',
|
||||
'ar': 'Arabic', 'an': 'Aragonese', 'as': 'Assamese', 'av': 'Avaric', 'ae': 'Avestan',
|
||||
'ay': 'Aymara', 'az': 'Azerbaijani', 'ba': 'Bashkir', 'bm': 'Bambara', 'eu': 'Basque',
|
||||
'be': 'Belarusian', 'bn': 'Bengali', 'bh': 'Bihari languages', 'bi': 'Bislama',
|
||||
'bo': 'Tibetan', 'bs': 'Bosnian', 'br': 'Breton', 'bg': 'Bulgarian', 'my': 'Burmese',
|
||||
'ca': 'Catalan; Valencian', 'cs': 'Czech', 'ch': 'Chamorro', 'ce': 'Chechen', 'zh': 'Chinese',
|
||||
'cu': 'Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic',
|
||||
'cv': 'Chuvash', 'kw': 'Cornish', 'co': 'Corsican', 'cr': 'Cree', 'cy': 'Welsh',
|
||||
'da': 'Danish', 'de': 'German', 'dv': 'Divehi; Dhivehi; Maldivian', 'nl': 'Dutch; Flemish',
|
||||
'dz': 'Dzongkha', 'en': 'English', 'eo': 'Esperanto',
|
||||
'et': 'Estonian', 'ee': 'Ewe', 'fo': 'Faroese', 'fa': 'Persian', 'fj': 'Fijian',
|
||||
'fi': 'Finnish', 'fr': 'French', 'fy': 'Western Frisian', 'ff': 'Fulah',
|
||||
'Ga': 'Georgian', 'gd': 'Gaelic; Scottish Gaelic', 'ga': 'Irish', 'gl': 'Galician',
|
||||
'gv': 'Manx', 'el': 'Greek, Modern (1453-)', 'gn': 'Guarani', 'gu': 'Gujarati',
|
||||
'ht': 'Haitian; Haitian Creole', 'ha': 'Hausa', 'he': 'Hebrew', 'hz': 'Herero', 'hi': 'Hindi',
|
||||
'ho': 'Hiri Motu', 'hr': 'Croatian', 'hu': 'Hungarian', 'hy': 'Armenian', 'ig': 'Igbo',
|
||||
'is': 'Icelandic', 'io': 'Ido', 'ii': 'Sichuan Yi; Nuosu', 'iu': 'Inuktitut',
|
||||
'ie': 'Interlingue; Occidental', 'ia': 'Interlingua (International Auxiliary Language Association)',
|
||||
'id': 'Indonesian', 'ik': 'Inupiaq', 'it': 'Italian', 'jv': 'Javanese',
|
||||
'ja': 'Japanese', 'kl': 'Kalaallisut; Greenlandic', 'kn': 'Kannada', 'ks': 'Kashmiri',
|
||||
'ka': 'Georgian', 'kr': 'Kanuri', 'kk': 'Kazakh', 'km': 'Central Khmer', 'ki': 'Kikuyu; Gikuyu',
|
||||
'rw': 'Kinyarwanda', 'ky': 'Kirghiz; Kyrgyz', 'kv': 'Komi', 'kg': 'Kongo', 'ko': 'Korean',
|
||||
'kj': 'Kuanyama; Kwanyama', 'ku': 'Kurdish', 'lo': 'Lao', 'la': 'Latin', 'lv': 'Latvian',
|
||||
'li': 'Limburgan; Limburger; Limburgish', 'ln': 'Lingala', 'lt': 'Lithuanian',
|
||||
'lb': 'Luxembourgish; Letzeburgesch', 'lu': 'Luba-Katanga', 'lg': 'Ganda', 'mk': 'Macedonian',
|
||||
'mh': 'Marshallese', 'ml': 'Malayalam', 'mi': 'Maori', 'mr': 'Marathi', 'ms': 'Malay', 'Mi': 'Micmac',
|
||||
'mg': 'Malagasy', 'mt': 'Maltese', 'mn': 'Mongolian', 'na': 'Nauru',
|
||||
'nv': 'Navajo; Navaho', 'nr': 'Ndebele, South; South Ndebele', 'nd': 'Ndebele, North; North Ndebele',
|
||||
'ng': 'Ndonga', 'ne': 'Nepali', 'nn': 'Norwegian Nynorsk; Nynorsk, Norwegian',
|
||||
'nb': 'Bokmål, Norwegian; Norwegian Bokmål', 'no': 'Norwegian', 'oc': 'Occitan (post 1500)',
|
||||
'oj': 'Ojibwa', 'or': 'Oriya', 'om': 'Oromo', 'os': 'Ossetian; Ossetic', 'pa': 'Panjabi; Punjabi',
|
||||
'pi': 'Pali', 'pl': 'Polish', 'pt': 'Portuguese', 'ps': 'Pushto; Pashto', 'qu': 'Quechua',
|
||||
'ro': 'Romanian; Moldavian; Moldovan', 'rn': 'Rundi', 'ru': 'Russian', 'sg': 'Sango', 'rm': 'Romansh',
|
||||
'sa': 'Sanskrit', 'si': 'Sinhala; Sinhalese', 'sk': 'Slovak', 'sl': 'Slovenian', 'se': 'Northern Sami',
|
||||
'sm': 'Samoan', 'sn': 'Shona', 'sd': 'Sindhi', 'so': 'Somali', 'st': 'Sotho, Southern', 'es': 'Spanish',
|
||||
'sc': 'Sardinian', 'sr': 'Serbian', 'ss': 'Swati', 'su': 'Sundanese', 'sw': 'Swahili', 'sv': 'Swedish',
|
||||
'ty': 'Tahitian', 'ta': 'Tamil', 'tt': 'Tatar', 'te': 'Telugu', 'tg': 'Tajik', 'tl': 'Tagalog',
|
||||
'th': 'Thai', 'ti': 'Tigrinya', 'to': 'Tonga (Tonga Islands)', 'tn': 'Tswana', 'ts': 'Tsonga',
|
||||
'tk': 'Turkmen', 'tr': 'Turkish', 'tw': 'Twi', 'ug': 'Uighur; Uyghur', 'uk': 'Ukrainian',
|
||||
'ur': 'Urdu', 'uz': 'Uzbek', 've': 'Venda', 'vi': 'Vietnamese', 'vo': 'Volapük',
|
||||
'wa': 'Walloon', 'wo': 'Wolof', 'xh': 'Xhosa', 'yi': 'Yiddish', 'yo': 'Yoruba', 'za': 'Zhuang; Chuang',
|
||||
'zu': 'Zulu'}
|
||||
|
||||
return languages.get(lng, lng)
|
||||
|
||||
def get_scraper_data(self, data_in):
|
||||
self.otmdb = None
|
||||
# logger.debug(str(data_in))
|
||||
|
||||
if self.listData:
|
||||
# Datos comunes a todos los listados
|
||||
infoLabels = self.scraper().get_infoLabels(origen=data_in)
|
||||
|
||||
if "original_language" in infoLabels:
|
||||
infoLabels["language"] = self.get_language(infoLabels["original_language"])
|
||||
if "vote_average" in data_in and "vote_count" in data_in:
|
||||
infoLabels["puntuacion"] = str(data_in["vote_average"]) + "/10 (" + str(data_in["vote_count"]) + ")"
|
||||
|
||||
self.result = infoLabels
|
||||
|
||||
def start(self, handler, data, caption="Información del vídeo", item=None, scraper=Tmdb):
|
||||
# Capturamos los parametros
|
||||
self.caption = caption
|
||||
self.item = item
|
||||
self.indexList = -1
|
||||
self.listData = []
|
||||
self.handler = handler
|
||||
self.scraper = scraper
|
||||
|
||||
logger.debug(data)
|
||||
if type(data) == list:
|
||||
self.listData = data
|
||||
self.indexList = 0
|
||||
data = self.listData[self.indexList]
|
||||
|
||||
self.get_scraper_data(data)
|
||||
|
||||
ID = self.update_window()
|
||||
|
||||
return self.onClick(ID)
|
||||
|
||||
def update_window(self):
|
||||
JsonData = {}
|
||||
JsonData["action"] = "OpenInfo"
|
||||
JsonData["data"] = {}
|
||||
JsonData["data"]["buttons"] = len(self.listData) > 0
|
||||
JsonData["data"]["previous"] = self.indexList > 0
|
||||
JsonData["data"]["next"] = self.indexList + 1 < len(self.listData)
|
||||
JsonData["data"]["count"] = "(%s/%s)" % (self.indexList + 1, len(self.listData))
|
||||
JsonData["data"]["title"] = self.caption
|
||||
JsonData["data"]["fanart"] = self.result.get("fanart", "")
|
||||
JsonData["data"]["thumbnail"] = self.result.get("thumbnail", "")
|
||||
|
||||
JsonData["data"]["lines"] = []
|
||||
|
||||
if self.result.get("mediatype", "movie") == "movie":
|
||||
JsonData["data"]["lines"].append({"title": "Título:", "text": self.result.get("title", "N/A")})
|
||||
JsonData["data"]["lines"].append(
|
||||
{"title": "Título Original:", "text": self.result.get("originaltitle", "N/A")})
|
||||
JsonData["data"]["lines"].append({"title": "Idioma Original:", "text": self.result.get("language", "N/A")})
|
||||
JsonData["data"]["lines"].append({"title": "Puntuación:", "text": self.result.get("puntuacion", "N/A")})
|
||||
JsonData["data"]["lines"].append({"title": "Lanzamiento:", "text": self.result.get("release_date", "N/A")})
|
||||
JsonData["data"]["lines"].append({"title": "Generos:", "text": self.result.get("genre", "N/A")})
|
||||
JsonData["data"]["lines"].append({"title": "", "text": ""})
|
||||
|
||||
|
||||
else:
|
||||
JsonData["data"]["lines"].append({"title": "Serie:", "text": self.result.get("title", "N/A")})
|
||||
JsonData["data"]["lines"].append({"title": "Idioma Original:", "text": self.result.get("language", "N/A")})
|
||||
JsonData["data"]["lines"].append({"title": "Puntuación:", "text": self.result.get("puntuacion", "N/A")})
|
||||
JsonData["data"]["lines"].append({"title": "Generos:", "text": self.result.get("genre", "N/A")})
|
||||
|
||||
if self.result.get("season"):
|
||||
JsonData["data"]["lines"].append(
|
||||
{"title": "Titulo temporada:", "text": self.result.get("temporada_nombre", "N/A")})
|
||||
JsonData["data"]["lines"].append({"title": "Temporada:",
|
||||
"text": self.result.get("season", "N/A") + " de " + self.result.get(
|
||||
"seasons", "N/A")})
|
||||
JsonData["data"]["lines"].append({"title": "", "text": ""})
|
||||
|
||||
if self.result.get("episode"):
|
||||
JsonData["data"]["lines"].append({"title": "Titulo:", "text": self.result.get("episode_title", "N/A")})
|
||||
JsonData["data"]["lines"].append({"title": "Episodio:",
|
||||
"text": self.result.get("episode", "N/A") + " de " + self.result.get(
|
||||
"episodes", "N/A")})
|
||||
JsonData["data"]["lines"].append({"title": "Emisión:", "text": self.result.get("date", "N/A")})
|
||||
|
||||
if self.result.get("plot"):
|
||||
JsonData["data"]["lines"].append({"title": "Sinopsis:", "text": self.result["plot"]})
|
||||
else:
|
||||
JsonData["data"]["lines"].append({"title": "", "text": ""})
|
||||
|
||||
ID = self.handler.send_message(JsonData)
|
||||
return ID
|
||||
|
||||
def onClick(self, ID):
|
||||
while True:
|
||||
response = self.handler.get_data(ID)
|
||||
|
||||
if response == "ok":
|
||||
return self.listData[self.indexList]
|
||||
|
||||
elif response == "close":
|
||||
return None
|
||||
|
||||
elif response == "next" and self.indexList < len(self.listData) - 1:
|
||||
self.indexList += 1
|
||||
self.get_scraper_data(self.listData[self.indexList])
|
||||
ID = self.update_window()
|
||||
|
||||
|
||||
elif response == "previous" and self.indexList > 0:
|
||||
self.indexList -= 1
|
||||
self.get_scraper_data(self.listData[self.indexList])
|
||||
ID = self.update_window()
|
||||
79
mediaserver/platformcode/html_recaptcha.py
Normal file
79
mediaserver/platformcode/html_recaptcha.py
Normal file
@@ -0,0 +1,79 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from core import httptools
|
||||
from core import scrapertools
|
||||
from platformcode import platformtools, logger
|
||||
|
||||
|
||||
class recaptcha(object):
|
||||
def start(self, handler, key, referer):
|
||||
self.handler = handler
|
||||
self.referer = referer
|
||||
self.key = key
|
||||
self.headers = {'Referer': self.referer}
|
||||
|
||||
api_js = httptools.downloadpage("http://www.google.com/recaptcha/api.js?hl=es").data
|
||||
version = scrapertools.find_single_match(api_js, 'po.src = \'(.*?)\';').split("/")[5]
|
||||
|
||||
self.url = "https://www.google.com/recaptcha/api/fallback?k=%s&hl=es&v=%s&t=2&ff=true" % (self.key, version)
|
||||
|
||||
ID = self.update_window()
|
||||
|
||||
return self.onClick(ID)
|
||||
|
||||
def update_window(self):
|
||||
data = httptools.downloadpage(self.url, headers=self.headers).data
|
||||
self.message = scrapertools.find_single_match(data,
|
||||
'<div class="rc-imageselect-desc-no-canonical">(.*?)(?:</label>|</div>)')
|
||||
self.token = scrapertools.find_single_match(data, 'name="c" value="([^"]+)"')
|
||||
self.image = "https://www.google.com/recaptcha/api2/payload?k=%s&c=%s" % (self.key, self.token)
|
||||
self.result = {}
|
||||
|
||||
JsonData = {}
|
||||
JsonData["action"] = "recaptcha"
|
||||
JsonData["data"] = {}
|
||||
JsonData["data"]["title"] = "reCaptcha"
|
||||
JsonData["data"]["image"] = self.image
|
||||
JsonData["data"]["message"] = self.message
|
||||
JsonData["data"]["selected"] = [int(k) for k in range(9) if self.result.get(k, False) == True]
|
||||
JsonData["data"]["unselected"] = [int(k) for k in range(9) if self.result.get(k, False) == False]
|
||||
ID = self.handler.send_message(JsonData)
|
||||
return ID
|
||||
|
||||
def onClick(self, ID):
|
||||
while True:
|
||||
response = self.handler.get_data(ID)
|
||||
|
||||
if type(response) == int:
|
||||
self.result[response] = not self.result.get(response, False)
|
||||
JsonData = {}
|
||||
JsonData["action"] = "recaptcha_select"
|
||||
JsonData["data"] = {}
|
||||
JsonData["data"]["selected"] = [int(k) for k in range(9) if self.result.get(k, False) == True]
|
||||
JsonData["data"]["unselected"] = [int(k) for k in range(9) if self.result.get(k, False) == False]
|
||||
self.handler.send_message(JsonData)
|
||||
|
||||
elif response == "refresh":
|
||||
ID = self.update_window()
|
||||
continue
|
||||
|
||||
elif response == True:
|
||||
post = "c=%s" % self.token
|
||||
for r in sorted([k for k, v in self.result.items() if v == True]):
|
||||
post += "&response=%s" % r
|
||||
logger.info(post)
|
||||
logger.info(self.result)
|
||||
data = httptools.downloadpage(self.url, post, headers=self.headers).data
|
||||
result = scrapertools.find_single_match(data, '<div class="fbc-verification-token">.*?>([^<]+)<')
|
||||
|
||||
if result:
|
||||
platformtools.dialog_notification("Captcha Correcto", "La verificación ha concluido")
|
||||
JsonData = {}
|
||||
JsonData["action"] = "ShowLoading"
|
||||
self.handler.send_message(JsonData)
|
||||
return result
|
||||
else:
|
||||
ID = self.update_window()
|
||||
|
||||
else:
|
||||
return
|
||||
523
mediaserver/platformcode/launcher.py
Normal file
523
mediaserver/platformcode/launcher.py
Normal file
@@ -0,0 +1,523 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------------------------------
|
||||
# Mediaserver Launcher
|
||||
# ------------------------------------------------------------
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
from core import channeltools
|
||||
from core import servertools
|
||||
from core import videolibrarytools
|
||||
from core.item import Item
|
||||
from platformcode import config, platformtools, logger
|
||||
|
||||
|
||||
def start():
|
||||
""" Primera funcion que se ejecuta al entrar en el plugin.
|
||||
Dentro de esta funcion deberian ir todas las llamadas a las
|
||||
funciones que deseamos que se ejecuten nada mas abrir el plugin.
|
||||
"""
|
||||
logger.info()
|
||||
|
||||
# Test if all the required directories are created
|
||||
config.verify_directories_created()
|
||||
import videolibrary_service
|
||||
videolibrary_service.start()
|
||||
|
||||
|
||||
def run(item):
|
||||
itemlist = []
|
||||
# Muestra el item en el log:
|
||||
PrintItems(item)
|
||||
|
||||
# Control Parental, comprueba si es adulto o no
|
||||
if item.action == "mainlist":
|
||||
# Parental control
|
||||
if channeltools.is_adult(item.channel) and config.get_setting("adult_pin") != "":
|
||||
tecleado = platformtools.dialog_input("", "Contraseña para canales de adultos", True)
|
||||
if tecleado is None or tecleado != config.get_setting("adult_pin"):
|
||||
platformtools.render_items(None, item)
|
||||
return
|
||||
|
||||
# Importa el canal para el item, todo item debe tener un canal, sino sale de la función
|
||||
if item.channel: channelmodule = ImportarCanal(item)
|
||||
|
||||
# If item has no action, stops here
|
||||
if item.action == "":
|
||||
logger.info("Item sin accion")
|
||||
itemlist = None
|
||||
|
||||
# Action Play, para mostrar el menú con las opciones de reproduccion.
|
||||
elif item.action == "play":
|
||||
logger.info("play")
|
||||
# Si el canal tiene una acción "play" tiene prioridad
|
||||
if hasattr(channelmodule, 'play'):
|
||||
logger.info("executing channel 'play' method")
|
||||
itemlist = channelmodule.play(item)
|
||||
b_favourite = item.isFavourite
|
||||
if len(itemlist) > 0 and isinstance(itemlist[0], Item):
|
||||
item = itemlist[0]
|
||||
if b_favourite:
|
||||
item.isFavourite = True
|
||||
play_menu(item)
|
||||
elif len(itemlist) > 0 and isinstance(itemlist[0], list):
|
||||
item.video_urls = itemlist
|
||||
play_menu(item)
|
||||
else:
|
||||
platformtools.dialog_ok("plugin", "No hay nada para reproducir")
|
||||
else:
|
||||
logger.info("no channel 'play' method, executing core method")
|
||||
play_menu(item)
|
||||
|
||||
itemlist = None
|
||||
|
||||
# Action Search, para mostrar el teclado y lanzar la busqueda con el texto indicado.
|
||||
elif item.action == "search":
|
||||
logger.info("search")
|
||||
tecleado = platformtools.dialog_input()
|
||||
if tecleado:
|
||||
itemlist = channelmodule.search(item, tecleado)
|
||||
else:
|
||||
itemlist = []
|
||||
|
||||
elif item.channel == "channelselector":
|
||||
import channelselector
|
||||
if item.action == "mainlist":
|
||||
itemlist = channelselector.getmainlist("banner_")
|
||||
|
||||
# if config.get_setting("check_for_plugin_updates"):
|
||||
# logger.info("channelselector.mainlist Verificar actualizaciones activado")
|
||||
#
|
||||
# from core import updater
|
||||
# try:
|
||||
# version = updater.checkforupdates()
|
||||
#
|
||||
# if version:
|
||||
# platformtools.dialog_ok("Versión " + version + " disponible",
|
||||
# "Ya puedes descargar la nueva versión del plugin\ndesde el listado principal")
|
||||
# itemlist.insert(0, Item(title="Actualizar Alfa a la versión " + version, version=version,
|
||||
# channel="updater", action="update",
|
||||
# thumbnail=os.path.join(config.get_runtime_path(), "resources", "images",
|
||||
# "banner", "thumb_update.png")))
|
||||
# except:
|
||||
# platformtools.dialog_ok("No se puede conectar", "No ha sido posible comprobar",
|
||||
# "si hay actualizaciones")
|
||||
# logger.info("Fallo al verificar la actualización")
|
||||
#
|
||||
# else:
|
||||
# logger.info("Verificar actualizaciones desactivado")
|
||||
|
||||
if item.action == "getchanneltypes":
|
||||
itemlist = channelselector.getchanneltypes("banner_")
|
||||
if item.action == "filterchannels":
|
||||
itemlist = channelselector.filterchannels(item.channel_type, "banner_")
|
||||
|
||||
# Todas las demas las intenta ejecturaren el siguiente orden:
|
||||
# 1. En el canal
|
||||
# 2. En el launcher
|
||||
# 3. Si no existe en el canal ni en el launcher guarda un error en el log
|
||||
else:
|
||||
# Si existe la funcion en el canal la ejecuta
|
||||
if hasattr(channelmodule, item.action):
|
||||
logger.info("Ejectuando accion: " + item.channel + "." + item.action + "(item)")
|
||||
exec "itemlist = channelmodule." + item.action + "(item)"
|
||||
|
||||
# Si existe la funcion en el launcher la ejecuta
|
||||
elif hasattr(sys.modules[__name__], item.action):
|
||||
logger.info("Ejectuando accion: " + item.action + "(item)")
|
||||
exec "itemlist =" + item.action + "(item)"
|
||||
|
||||
# Si no existe devuelve un error
|
||||
else:
|
||||
logger.info(
|
||||
"No se ha encontrado la accion [" + item.action + "] en el canal [" + item.channel + "] ni en el launcher")
|
||||
|
||||
# Llegados a este punto ya tenemos que tener el itemlist con los resultados correspondientes
|
||||
# Pueden darse 3 escenarios distintos:
|
||||
# 1. la función ha generado resultados y estan en el itemlist
|
||||
# 2. la función no ha generado resultados y por tanto el itemlist contiene 0 items, itemlist = []
|
||||
# 3. la función realiza alguna accion con la cual no se generan nuevos items, en ese caso el resultado deve ser: itemlist = None para que no modifique el listado
|
||||
# A partir de aquí ya se ha ejecutado la funcion en el lugar adecuado, si queremos realizar alguna acción sobre los resultados, este es el lugar.
|
||||
|
||||
|
||||
|
||||
# Filtrado de Servers
|
||||
if item.action == "findvideos":
|
||||
itemlist = servertools.filter_servers(itemlist)
|
||||
|
||||
# Si la accion no ha devuelto ningún resultado, añade un item con el texto "No hay elementos para mostrar"
|
||||
if type(itemlist) == list:
|
||||
if len(itemlist) == 0:
|
||||
from channelselector import get_thumb
|
||||
itemlist = [Item(title="No hay elementos para mostrar", thumbnail=get_thumb("error.png"))]
|
||||
|
||||
# Imprime en el log el resultado
|
||||
PrintItems(itemlist)
|
||||
|
||||
# Muestra los resultados en pantalla
|
||||
platformtools.render_items(itemlist, item)
|
||||
|
||||
|
||||
def ImportarCanal(item):
|
||||
channel = item.channel
|
||||
channelmodule = ""
|
||||
if os.path.exists(os.path.join(config.get_runtime_path(), "channels", channel + ".py")):
|
||||
exec "from channels import " + channel + " as channelmodule"
|
||||
elif os.path.exists(os.path.join(config.get_runtime_path(), "core", channel + ".py")):
|
||||
exec "from core import " + channel + " as channelmodule"
|
||||
elif os.path.exists(os.path.join(config.get_runtime_path(), channel + ".py")):
|
||||
exec "import " + channel + " as channelmodule"
|
||||
return channelmodule
|
||||
|
||||
|
||||
def PrintItems(itemlist):
|
||||
if type(itemlist) == list:
|
||||
if len(itemlist) > 0:
|
||||
logger.info("Items devueltos")
|
||||
logger.info("-----------------------------------------------------------------------")
|
||||
for item in itemlist:
|
||||
logger.info(item.tostring())
|
||||
logger.info("-----------------------------------------------------------------------")
|
||||
else:
|
||||
item = itemlist
|
||||
logger.info("-----------------------------------------------------------------------")
|
||||
logger.info(item.tostring())
|
||||
logger.info("-----------------------------------------------------------------------")
|
||||
|
||||
|
||||
def findvideos(item):
|
||||
logger.info()
|
||||
itemlist = servertools.find_video_items(item)
|
||||
return itemlist
|
||||
|
||||
|
||||
def add_pelicula_to_library(item):
|
||||
videolibrarytools.add_movie(item)
|
||||
|
||||
|
||||
def add_serie_to_library(item):
|
||||
channel = ImportarCanal(item)
|
||||
videolibrarytools.add_tvshow(item, channel)
|
||||
|
||||
|
||||
def download_all_episodes(item, first_episode="", preferred_server="vidspot", filter_language=""):
|
||||
logger.info("show=" + item.show)
|
||||
channel = ImportarCanal(item)
|
||||
show_title = item.show
|
||||
|
||||
# Obtiene el listado desde el que se llamó
|
||||
action = item.extra
|
||||
|
||||
# Esta marca es porque el item tiene algo más aparte en el atributo "extra"
|
||||
if "###" in item.extra:
|
||||
action = item.extra.split("###")[0]
|
||||
item.extra = item.extra.split("###")[1]
|
||||
|
||||
exec "episode_itemlist = channel." + action + "(item)"
|
||||
|
||||
# Ordena los episodios para que funcione el filtro de first_episode
|
||||
episode_itemlist = sorted(episode_itemlist, key=lambda Item: Item.title)
|
||||
|
||||
from core import downloadtools
|
||||
from core import scrapertools
|
||||
|
||||
best_server = preferred_server
|
||||
worst_server = "moevideos"
|
||||
|
||||
# Para cada episodio
|
||||
if first_episode == "":
|
||||
empezar = True
|
||||
else:
|
||||
empezar = False
|
||||
|
||||
for episode_item in episode_itemlist:
|
||||
try:
|
||||
logger.info("episode=" + episode_item.title)
|
||||
episode_title = scrapertools.get_match(episode_item.title, "(\d+x\d+)")
|
||||
logger.info("episode=" + episode_title)
|
||||
except:
|
||||
import traceback
|
||||
logger.error(traceback.format_exc())
|
||||
continue
|
||||
|
||||
if first_episode != "" and episode_title == first_episode:
|
||||
empezar = True
|
||||
|
||||
if episodio_ya_descargado(show_title, episode_title):
|
||||
continue
|
||||
|
||||
if not empezar:
|
||||
continue
|
||||
|
||||
# Extrae los mirrors
|
||||
try:
|
||||
mirrors_itemlist = channel.findvideos(episode_item)
|
||||
except:
|
||||
mirrors_itemlist = servertools.find_video_items(episode_item)
|
||||
print mirrors_itemlist
|
||||
|
||||
descargado = False
|
||||
|
||||
new_mirror_itemlist_1 = []
|
||||
new_mirror_itemlist_2 = []
|
||||
new_mirror_itemlist_3 = []
|
||||
new_mirror_itemlist_4 = []
|
||||
new_mirror_itemlist_5 = []
|
||||
new_mirror_itemlist_6 = []
|
||||
|
||||
for mirror_item in mirrors_itemlist:
|
||||
|
||||
# Si está en español va al principio, si no va al final
|
||||
if "(Español)" in mirror_item.title:
|
||||
if best_server in mirror_item.title.lower():
|
||||
new_mirror_itemlist_1.append(mirror_item)
|
||||
else:
|
||||
new_mirror_itemlist_2.append(mirror_item)
|
||||
elif "(Latino)" in mirror_item.title:
|
||||
if best_server in mirror_item.title.lower():
|
||||
new_mirror_itemlist_3.append(mirror_item)
|
||||
else:
|
||||
new_mirror_itemlist_4.append(mirror_item)
|
||||
elif "(VOS)" in mirror_item.title:
|
||||
if best_server in mirror_item.title.lower():
|
||||
new_mirror_itemlist_3.append(mirror_item)
|
||||
else:
|
||||
new_mirror_itemlist_4.append(mirror_item)
|
||||
else:
|
||||
if best_server in mirror_item.title.lower():
|
||||
new_mirror_itemlist_5.append(mirror_item)
|
||||
else:
|
||||
new_mirror_itemlist_6.append(mirror_item)
|
||||
|
||||
mirrors_itemlist = new_mirror_itemlist_1 + new_mirror_itemlist_2 + new_mirror_itemlist_3 + new_mirror_itemlist_4 + new_mirror_itemlist_5 + new_mirror_itemlist_6
|
||||
|
||||
for mirror_item in mirrors_itemlist:
|
||||
logger.info("mirror=" + mirror_item.title)
|
||||
|
||||
if "(Español)" in mirror_item.title:
|
||||
idioma = "(Español)"
|
||||
codigo_idioma = "es"
|
||||
elif "(Latino)" in mirror_item.title:
|
||||
idioma = "(Latino)"
|
||||
codigo_idioma = "lat"
|
||||
elif "(VOS)" in mirror_item.title:
|
||||
idioma = "(VOS)"
|
||||
codigo_idioma = "vos"
|
||||
elif "(VO)" in mirror_item.title:
|
||||
idioma = "(VO)"
|
||||
codigo_idioma = "vo"
|
||||
else:
|
||||
idioma = "(Desconocido)"
|
||||
codigo_idioma = "desconocido"
|
||||
|
||||
logger.info("filter_language=#" + filter_language + "#, codigo_idioma=#" + codigo_idioma + "#")
|
||||
if filter_language == "" or (filter_language != "" and filter_language == codigo_idioma):
|
||||
logger.info("downloading mirror")
|
||||
else:
|
||||
logger.info("language " + codigo_idioma + " filtered, skipping")
|
||||
continue
|
||||
|
||||
if hasattr(channel, 'play'):
|
||||
video_items = channel.play(mirror_item)
|
||||
else:
|
||||
video_items = [mirror_item]
|
||||
|
||||
if len(video_items) > 0:
|
||||
video_item = video_items[0]
|
||||
|
||||
# Comprueba que esté disponible
|
||||
video_urls, puedes, motivo = servertools.resolve_video_urls_for_playing(video_item.server,
|
||||
video_item.url,
|
||||
video_password="",
|
||||
muestra_dialogo=False)
|
||||
|
||||
# Lo añade a la lista de descargas
|
||||
if puedes:
|
||||
logger.info("downloading mirror started...")
|
||||
# El vídeo de más calidad es el último
|
||||
mediaurl = video_urls[len(video_urls) - 1][1]
|
||||
devuelve = downloadtools.downloadbest(video_urls,
|
||||
show_title + " " + episode_title + " " + idioma + " [" + video_item.server + "]",
|
||||
continuar=False)
|
||||
|
||||
if devuelve == 0:
|
||||
logger.info("download ok")
|
||||
descargado = True
|
||||
break
|
||||
elif devuelve == -1:
|
||||
try:
|
||||
|
||||
platformtools.dialog_ok("plugin", "Descarga abortada")
|
||||
except:
|
||||
pass
|
||||
return
|
||||
else:
|
||||
logger.info("download error, try another mirror")
|
||||
continue
|
||||
|
||||
else:
|
||||
logger.info("downloading mirror not available... trying next")
|
||||
|
||||
if not descargado:
|
||||
logger.info("EPISODIO NO DESCARGADO " + episode_title)
|
||||
|
||||
|
||||
def add_to_favorites(item):
|
||||
# Proviene del menu contextual:
|
||||
if "item_action" in item:
|
||||
item.action = item.item_action
|
||||
del item.item_action
|
||||
item.context = []
|
||||
|
||||
from channels import favorites
|
||||
from core import downloadtools
|
||||
if not item.fulltitle: item.fulltitle = item.title
|
||||
title = platformtools.dialog_input(
|
||||
default=downloadtools.limpia_nombre_excepto_1(item.fulltitle) + " [" + item.channel + "]")
|
||||
if title is not None:
|
||||
item.title = title
|
||||
favorites.addFavourite(item)
|
||||
platformtools.dialog_ok("Alfa", config.get_localized_string(
|
||||
30102) + "\n" + item.title + "\n" + config.get_localized_string(30108))
|
||||
return
|
||||
|
||||
|
||||
def remove_from_favorites(item):
|
||||
from channels import favorites
|
||||
# En "extra" está el nombre del fichero en favoritos
|
||||
favorites.delFavourite(item.extra)
|
||||
platformtools.dialog_ok("Alfa",
|
||||
config.get_localized_string(30102) + "\n" + item.title + "\n" + config.get_localized_string(
|
||||
30105))
|
||||
platformtools.itemlist_refresh()
|
||||
return
|
||||
|
||||
|
||||
def download(item):
|
||||
from channels import downloads
|
||||
if item.contentType == "list" or item.contentType == "tvshow":
|
||||
item.contentType = "video"
|
||||
item.play_menu = True
|
||||
downloads.save_download(item)
|
||||
return
|
||||
|
||||
|
||||
def add_to_library(item):
|
||||
if "item_action" in item:
|
||||
item.action = item.item_action
|
||||
del item.item_action
|
||||
|
||||
if not item.fulltitle == "":
|
||||
item.title = item.fulltitle
|
||||
videolibrarytools.savelibrary(item)
|
||||
platformtools.dialog_ok("Alfa",
|
||||
config.get_localized_string(30101) + "\n" + item.title + "\n" + config.get_localized_string(
|
||||
30135))
|
||||
return
|
||||
|
||||
|
||||
def delete_file(item):
|
||||
os.remove(item.url)
|
||||
platformtools.itemlist_refresh()
|
||||
return
|
||||
|
||||
|
||||
def search_trailer(item):
|
||||
config.set_setting("subtitulo", False)
|
||||
item.channel = "trailertools"
|
||||
item.action = "buscartrailer"
|
||||
item.contextual = True
|
||||
run(item)
|
||||
return
|
||||
|
||||
|
||||
# Crea la lista de opciones para el menu de reproduccion
|
||||
def check_video_options(item, video_urls):
|
||||
itemlist = []
|
||||
# Opciones Reproducir
|
||||
playable = (len(video_urls) > 0)
|
||||
|
||||
for video_url in video_urls:
|
||||
itemlist.append(
|
||||
item.clone(option=config.get_localized_string(30151) + " " + video_url[0], video_url=video_url[1],
|
||||
action="play_video"))
|
||||
|
||||
if item.server == "local":
|
||||
itemlist.append(item.clone(option=config.get_localized_string(30164), action="delete_file"))
|
||||
|
||||
if not item.server == "local" and playable:
|
||||
itemlist.append(item.clone(option=config.get_localized_string(30153), action="download", video_urls=video_urls))
|
||||
|
||||
if item.channel == "favorites":
|
||||
itemlist.append(item.clone(option=config.get_localized_string(30154), action="remove_from_favorites"))
|
||||
|
||||
if not item.channel == "favorites" and playable:
|
||||
itemlist.append(
|
||||
item.clone(option=config.get_localized_string(30155), action="add_to_favorites", item_action=item.action))
|
||||
|
||||
if not item.strmfile and playable and item.contentType == "movie":
|
||||
itemlist.append(
|
||||
item.clone(option=config.get_localized_string(30161), action="add_to_library", item_action=item.action))
|
||||
|
||||
if not item.channel in ["Trailer", "ecarteleratrailers"] and playable:
|
||||
itemlist.append(item.clone(option=config.get_localized_string(30162), action="search_trailer"))
|
||||
|
||||
return itemlist
|
||||
|
||||
|
||||
# play_menu, abre el menu con las opciones para reproducir
|
||||
def play_menu(item):
|
||||
if item.server == "": item.server = "directo"
|
||||
|
||||
if item.video_urls:
|
||||
video_urls, puedes, motivo = item.video_urls, True, ""
|
||||
else:
|
||||
video_urls, puedes, motivo = servertools.resolve_video_urls_for_playing(item.server, item.url, item.password,
|
||||
True)
|
||||
|
||||
if not "strmfile" in item: item.strmfile = False
|
||||
# TODO: unificar show y Serie ya que se usan indistintamente.
|
||||
if not "Serie" in item: item.Serie = item.show
|
||||
if item.server == "": item.server = "directo"
|
||||
|
||||
opciones = check_video_options(item, video_urls)
|
||||
if not puedes:
|
||||
if item.server != "directo":
|
||||
motivo = motivo.replace("<br/>", "\n")
|
||||
platformtools.dialog_ok("No puedes ver ese vídeo porque...", motivo + "\n" + item.url)
|
||||
else:
|
||||
platformtools.dialog_ok("No puedes ver ese vídeo porque...",
|
||||
"El servidor donde está alojado no está\nsoportado en Alfa todavía\n" + item.url)
|
||||
|
||||
if len(opciones) == 0:
|
||||
return
|
||||
|
||||
default_action = config.get_setting("default_action")
|
||||
logger.info("default_action=%s" % (default_action))
|
||||
# Si la accion por defecto es "Preguntar", pregunta
|
||||
if default_action == 0:
|
||||
seleccion = platformtools.dialog_select(config.get_localized_string(30163),
|
||||
[opcion.option for opcion in opciones])
|
||||
elif default_action == 1:
|
||||
seleccion = 0
|
||||
elif default_action == 2:
|
||||
seleccion = len(video_urls) - 1
|
||||
elif default_action == 3:
|
||||
seleccion = seleccion
|
||||
else:
|
||||
seleccion = 0
|
||||
|
||||
if seleccion > -1:
|
||||
logger.info("seleccion=%d" % seleccion)
|
||||
logger.info("seleccion=%s" % opciones[seleccion].option)
|
||||
selecteditem = opciones[seleccion]
|
||||
del selecteditem.option
|
||||
run(opciones[seleccion])
|
||||
|
||||
return
|
||||
|
||||
|
||||
# play_video, Llama a la función especifica de la plataforma para reproducir
|
||||
def play_video(item):
|
||||
platformtools.play_video(item)
|
||||
48
mediaserver/platformcode/logger.py
Normal file
48
mediaserver/platformcode/logger.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------------------------------
|
||||
# logger for mediaserver
|
||||
# ------------------------------------------------------------
|
||||
import logging
|
||||
import logging.config
|
||||
import os
|
||||
|
||||
import config
|
||||
|
||||
|
||||
class ExtendedLogger(logging.Logger):
|
||||
def findCaller(self):
|
||||
f = logging.currentframe().f_back.f_back
|
||||
rv = "(unknown file)", 0, "(unknown function)"
|
||||
while hasattr(f, "f_code"):
|
||||
co = f.f_code
|
||||
filename = os.path.normcase(co.co_filename)
|
||||
if "logger" in filename: # This line is modified.
|
||||
f = f.f_back
|
||||
continue
|
||||
filename = filename + " " + co.co_name
|
||||
rv = (filename, f.f_lineno, co.co_name)
|
||||
break
|
||||
return rv
|
||||
|
||||
|
||||
logging.setLoggerClass(ExtendedLogger)
|
||||
logging.basicConfig(level=logging.DEBUG,
|
||||
format='%(levelname)-5s %(asctime)s [%(filename)-40s] %(message)s',
|
||||
datefmt="%d/%m/%y-%H:%M:%S",
|
||||
filename=os.path.join(config.get_data_path(), "alfa.log"),
|
||||
filemode='w')
|
||||
logger_object = logging.getLogger("mediaserver")
|
||||
|
||||
|
||||
def info(texto=""):
|
||||
if config.get_setting("debug"):
|
||||
logger_object.info(unicode(str(texto), "utf-8", "ignore").replace("\n", "\n" + " " * 67))
|
||||
|
||||
|
||||
def debug(texto=""):
|
||||
if config.get_setting("debug"):
|
||||
logger_object.debug(unicode(str(texto), "utf-8", "ignore").replace("\n", "\n" + " " * 67))
|
||||
|
||||
|
||||
def error(texto=""):
|
||||
logger_object.error(unicode(str(texto), "utf-8", "ignore").replace("\n", "\n" + " " * 67))
|
||||
107
mediaserver/platformcode/platformtools.py
Normal file
107
mediaserver/platformcode/platformtools.py
Normal file
@@ -0,0 +1,107 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------------------------------
|
||||
# platformtools
|
||||
# ------------------------------------------------------------
|
||||
# Herramientas responsables de adaptar los diferentes
|
||||
# cuadros de dialogo a una plataforma en concreto,
|
||||
# en este caso Mediserver.
|
||||
# version 1.3
|
||||
# ------------------------------------------------------------
|
||||
import threading
|
||||
|
||||
controllers = {}
|
||||
|
||||
|
||||
def dialog_ok(*args, **kwargs):
|
||||
id = threading.current_thread().name
|
||||
return controllers[id].dialog_ok(*args, **kwargs)
|
||||
|
||||
|
||||
def dialog_notification(*args, **kwargs):
|
||||
id = threading.current_thread().name
|
||||
return controllers[id].dialog_notification(*args, **kwargs)
|
||||
|
||||
|
||||
def dialog_yesno(*args, **kwargs):
|
||||
id = threading.current_thread().name
|
||||
return controllers[id].dialog_yesno(*args, **kwargs)
|
||||
|
||||
|
||||
def dialog_select(*args, **kwargs):
|
||||
id = threading.current_thread().name
|
||||
return controllers[id].dialog_select(*args, **kwargs)
|
||||
|
||||
|
||||
def dialog_progress(*args, **kwargs):
|
||||
id = threading.current_thread().name
|
||||
return controllers[id].dialog_progress(*args, **kwargs)
|
||||
|
||||
|
||||
def dialog_progress_bg(*args, **kwargs):
|
||||
id = threading.current_thread().name
|
||||
return controllers[id].dialog_progress_bg(*args, **kwargs)
|
||||
|
||||
|
||||
def dialog_input(*args, **kwargs):
|
||||
id = threading.current_thread().name
|
||||
return controllers[id].dialog_input(*args, **kwargs)
|
||||
|
||||
|
||||
def dialog_numeric(*args, **kwargs):
|
||||
id = threading.current_thread().name
|
||||
return controllers[id].dialog_numeric(*args, **kwargs)
|
||||
|
||||
|
||||
def itemlist_refresh(*args, **kwargs):
|
||||
id = threading.current_thread().name
|
||||
return controllers[id].itemlist_refresh(*args, **kwargs)
|
||||
|
||||
|
||||
def itemlist_update(*args, **kwargs):
|
||||
id = threading.current_thread().name
|
||||
return controllers[id].itemlist_update(*args, **kwargs)
|
||||
|
||||
|
||||
def render_items(*args, **kwargs):
|
||||
id = threading.current_thread().name
|
||||
return controllers[id].render_items(*args, **kwargs)
|
||||
|
||||
|
||||
def is_playing(*args, **kwargs):
|
||||
id = threading.current_thread().name
|
||||
return controllers[id].is_playing(*args, **kwargs)
|
||||
|
||||
|
||||
def play_video(*args, **kwargs):
|
||||
id = threading.current_thread().name
|
||||
return controllers[id].play_video(*args, **kwargs)
|
||||
|
||||
|
||||
def stop_video(*args, **kwargs):
|
||||
# id = threading.current_thread().name
|
||||
# return controllers[id].play_video(*args, **kwargs)
|
||||
return False
|
||||
|
||||
|
||||
def open_settings(*args, **kwargs):
|
||||
id = threading.current_thread().name
|
||||
return controllers[id].open_settings(*args, **kwargs)
|
||||
|
||||
|
||||
def show_channel_settings(*args, **kwargs):
|
||||
id = threading.current_thread().name
|
||||
return controllers[id].show_channel_settings(*args, **kwargs)
|
||||
|
||||
|
||||
def show_video_info(*args, **kwargs):
|
||||
id = threading.current_thread().name
|
||||
return controllers[id].show_video_info(*args, **kwargs)
|
||||
|
||||
|
||||
def show_recaptcha(*args, **kwargs):
|
||||
id = threading.current_thread().name
|
||||
return controllers[id].show_recaptcha(*args, **kwargs)
|
||||
|
||||
|
||||
def torrent_client_installed(show_tuple=False):
|
||||
return []
|
||||
1306
mediaserver/platformcode/template/css/alfa.css
Normal file
1306
mediaserver/platformcode/template/css/alfa.css
Normal file
File diff suppressed because one or more lines are too long
BIN
mediaserver/platformcode/template/favicon.ico
Normal file
BIN
mediaserver/platformcode/template/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.4 KiB |
7
mediaserver/platformcode/template/html/config_bool.html
Normal file
7
mediaserver/platformcode/template/html/config_bool.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<li onmousemove="focus_element(this.getElementsByTagName('input')[0])">
|
||||
<div class="control">
|
||||
<span class="name" style='color:%item_color'>%item_label</span>
|
||||
<input class="checkbox" onchange="evaluate_controls(this)" onfocus="this.parentNode.className='control control_focused'" onblur="this.parentNode.className='control'" type="checkbox" id="%item_id" %item_value>
|
||||
<label class="checkbox"><i></i></label>
|
||||
</div>
|
||||
</li>
|
||||
@@ -0,0 +1 @@
|
||||
<a class="control_button" href="javascript:void(0)"onmouseover="focus_element(this)" onclick="change_category('%item_category')">%item_label</a>
|
||||
@@ -0,0 +1 @@
|
||||
<ul class="settings_list" style="display:none" id="%item_id">%item_value</ul>
|
||||
5
mediaserver/platformcode/template/html/config_label.html
Normal file
5
mediaserver/platformcode/template/html/config_label.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<li>
|
||||
<div>
|
||||
<span class="name" style='color:%item_color'>%item_label</span>
|
||||
</div>
|
||||
</li>
|
||||
7
mediaserver/platformcode/template/html/config_list.html
Normal file
7
mediaserver/platformcode/template/html/config_list.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<li onmousemove="focus_element(this.getElementsByTagName('select')[0])">
|
||||
<div class="control">
|
||||
<span class="name" style='color:%item_color'>%item_label</span>
|
||||
<select class="list" onchange="evaluate_controls(this)" name="%item_type" onfocus="this.parentNode.className='control control_focused'" onblur="this.parentNode.className='control'" id="%item_id">%item_values</select>
|
||||
<label class="list"><i></i></label>
|
||||
</div>
|
||||
</li>
|
||||
4
mediaserver/platformcode/template/html/config_sep.html
Normal file
4
mediaserver/platformcode/template/html/config_sep.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<li>
|
||||
<div class="separator">
|
||||
</div>
|
||||
</li>
|
||||
7
mediaserver/platformcode/template/html/config_text.html
Normal file
7
mediaserver/platformcode/template/html/config_text.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<li onmousemove="focus_element(this.getElementsByTagName('input')[0])">
|
||||
<div class="control">
|
||||
<span class="name" style='color:%item_color'>%item_label</span>
|
||||
<input class="text" onchange="evaluate_controls(this)" onkeyup="evaluate_controls(this)" onfocus="this.parentNode.className='control control_focused'" onblur="this.parentNode.className='control'" onkeypress="%keypress" type="%item_type" id="%item_id" value="%item_value">
|
||||
<label class="text"><i></i></label>
|
||||
</div>
|
||||
</li>
|
||||
10
mediaserver/platformcode/template/html/itemlist_banner.html
Normal file
10
mediaserver/platformcode/template/html/itemlist_banner.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<li class="item_banner">
|
||||
<a class="item %item_class" onblur="unload_info(this)" oncontextmenu="dialog.menu('Menu','%menu_items');return false" onfocus="focused_item=this;load_info(this, 'banner')" onmouseover="focus_element(this)" href="javascript:void(0)" onclick="send_request('%item_url')">
|
||||
<img class="thumbnail" onerror="this.style.visibility='hidden'">
|
||||
<h3 class="label">%item_title</h3>
|
||||
<label class="thumbnail">%item_thumbnail</label>
|
||||
<label class="plot">%item_plot</label>
|
||||
<label class="fanart">%item_fanart</label>
|
||||
</a>
|
||||
%item_menu
|
||||
</li>
|
||||
10
mediaserver/platformcode/template/html/itemlist_channel.html
Normal file
10
mediaserver/platformcode/template/html/itemlist_channel.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<li class="item_channel">
|
||||
<a class="item %item_class" onblur="unload_info(this)" oncontextmenu="dialog.menu('Menu','%menu_items');return false" onfocus="focused_item=this;load_info(this, 'channel')" onmouseover="focus_element(this)" href="javascript:void(0)" onclick="send_request('%item_url')">
|
||||
<h3 class="label">%item_title</h3>
|
||||
<img class="thumbnail" onerror="this.style.visibility='hidden'" onload="this.parentNode.children[0].style.visibility='hidden'">
|
||||
<label class="thumbnail">%item_thumbnail</label>
|
||||
<label class="plot">%item_plot</label>
|
||||
<label class="fanart">%item_fanart</label>
|
||||
</a>
|
||||
%item_menu
|
||||
</li>
|
||||
10
mediaserver/platformcode/template/html/itemlist_list.html
Normal file
10
mediaserver/platformcode/template/html/itemlist_list.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<li class="item_list">
|
||||
<a class="item %item_class" onblur="unload_info(this)" oncontextmenu="dialog.menu('Menu','%menu_items');return false" onfocus="focused_item=this;load_info(this, 'list')" onmouseover="focus_element(this)" href="javascript:void(0)" onclick="send_request('%item_url')">
|
||||
<h3 class="label">%item_title</h3>
|
||||
<img class="thumbnail" onerror="image_error(this)">
|
||||
<label class="thumbnail">%item_thumbnail</label>
|
||||
<label class="plot">%item_plot</label>
|
||||
<label class="fanart">%item_fanart</label>
|
||||
</a>
|
||||
%item_menu
|
||||
</li>
|
||||
@@ -0,0 +1 @@
|
||||
<a class="item_menu" href="javascript:void(0)" onmouseover="focus_element(this)" onclick="focused_item=this;dialog.menu('Menu','%menu_items')"></a>
|
||||
10
mediaserver/platformcode/template/html/itemlist_movie.html
Normal file
10
mediaserver/platformcode/template/html/itemlist_movie.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<li class="item_movie">
|
||||
<a class="item %item_class" onblur="unload_info(this)" oncontextmenu="dialog.menu('Menu','%menu_items');return false" onfocus="focused_item=this;load_info(this, 'movie')" onmouseover="focus_element(this)" href="javascript:void(0)" onclick="send_request('%item_url')">
|
||||
<h3 class="label">%item_title</h3>
|
||||
<img class="thumbnail" onerror="image_error(this)">
|
||||
<label class="thumbnail">%item_thumbnail</label>
|
||||
<label class="plot">%item_plot</label>
|
||||
<label class="fanart">%item_fanart</label>
|
||||
</a>
|
||||
%item_menu
|
||||
</li>
|
||||
6
mediaserver/platformcode/template/html/player_flash.html
Normal file
6
mediaserver/platformcode/template/html/player_flash.html
Normal file
@@ -0,0 +1,6 @@
|
||||
<object class="media_player" data="http://releases.flowplayer.org/swf/flowplayer-3.2.18.swf" type="application/x-shockwave-flash">
|
||||
<param name="movie" value="http://releases.flowplayer.org/swf/flowplayer-3.2.18.swf" />
|
||||
<param name="allowfullscreen" value="true" />
|
||||
<param name="allowscriptaccess" value="always" />
|
||||
<param name="flashvars" value='config={"clip":{"url":"%video_url"},"playlist":[{"url":"%video_url"}]}' />
|
||||
</object>
|
||||
1
mediaserver/platformcode/template/html/player_html.html
Normal file
1
mediaserver/platformcode/template/html/player_html.html
Normal file
@@ -0,0 +1 @@
|
||||
<video class="media_player" id="media_player" type="application/x-mplayer2" autoplay="true" controls="true" src="%video_url"/>
|
||||
7
mediaserver/platformcode/template/html/player_vlc.html
Normal file
7
mediaserver/platformcode/template/html/player_vlc.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<object class="media_player" classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921" codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab" id="vlc" events="False">
|
||||
<param name="Src" value="%video_url"></param>
|
||||
<param name="ShowDisplay" value="True"></param>
|
||||
<param name="AutoLoop" value="no"></param>
|
||||
<param name="AutoPlay" value="yes"></param>
|
||||
<embed type="application/x-google-vlc-plugin" name="vlcfirefox" autoplay="yes" loop="no" width="100%" height="100%" target="%video_url"></embed>
|
||||
</object>
|
||||
5
mediaserver/platformcode/template/html/select_item.html
Normal file
5
mediaserver/platformcode/template/html/select_item.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<li class="item">
|
||||
<a href="javascript:void(0)" onmouseover="focus_element(this)" onclick="dialog.closeall(); %item_action">
|
||||
<h3>%item_title</h3>
|
||||
</a>
|
||||
</li>
|
||||
BIN
mediaserver/platformcode/template/icon-512.png
Normal file
BIN
mediaserver/platformcode/template/icon-512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 85 KiB |
503
mediaserver/platformcode/template/js/dialogs.js
Normal file
503
mediaserver/platformcode/template/js/dialogs.js
Normal file
@@ -0,0 +1,503 @@
|
||||
loading.close = function () {
|
||||
var el = document.getElementById("window_loading");
|
||||
if (el.style.display == "block") {
|
||||
el.style.display = "none";
|
||||
document.getElementById("window_overlay").style.display = "none";
|
||||
if (focused_item) {
|
||||
focused_item.focus();
|
||||
}
|
||||
else if (document.getElementById("itemlist").children.length) {
|
||||
document.getElementById("itemlist").children[0].children[0].focus();
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
loading.show = function (message) {
|
||||
if (!message) {
|
||||
message = "Cargando...";
|
||||
};
|
||||
var el = document.getElementById("window_loading");
|
||||
el.getElementById("loading_message").innerHTML = message;
|
||||
document.getElementById("window_overlay").style.display = "block";
|
||||
el.style.display = "block";
|
||||
el.getElementById("loading_message").focus();
|
||||
center_window(el);
|
||||
};
|
||||
|
||||
dialog.closeall = function () {
|
||||
document.getElementById('window_overlay').style.display = 'none';
|
||||
document.getElementById("window_loading").style.display = "none";
|
||||
document.getElementById("window_select").style.display = "none";
|
||||
document.getElementById("window_settings").style.display = "none";
|
||||
document.getElementById("window_settings").style.display = "none";
|
||||
document.getElementById("window_player").style.display = "none";
|
||||
document.getElementById("window_player").getElementById("media_content").innerHTML = '';
|
||||
document.getElementById("window_ok").style.display = "none";
|
||||
document.getElementById("window_yesno").style.display = "none";
|
||||
document.getElementById("window_input").style.display = "none";
|
||||
document.getElementById("window_recaptcha").style.display = "none";
|
||||
document.getElementById("window_progress").style.display = "none";
|
||||
document.getElementById("window_info").style.display = "none";
|
||||
if (focused_item) {
|
||||
focused_item.focus();
|
||||
}
|
||||
else if (document.getElementById("itemlist").children.length) {
|
||||
document.getElementById("itemlist").children[0].children[0].focus();
|
||||
};
|
||||
};
|
||||
|
||||
dialog.menu = function (title, list) {
|
||||
dialog.closeall();
|
||||
if (list) {
|
||||
var el = document.getElementById("window_select")
|
||||
el.getElementById("window_heading").innerHTML = title;
|
||||
el.getElementById("control_list").innerHTML = atob(list);
|
||||
el.style.display = "block";
|
||||
document.getElementById("window_overlay").style.display = "block";
|
||||
el.getElementById("control_list").children[0].children[0].focus();
|
||||
center_window(el);
|
||||
};
|
||||
};
|
||||
|
||||
dialog.select = function (id, data) {
|
||||
dialog.closeall();
|
||||
var el = document.getElementById("window_select");
|
||||
|
||||
el.getElementById("window_heading").innerHTML = data.title;
|
||||
el.RequestID = id;
|
||||
var lista = [];
|
||||
for (var x in data.list) {
|
||||
lista.push(replace_list(html.dialog.select.item, {
|
||||
"item_title": data.list[x],
|
||||
"item_action": "send_data({'id':'" + id + "', 'result':" + x + "})"
|
||||
}));
|
||||
};
|
||||
el.getElementById("control_list").innerHTML = lista.join("");
|
||||
el.style.display = "block";
|
||||
document.getElementById("window_overlay").style.display = "block";
|
||||
|
||||
el.getElementById("control_list").children[0].children[0].focus();
|
||||
center_window(el);
|
||||
};
|
||||
|
||||
dialog.player = function (title, player) {
|
||||
dialog.closeall();
|
||||
var el = document.getElementById("window_player");
|
||||
el.getElementById("window_heading").innerHTML = title;
|
||||
el.getElementById("media_content").innerHTML = player;
|
||||
el.style.display = "block";
|
||||
document.getElementById("window_overlay").style.display = "block";
|
||||
el.children[0].focus();
|
||||
center_window(el);
|
||||
};
|
||||
|
||||
dialog.ok = function (id, data) {
|
||||
dialog.closeall();
|
||||
var el = document.getElementById("window_ok");
|
||||
document.getElementById("window_overlay").style.display = "block";
|
||||
el.style.display = "block";
|
||||
el.RequestID = id;
|
||||
el.getElementById("window_message").innerHTML = data.text.replace(new RegExp("\n", 'g'), "<br/>");
|
||||
el.getElementById("window_heading").innerHTML = data.title;
|
||||
el.getElementById("window_footer").children[0].focus();
|
||||
center_window(el);
|
||||
};
|
||||
|
||||
dialog.yesno = function (id, data) {
|
||||
dialog.closeall();
|
||||
var el = document.getElementById("window_yesno");
|
||||
document.getElementById("window_overlay").style.display = "block";
|
||||
el.style.display = "block";
|
||||
el.RequestID = id;
|
||||
el.getElementById("window_message").innerHTML = data.text.replace(new RegExp("\n", 'g'), "<br/>");
|
||||
el.getElementById("window_heading").innerHTML = data.title;
|
||||
el.getElementById("window_footer").children[0].focus();
|
||||
center_window(el);
|
||||
};
|
||||
|
||||
dialog.notification = function (id, data) {
|
||||
var el = document.getElementById("window_notification");
|
||||
el.style.display = "block";
|
||||
if (!data.icon){data.icon = 0}
|
||||
el.getElementById("window_heading").innerHTML = data.title;
|
||||
el.getElementById("window_message").innerHTML = data.text;
|
||||
el.getElementById("window_icon").className = "window_icon" + data.icon;
|
||||
|
||||
|
||||
|
||||
auto_scroll(el.getElementById("window_message"))
|
||||
setTimeout(function(){ el.style.display = "none"; }, data.time);
|
||||
};
|
||||
|
||||
dialog.keyboard = function (id, data) {
|
||||
dialog.closeall();
|
||||
var el = document.getElementById("window_input");
|
||||
|
||||
if (data.title === "") {
|
||||
data.title = "Teclado";
|
||||
};
|
||||
if (data.password == true) {
|
||||
el.getElementById("window_value").type = "password";
|
||||
}
|
||||
else {
|
||||
el.getElementById("window_value").type = "text";
|
||||
};
|
||||
|
||||
el.RequestID = id;
|
||||
document.getElementById("window_overlay").style.display = "block";
|
||||
el.style.display = "block";
|
||||
el.getElementById("window_value").value = data.text;
|
||||
el.getElementById("window_heading").innerHTML = data.title;
|
||||
el.getElementById("window_value").focus();
|
||||
center_window(el);
|
||||
};
|
||||
|
||||
dialog.recaptcha = function (id, data) {
|
||||
dialog.closeall();
|
||||
var el = document.getElementById("window_recaptcha");
|
||||
|
||||
if (data.title === "") {
|
||||
data.title = "Introduce el texto de la imagen";
|
||||
};
|
||||
|
||||
el.RequestID = id;
|
||||
document.getElementById("window_overlay").style.display = "block";
|
||||
el.style.display = "block";
|
||||
el.getElementById("window_image").style.backgroundImage = "url(" + data.image + ")";
|
||||
el.getElementById("window_heading").innerHTML = data.title;
|
||||
el.getElementById("window_message").innerHTML = data.message;
|
||||
|
||||
for (var x in [0,1,2,3,4,5,6,7,8]) {
|
||||
el.getElementById("window_image").children[x].className = "";
|
||||
}
|
||||
el.getElementById("window_footer").children[0].focus();
|
||||
center_window(el);
|
||||
};
|
||||
|
||||
dialog.recaptcha_select = function (id, data) {
|
||||
var el = document.getElementById("window_recaptcha");
|
||||
console.log(data.selected)
|
||||
console.log(data.unselected)
|
||||
for (var x in data.selected) {
|
||||
el.getElementById("window_image").children[data.selected[x]].className = "selected";
|
||||
}
|
||||
for (var x in data.unselected) {
|
||||
el.getElementById("window_image").children[data.unselected[x]].className = "";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
dialog.progress_bg = function (id, data) {
|
||||
var el = document.getElementById("window_background_progress");
|
||||
el.style.display = "block";
|
||||
el.RequestID = id;
|
||||
el.getElementById("window_message").innerHTML = data.text.replace(new RegExp("\n", 'g'), "<br/>");
|
||||
el.getElementById("window_heading").innerHTML = data.title;
|
||||
el.getElementById("progressbar").style.width = data.percent + "%";
|
||||
};
|
||||
|
||||
dialog.progress_bg_close = function () {
|
||||
document.getElementById("window_background_progress").style.display = "none";
|
||||
};
|
||||
|
||||
dialog.progress = function (id, data) {
|
||||
var el = document.getElementById("window_progress");
|
||||
if (id != el.RequestID) {
|
||||
dialog.closeall();
|
||||
};
|
||||
el.RequestID = id;
|
||||
document.getElementById("window_overlay").style.display = "block";
|
||||
el.style.display = "block";
|
||||
el.getElementById("window_message").innerHTML = data.text.replace(new RegExp("\n", 'g'), "<br/>");
|
||||
el.getElementById("window_heading").innerHTML = data.title;
|
||||
el.getElementById("canceled").checked = "";
|
||||
el.getElementById("progress").style.width = data.percent + "%";
|
||||
el.getElementById("window_footer").children[0].focus;
|
||||
center_window(el);
|
||||
};
|
||||
|
||||
dialog.progress_update = function (id, data) {
|
||||
var el = document.getElementById("window_progress");
|
||||
el.getElementById("window_message").innerHTML = data.text.replace(new RegExp("\n", 'g'), "<br/>");
|
||||
if (el.getElementById("canceled").checked != "") {
|
||||
el.getElementById("window_heading").innerHTML = data.title + " " + data.percent + "% - Cancelando...";
|
||||
}
|
||||
else {
|
||||
el.getElementById("window_heading").innerHTML = data.title + " " + data.percent + "%";
|
||||
};
|
||||
el.getElementById("progress").style.width = data.percent + "%";
|
||||
};
|
||||
|
||||
dialog.progress_close = function () {
|
||||
dialog.closeall();
|
||||
};
|
||||
|
||||
dialog.custom_button = function(id, data) {
|
||||
var el = document.getElementById("window_settings");
|
||||
el.RequestID = id;
|
||||
if (data.return_value.label){
|
||||
el.getElementById("custom_button").innerHTML = data.return_value.label
|
||||
};
|
||||
var controls = document.getElementById("window_settings").getControls();
|
||||
for (var x in controls) {
|
||||
switch (controls[x].type) {
|
||||
case "text":
|
||||
controls[x].value = data.values[controls[x].id];
|
||||
break;
|
||||
case "password":
|
||||
controls[x].value = data.values[controls[x].id];
|
||||
break;
|
||||
case "checkbox":
|
||||
value = data.values[controls[x].id];
|
||||
if (value == true) {
|
||||
value = "checked";
|
||||
}
|
||||
else {
|
||||
value = "";
|
||||
};
|
||||
controls[x].checked = value;
|
||||
break;
|
||||
case "select-one":
|
||||
if (controls[x].name == "enum") {
|
||||
controls[x].selectedIndex = data.values[controls[x].id];
|
||||
}
|
||||
else if (controls[x].name == "labelenum") {
|
||||
controls[x].value = data.values[controls[x].id];
|
||||
};
|
||||
break;
|
||||
};
|
||||
controls[x].onchange()
|
||||
};
|
||||
};
|
||||
|
||||
dialog.config = function (id, data, Secciones, Lista) {
|
||||
dialog.closeall();
|
||||
var el = document.getElementById("window_settings");
|
||||
|
||||
el.RequestID = id;
|
||||
el.getElementById("controls_container").innerHTML = Lista;
|
||||
el.getElementById("window_heading").innerHTML = data.title;
|
||||
if (data.custom_button != null) {
|
||||
if (!data.custom_button.visible) {
|
||||
el.getElementById("custom_button").style.display = "none"
|
||||
}
|
||||
else {
|
||||
el.getElementById("custom_button").style.display = "inline";
|
||||
el.getElementById("custom_button").innerHTML = data.custom_button.label;
|
||||
el.getElementById("custom_button").onclick = function () {
|
||||
custom_button(data.custom_button);
|
||||
};
|
||||
};
|
||||
}
|
||||
else {
|
||||
el.getElementById("custom_button").style.display = "inline";
|
||||
el.getElementById("custom_button").innerHTML = "Por defecto";
|
||||
el.getElementById("custom_button").onclick = function () {
|
||||
custom_button(null);
|
||||
};
|
||||
};
|
||||
|
||||
if (Secciones != "") {
|
||||
el.getElementById("category_container").innerHTML = Secciones;
|
||||
el.getElementById("category_container").style.display = "block";
|
||||
el.getElementById("category_General").style.display = "block";
|
||||
|
||||
}
|
||||
else {
|
||||
el.getElementById("category_container").style.display = "none";
|
||||
el.getElementById("category_undefined").style.display = "block";
|
||||
|
||||
};
|
||||
|
||||
el.getElementById("window_footer").style.display = "block";
|
||||
el.getElementById("window_footer_local").style.display = "none";
|
||||
document.getElementById("window_overlay").style.display = "block";
|
||||
el.style.display = "block";
|
||||
if (Secciones != "") {
|
||||
el.getElementById("category_container").children[0].focus();
|
||||
el.getElementById("category_General").scrollTop = 0;
|
||||
}
|
||||
else {
|
||||
el.getElementById("window_footer").children[0].focus();
|
||||
el.getElementById("category_undefined").scrollTop = 0;
|
||||
};
|
||||
center_window(el);
|
||||
};
|
||||
|
||||
dialog.settings = function () {
|
||||
dialog.closeall();
|
||||
var el = document.getElementById("window_settings");
|
||||
el.getElementById("window_heading").innerHTML = "Ajustes";
|
||||
var controls = [];
|
||||
|
||||
controls.push(replace_list(html.config.label, {
|
||||
"item_color": "#FFFFFF",
|
||||
"item_label": "Navegación:"
|
||||
}));
|
||||
|
||||
if (settings.builtin_history) {
|
||||
var value = "checked=checked";
|
||||
}
|
||||
else {
|
||||
var value = "";
|
||||
};
|
||||
|
||||
controls.push(replace_list(html.config.bool, {
|
||||
"item_color": "#FFFFFF",
|
||||
"item_label": "Usar navegación del explorador",
|
||||
"item_id": "builtin_history",
|
||||
"item_value": value
|
||||
}));
|
||||
|
||||
controls.push(replace_list(html.config.label, {
|
||||
"item_color": "#FFFFFF",
|
||||
"item_label": "Visualización:"
|
||||
}));
|
||||
|
||||
if (settings.show_fanart) {
|
||||
var value = "checked=checked";
|
||||
}
|
||||
else {
|
||||
var value = "";
|
||||
};
|
||||
|
||||
controls.push(replace_list(html.config.bool, {
|
||||
"item_color": "#FFFFFF",
|
||||
"item_label": "Mostrar Fanarts",
|
||||
"item_id": "show_fanart",
|
||||
"item_value": value
|
||||
}));
|
||||
|
||||
controls.push(replace_list(html.config.label, {
|
||||
"item_color": "#FFFFFF",
|
||||
"item_label": "Reproducción:"
|
||||
}));
|
||||
|
||||
var options = ["<option>Preguntar</option>", "<option>Indirecto</option>", "<option>Directo</option>"];
|
||||
options[settings.play_mode] = options[settings.play_mode].replace("<option>", "<option selected=selected>");
|
||||
controls.push(replace_list(html.config.list, {
|
||||
"item_type": "enum",
|
||||
"item_color": "#FFFFFF",
|
||||
"item_label": "Método de reproduccion:",
|
||||
"item_id": "play_mode",
|
||||
"item_values": options.join("")
|
||||
}));
|
||||
|
||||
options = ["<option>Preguntar</option>"];
|
||||
for (var player in players) {
|
||||
options.push("<option>" + players[player] + "</option>");
|
||||
};
|
||||
options[settings.player_mode] = options[settings.player_mode].replace("<option>", "<option selected=selected>");
|
||||
controls.push(replace_list(html.config.list, {
|
||||
"item_type": "enum",
|
||||
"item_color": "#FFFFFF",
|
||||
"item_label": "Reproductor:",
|
||||
"item_id": "player_mode",
|
||||
"item_values": options.join("")
|
||||
}));
|
||||
|
||||
el.getElementById("controls_container").innerHTML = replace_list(html.config.container, {
|
||||
"item_id": "category_all",
|
||||
"item_value": controls.join("").replace(/evaluate_controls\(this\)/g, '')
|
||||
});
|
||||
el.getElementById("category_container").style.display = "none";
|
||||
el.getElementById("category_all").style.display = "block";
|
||||
el.getElementById("window_footer").style.display = "none";
|
||||
el.getElementById("window_footer_local").style.display = "block";
|
||||
document.getElementById("window_overlay").style.display = "block";
|
||||
el.style.display = "block";
|
||||
el.children[0].focus();
|
||||
center_window(el);
|
||||
};
|
||||
|
||||
dialog.info = function (id, data) {
|
||||
dialog.closeall();
|
||||
var el = document.getElementById("window_info");
|
||||
|
||||
el.RequestID = id;
|
||||
el.getElementById("window_heading").innerHTML = data.title;
|
||||
el.getElementById("info_fanart").src = data.fanart;
|
||||
el.getElementById("info_poster").src = data.thumbnail;
|
||||
|
||||
if (data.buttons) {
|
||||
el.getElementById("window_footer").style.display = "block";
|
||||
el.getElementById("page_info").innerHTML = data.count;
|
||||
|
||||
if (data.previous) {
|
||||
el.getElementById("previous").onclick = function () {
|
||||
info_window('previous');
|
||||
};
|
||||
el.getElementById("previous").className = "control_button";
|
||||
el.getElementById("previous").disabled = false;
|
||||
}
|
||||
else {
|
||||
el.getElementById("previous").onclick = "";
|
||||
el.getElementById("previous").className = "control_button disabled";
|
||||
el.getElementById("previous").disabled = true;
|
||||
};
|
||||
|
||||
if (data.next) {
|
||||
el.getElementById("next").onclick = function () {
|
||||
info_window('next');
|
||||
};
|
||||
el.getElementById("next").className = "control_button";
|
||||
el.getElementById("next").disabled = false;
|
||||
}
|
||||
else {
|
||||
el.getElementById("next").onclick = "";
|
||||
el.getElementById("next").className = "control_button disabled";
|
||||
el.getElementById("next").disabled = true;
|
||||
};
|
||||
}
|
||||
else {
|
||||
el.getElementById("window_footer").style.display = "none";
|
||||
};
|
||||
|
||||
el.getElementById("line1_head").innerHTML = data["lines"][0]["title"];
|
||||
el.getElementById("line2_head").innerHTML = data["lines"][1]["title"];
|
||||
el.getElementById("line3_head").innerHTML = data["lines"][2]["title"];
|
||||
el.getElementById("line4_head").innerHTML = data["lines"][3]["title"];
|
||||
el.getElementById("line5_head").innerHTML = data["lines"][4]["title"];
|
||||
el.getElementById("line6_head").innerHTML = data["lines"][5]["title"];
|
||||
el.getElementById("line7_head").innerHTML = data["lines"][6]["title"];
|
||||
el.getElementById("line8_head").innerHTML = data["lines"][7]["title"];
|
||||
|
||||
el.getElementById("line1").innerHTML = data["lines"][0]["text"];
|
||||
el.getElementById("line2").innerHTML = data["lines"][1]["text"];
|
||||
el.getElementById("line3").innerHTML = data["lines"][2]["text"];
|
||||
el.getElementById("line4").innerHTML = data["lines"][3]["text"];
|
||||
el.getElementById("line5").innerHTML = data["lines"][4]["text"];
|
||||
el.getElementById("line6").innerHTML = data["lines"][5]["text"];
|
||||
el.getElementById("line7").innerHTML = data["lines"][6]["text"];
|
||||
el.getElementById("line8").innerHTML = data["lines"][7]["text"];
|
||||
|
||||
if (el.style.display == "block") {
|
||||
update = true;
|
||||
}
|
||||
else {
|
||||
update = false;
|
||||
};
|
||||
|
||||
document.getElementById("window_overlay").style.display = "block";
|
||||
el.style.display = "block";
|
||||
|
||||
auto_scroll(el.getElementById("line1"));
|
||||
auto_scroll(el.getElementById("line2"));
|
||||
auto_scroll(el.getElementById("line3"));
|
||||
auto_scroll(el.getElementById("line4"));
|
||||
auto_scroll(el.getElementById("line5"));
|
||||
auto_scroll(el.getElementById("line6"));
|
||||
auto_scroll(el.getElementById("line7"));
|
||||
auto_scroll(el.getElementById("line8"));
|
||||
|
||||
if (data["buttons"]) {
|
||||
if (!update) {
|
||||
el.getElementById("window_footer").children[3].focus();
|
||||
};
|
||||
}
|
||||
else {
|
||||
el.children[0].focus();
|
||||
};
|
||||
|
||||
center_window(el);
|
||||
};
|
||||
107
mediaserver/platformcode/template/js/main.js
Normal file
107
mediaserver/platformcode/template/js/main.js
Normal file
@@ -0,0 +1,107 @@
|
||||
HTMLElement.prototype.getElementById = function(id) {
|
||||
if (this.querySelector("#" + id)) {
|
||||
return this.querySelector("#" + id);
|
||||
};
|
||||
|
||||
for (var x = 0; x < this.children.length; x++) {
|
||||
if (this.children[x].id == id) {
|
||||
return this.children[x];
|
||||
};
|
||||
};
|
||||
|
||||
for (var x = 0; x < this.children.length; x++) {
|
||||
result = this.children[x].getElementById(id);
|
||||
if (result != null) {
|
||||
return result;
|
||||
};
|
||||
};
|
||||
return null;
|
||||
};
|
||||
|
||||
HTMLElement.prototype.getControls = function() {
|
||||
return [].concat(Array.prototype.slice.call(this.getElementsByTagName("input")), Array.prototype.slice.call(this.getElementsByTagName("select")));
|
||||
};
|
||||
|
||||
window.onload = function() {
|
||||
var url = (window.location.href.split("#")[1] ? window.location.href.split("#")[1] : "");
|
||||
dispose();
|
||||
loading.show("Cargando pagina...");
|
||||
ajax_running.remove = function(val) {
|
||||
if (this.indexOf(val) > -1) {
|
||||
this.splice(this.indexOf(val), 1);
|
||||
};
|
||||
if (!this.length && !websocket) {
|
||||
send_request(url);
|
||||
};
|
||||
};
|
||||
load_settings();
|
||||
dowload_files();
|
||||
};
|
||||
|
||||
window.onpopstate = function(e) {
|
||||
if (e.state) {
|
||||
nav_history.go(e.state - nav_history.current);
|
||||
};
|
||||
};
|
||||
|
||||
window.onresize = function() {
|
||||
dispose();
|
||||
};
|
||||
|
||||
window.getCookie = function(name) {
|
||||
var match = document.cookie.match(new RegExp(name + '=([^;]+)'));
|
||||
if (match) return match[1];
|
||||
};
|
||||
|
||||
function load_settings() {
|
||||
settings["play_mode"] = (window.getCookie("play_mode") ? parseInt(window.getCookie("play_mode")) : 0);
|
||||
settings["player_mode"] = (window.getCookie("player_mode") ? parseInt(window.getCookie("player_mode")) : 0);
|
||||
settings["show_fanart"] = (window.getCookie("show_fanart") == "false" ? false : true);
|
||||
settings["builtin_history"] = (window.getCookie("builtin_history") == "true" ? true : false);
|
||||
};
|
||||
|
||||
function save_settings() {
|
||||
var controls = document.getElementById("window_settings").getControls();
|
||||
for (var x in controls) {
|
||||
switch (controls[x].type) {
|
||||
case "text":
|
||||
case "password":
|
||||
save_setting(controls[x].id, controls[x].value);
|
||||
break;
|
||||
case "checkbox":
|
||||
save_setting(controls[x].id, controls[x].checked);
|
||||
break;
|
||||
case "select-one":
|
||||
save_setting(controls[x].id, controls[x].selectedIndex);
|
||||
break;
|
||||
};
|
||||
};
|
||||
load_settings();
|
||||
};
|
||||
|
||||
function save_setting(id, value) {
|
||||
document.cookie = id + "=" + value + '; expires=Fri, 31 Dec 9999 23:59:59 GMT';
|
||||
};
|
||||
|
||||
function dowload_files() {
|
||||
ajax_to_dict("/media/html/player_vlc.html", html, "vlc_player");
|
||||
ajax_to_dict("/media/html/player_html.html", html, "html_player");
|
||||
ajax_to_dict("/media/html/player_flash.html", html, "flash_player");
|
||||
|
||||
ajax_to_dict("/media/html/itemlist_banner.html", html, "itemlist.banner");
|
||||
ajax_to_dict("/media/html/itemlist_channel.html", html, "itemlist.channel");
|
||||
ajax_to_dict("/media/html/itemlist_movie.html", html, "itemlist.movie");
|
||||
ajax_to_dict("/media/html/itemlist_list.html", html, "itemlist.list");
|
||||
ajax_to_dict("/media/html/itemlist_menu.html", html, "itemlist.menu");
|
||||
|
||||
ajax_to_dict("/media/html/select_item.html", html, "dialog.select.item");
|
||||
|
||||
ajax_to_dict("/media/html/config_label.html", html, "config.label");
|
||||
ajax_to_dict("/media/html/config_sep.html", html, "config.sep");
|
||||
ajax_to_dict("/media/html/config_text.html", html, "config.text");
|
||||
ajax_to_dict("/media/html/config_bool.html", html, "config.bool");
|
||||
ajax_to_dict("/media/html/config_list.html", html, "config.list");
|
||||
|
||||
ajax_to_dict("/media/html/config_category.html", html, "config.category");
|
||||
ajax_to_dict("/media/html/config_container.html", html, "config.container");
|
||||
};
|
||||
739
mediaserver/platformcode/template/js/navigation.js
Normal file
739
mediaserver/platformcode/template/js/navigation.js
Normal file
@@ -0,0 +1,739 @@
|
||||
window.onkeydown = function (e) {
|
||||
if (e.keyCode == 27) {
|
||||
dialog.closeall()
|
||||
}
|
||||
|
||||
if (e.target.tagName == "BODY") {
|
||||
body_events(e);
|
||||
};
|
||||
if (document.getElementById("window_loading").contains(e.target)) {
|
||||
window_loading_events(e);
|
||||
};
|
||||
if (document.getElementById("window_settings").contains(e.target)) {
|
||||
window_settings_events(e);
|
||||
};
|
||||
if (document.getElementById("window_select").contains(e.target)) {
|
||||
window_select_events(e);
|
||||
};
|
||||
if (document.getElementById("window_ok").contains(e.target)) {
|
||||
window_generic_events(e);
|
||||
};
|
||||
if (document.getElementById("window_yesno").contains(e.target)) {
|
||||
window_generic_events(e);
|
||||
};
|
||||
if (document.getElementById("window_recaptcha").contains(e.target)) {
|
||||
window_recaptcha_events(e);
|
||||
};
|
||||
if (document.getElementById("window_progress").contains(e.target)) {
|
||||
window_generic_events(e);
|
||||
};
|
||||
if (document.getElementById("window_info").contains(e.target)) {
|
||||
window_generic_events(e);
|
||||
}
|
||||
if (document.getElementById("window_input").contains(e.target)) {
|
||||
window_input_events(e);
|
||||
};
|
||||
if (document.getElementById("itemlist").contains(e.target)) {
|
||||
itemlist_events(e);
|
||||
};
|
||||
};
|
||||
|
||||
function itemlist_events(e) {
|
||||
var el = document.getElementById('itemlist');
|
||||
|
||||
switch (e.keyCode) {
|
||||
case 96:
|
||||
case 97:
|
||||
case 98:
|
||||
case 99:
|
||||
case 100:
|
||||
case 101:
|
||||
case 102:
|
||||
case 103:
|
||||
case 104:
|
||||
case 105:
|
||||
numeric_search(e.keyCode);
|
||||
break;
|
||||
|
||||
case 93: //Menu
|
||||
e.preventDefault();
|
||||
if (e.target.parentNode.children.length == 2) {
|
||||
e.target.parentNode.children[1].onclick.apply(e.target.parentNode.children[1]);
|
||||
focused_item = e.target.parentNode.children[1];
|
||||
};
|
||||
break;
|
||||
|
||||
case 8: //BACK
|
||||
e.preventDefault();
|
||||
if (nav_history.current > 0) {
|
||||
send_request("go_back");
|
||||
};
|
||||
break;
|
||||
|
||||
case 37: //LEFT
|
||||
e.preventDefault();
|
||||
var index = Array.prototype.indexOf.call(e.target.parentNode.children, e.target);
|
||||
if (index > 0){
|
||||
e.target.parentNode.children[index - 1].focus();
|
||||
};
|
||||
break;
|
||||
|
||||
case 38: //UP
|
||||
e.preventDefault();
|
||||
var index = Array.prototype.indexOf.call(el.children, e.target.parentNode);
|
||||
if (index == 0) {
|
||||
index = el.children.length;
|
||||
};
|
||||
el.children[index - 1].children[0].focus();
|
||||
break;
|
||||
|
||||
case 39: //RIGHT
|
||||
e.preventDefault();
|
||||
var index = Array.prototype.indexOf.call(e.target.parentNode.children, e.target);
|
||||
if (index < e.target.parentNode.children.length - 1){
|
||||
e.target.parentNode.children[index + 1].focus();
|
||||
};
|
||||
break;
|
||||
|
||||
case 40: //DOWN
|
||||
e.preventDefault();
|
||||
var index = Array.prototype.indexOf.call(el.children, e.target.parentNode);
|
||||
if (index + 1 == el.children.length) {
|
||||
index = -1;
|
||||
};
|
||||
el.children[index + 1].children[0].focus();
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
function window_loading_events(e) {
|
||||
switch (e.keyCode) {
|
||||
case 8: //BACK
|
||||
loading.close();
|
||||
connection_retry = false;
|
||||
e.preventDefault();
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
function body_events(e) {
|
||||
switch (e.keyCode) {
|
||||
case 8: //BACK
|
||||
e.preventDefault();
|
||||
break;
|
||||
|
||||
case 37: //LEFT
|
||||
case 38: //UP
|
||||
case 39: //RIGHT
|
||||
case 40: //DOWN
|
||||
e.preventDefault();
|
||||
document.getElementById("itemlist").children[0].children[0].focus();
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
function window_generic_events(e) {
|
||||
var el = (document.getElementById("window_ok").contains(e.target) ? document.getElementById("window_ok") : el);
|
||||
var el = (document.getElementById("window_yesno").contains(e.target) ? document.getElementById("window_yesno") : el);
|
||||
var el = (document.getElementById("window_progress").contains(e.target) ? document.getElementById("window_progress") : el);
|
||||
var el = (document.getElementById("window_info").contains(e.target) ? document.getElementById("window_info") : el);
|
||||
|
||||
switch (e.keyCode) {
|
||||
case 8: //BACK
|
||||
e.preventDefault();
|
||||
dialog.closeall();
|
||||
break;
|
||||
|
||||
case 38: //UP
|
||||
e.preventDefault();
|
||||
if (el.getElementById("window_footer").contains(e.target)) {
|
||||
el.children[0].focus();
|
||||
};
|
||||
break;
|
||||
|
||||
case 37: //LEFT
|
||||
e.preventDefault();
|
||||
|
||||
if (el.getElementById("window_footer").contains(e.target)) {
|
||||
var index = Array.prototype.indexOf.call(el.getElementById("window_footer").children, e.target) -1;
|
||||
while (index >= 0 && el.getElementById("window_footer").children[index].disabled){
|
||||
index --;
|
||||
};
|
||||
if (index >=0){
|
||||
el.getElementById("window_footer").children[index].focus();
|
||||
};
|
||||
};
|
||||
break;
|
||||
|
||||
case 39: //RIGHT
|
||||
e.preventDefault();
|
||||
if (el.getElementById("window_footer").contains(e.target)) {
|
||||
var index = Array.prototype.indexOf.call(el.getElementById("window_footer").children, e.target) +1;
|
||||
while (index < el.getElementById("window_footer").children.length && el.getElementById("window_footer").children[index].disabled){
|
||||
index ++;
|
||||
};
|
||||
if (index < el.getElementById("window_footer").children.length){
|
||||
el.getElementById("window_footer").children[index].focus();
|
||||
};
|
||||
};
|
||||
break;
|
||||
|
||||
case 40: //DOWN
|
||||
e.preventDefault();
|
||||
if (e.target.parentNode == el) {
|
||||
el.getElementById("window_footer").children[0].focus();
|
||||
};
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
function window_recaptcha_events(e) {
|
||||
var el = document.getElementById("window_recaptcha");
|
||||
|
||||
switch (e.keyCode) {
|
||||
case 8: //BACK
|
||||
e.preventDefault();
|
||||
dialog.closeall();
|
||||
break;
|
||||
|
||||
case 38: //UP
|
||||
e.preventDefault();
|
||||
if (el.getElementById("window_footer").contains(e.target)) {
|
||||
el.getElementById("window_image").children[el.getElementById("window_image").children.length -1].focus();
|
||||
}
|
||||
|
||||
else {
|
||||
var index = Array.prototype.indexOf.call(el.getElementById("window_image").children, e.target) -3;
|
||||
if (index >-1) {
|
||||
el.getElementById("window_image").children[index].focus();
|
||||
}
|
||||
else {
|
||||
el.children[0].focus();
|
||||
};
|
||||
};
|
||||
break;
|
||||
|
||||
case 37: //LEFT
|
||||
e.preventDefault();
|
||||
|
||||
if (el.getElementById("window_footer").contains(e.target)) {
|
||||
var index = Array.prototype.indexOf.call(el.getElementById("window_footer").children, e.target) -1;
|
||||
while (index >= 0 && el.getElementById("window_footer").children[index].disabled){
|
||||
index --;
|
||||
};
|
||||
if (index >=0){
|
||||
el.getElementById("window_footer").children[index].focus();
|
||||
};
|
||||
} else if (e.target.parentNode == el.getElementById("window_image")) {
|
||||
var index = Array.prototype.indexOf.call(el.getElementById("window_image").children, e.target) -1;
|
||||
if ([-1,2,5].indexOf(index) == -1) {
|
||||
el.getElementById("window_image").children[index].focus();
|
||||
};
|
||||
};
|
||||
break;
|
||||
|
||||
case 39: //RIGHT
|
||||
e.preventDefault();
|
||||
if (el.getElementById("window_footer").contains(e.target)) {
|
||||
var index = Array.prototype.indexOf.call(el.getElementById("window_footer").children, e.target) +1;
|
||||
while (index < el.getElementById("window_footer").children.length && el.getElementById("window_footer").children[index].disabled){
|
||||
index ++;
|
||||
};
|
||||
if (index < el.getElementById("window_footer").children.length){
|
||||
el.getElementById("window_footer").children[index].focus();
|
||||
};
|
||||
} else if (e.target.parentNode == el.getElementById("window_image")) {
|
||||
var index = Array.prototype.indexOf.call(el.getElementById("window_image").children, e.target) +1;
|
||||
if ([3,6,9].indexOf(index) == -1) {
|
||||
el.getElementById("window_image").children[index].focus();
|
||||
};
|
||||
};
|
||||
break;
|
||||
|
||||
case 40: //DOWN
|
||||
e.preventDefault();
|
||||
if (e.target.parentNode == el) {
|
||||
el.getElementById("window_image").children[0].focus();
|
||||
}
|
||||
else if (e.target.parentNode == el.getElementById("window_image")) {
|
||||
var index = Array.prototype.indexOf.call(el.getElementById("window_image").children, e.target) +3;
|
||||
if (index < el.getElementById("window_image").children.length) {
|
||||
el.getElementById("window_image").children[index].focus();
|
||||
}
|
||||
else {
|
||||
el.getElementById("window_footer").children[0].focus();
|
||||
};
|
||||
};
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
function window_select_events(e) {
|
||||
var el = document.getElementById('window_select');
|
||||
|
||||
switch (e.keyCode) {
|
||||
case 8: //BACK
|
||||
e.preventDefault();
|
||||
dialog.closeall();
|
||||
break;
|
||||
|
||||
case 38: //UP
|
||||
e.preventDefault();
|
||||
var index = Array.prototype.indexOf.call(el.getElementById("control_list").children, e.target.parentNode);
|
||||
if (index != 0) {
|
||||
el.getElementById("control_list").children[index - 1].children[0].focus();
|
||||
}
|
||||
else {
|
||||
el.children[0].focus();
|
||||
};
|
||||
break;
|
||||
|
||||
case 40: //DOWN
|
||||
e.preventDefault();
|
||||
if (e.target.parentNode == el) {
|
||||
el.getElementById("control_list").children[0].children[0].focus();
|
||||
}
|
||||
else {
|
||||
var index = Array.prototype.indexOf.call(el.getElementById("control_list").children, e.target.parentNode);
|
||||
el.getElementById("control_list").children[index + 1].children[0].focus();
|
||||
};
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
function window_settings_events(e) {
|
||||
el = document.getElementById('window_settings');
|
||||
|
||||
switch (e.keyCode) {
|
||||
case 8: //BACK
|
||||
if ((e.target.tagName != "INPUT" || (e.target.type != "text" && e.target.type != "password")) && e.target.tagName != "SELECT") {
|
||||
e.preventDefault();
|
||||
dialog.closeall();
|
||||
};
|
||||
break;
|
||||
|
||||
case 38: //UP
|
||||
e.preventDefault();
|
||||
if (e.target.parentNode == el) {
|
||||
return;
|
||||
};
|
||||
if (el.getElementById("category_container").contains(e.target)) {
|
||||
el.children[0].focus();
|
||||
return;
|
||||
|
||||
}
|
||||
else if (el.getElementById("window_footer").contains(e.target) || el.getElementById("window_footer_local").contains(e.target)) {
|
||||
var index = null;
|
||||
var group = null;
|
||||
|
||||
}
|
||||
else if (el.getElementById("controls_container").contains(e.target)) {
|
||||
var group = Array.prototype.indexOf.call(el.getElementById("controls_container").children, e.target.parentNode.parentNode.parentNode);
|
||||
var index = Array.prototype.indexOf.call(el.getElementById("controls_container").children[group].children, e.target.parentNode.parentNode) - 1;
|
||||
};
|
||||
|
||||
if (group == null) {
|
||||
for (group = 0; group < el.getElementById("category_container").children.length; group++) {
|
||||
if (el.getElementById("category_container").children[group].style.display != "none") {
|
||||
break;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
if (index == null) {
|
||||
index = el.getElementById("controls_container").children[group].children.length - 1;
|
||||
};
|
||||
|
||||
while (index >= 0 &&
|
||||
(el.getElementById("controls_container").children[group].children[index].children[0].className != "control" ||
|
||||
el.getElementById("controls_container").children[group].children[index].children[0].children[1].disabled ||
|
||||
el.getElementById("controls_container").children[group].children[index].style.display == "none")) {
|
||||
|
||||
index--;
|
||||
};
|
||||
|
||||
if (index >= 0) {
|
||||
el.getElementById("controls_container").children[group].children[index].children[0].children[1].focus();
|
||||
}
|
||||
else {
|
||||
if (el.getElementById("category_container").style.display == "none") {
|
||||
el.children[0].focus();
|
||||
}
|
||||
else {
|
||||
el.getElementById("category_container").children[0].focus();
|
||||
};
|
||||
};
|
||||
break;
|
||||
|
||||
case 37: //LEFT
|
||||
if ((e.target.tagName != "INPUT" || (e.target.type != "text" && e.target.type != "password")) && e.target.tagName != "SELECT") {
|
||||
e.preventDefault();
|
||||
if (el.getElementById("category_container").contains(e.target)) {
|
||||
var index = Array.prototype.indexOf.call(el.getElementById("category_container").children, e.target);
|
||||
el.getElementById("category_container").children[index - 1].focus();
|
||||
}
|
||||
else if (el.getElementById("window_footer").contains(e.target)) {
|
||||
var index = Array.prototype.indexOf.call(el.getElementById("window_footer").children, e.target);
|
||||
el.getElementById("window_footer").children[index - 1].focus();
|
||||
}
|
||||
else if (el.getElementById("window_footer_local").contains(e.target)) {
|
||||
var index = Array.prototype.indexOf.call(el.getElementById("window_footer_local").children, e.target);
|
||||
el.getElementById("window_footer_local").children[index - 1].focus();
|
||||
};
|
||||
};
|
||||
break;
|
||||
|
||||
case 39: //RIGHT
|
||||
if ((e.target.tagName != "INPUT" || (e.target.type != "text" && e.target.type != "password")) && e.target.tagName != "SELECT") {
|
||||
e.preventDefault();
|
||||
if (el.getElementById("category_container").contains(e.target)) {
|
||||
var index = Array.prototype.indexOf.call(el.getElementById("category_container").children, e.target);
|
||||
el.getElementById("category_container").children[index + 1].focus();
|
||||
}
|
||||
else if (el.getElementById("window_footer").contains(e.target)) {
|
||||
var index = Array.prototype.indexOf.call(el.getElementById("window_footer").children, e.target);
|
||||
el.getElementById("window_footer").children[index + 1].focus();
|
||||
}
|
||||
else if (el.getElementById("window_footer_local").contains(e.target)) {
|
||||
var index = Array.prototype.indexOf.call(el.getElementById("window_footer_local").children, e.target);
|
||||
el.getElementById("window_footer_local").children[index + 1].focus();
|
||||
};
|
||||
};
|
||||
break;
|
||||
|
||||
case 40: //DOWN
|
||||
e.preventDefault();
|
||||
if (e.target.parentNode == el) {
|
||||
if (el.getElementById("category_container").style.display == "none") {
|
||||
var index = 0;
|
||||
var group = null;
|
||||
}
|
||||
else {
|
||||
el.getElementById("category_container").children[0].focus();
|
||||
};
|
||||
}
|
||||
else if (el.getElementById("category_container").contains(e.target)) {
|
||||
var index = 0;
|
||||
var group = null;
|
||||
|
||||
}
|
||||
else if (el.getElementById("controls_container").contains(e.target)) {
|
||||
var group = Array.prototype.indexOf.call(el.getElementById("controls_container").children, e.target.parentNode.parentNode.parentNode);
|
||||
var index = Array.prototype.indexOf.call(el.getElementById("controls_container").children[group].children, e.target.parentNode.parentNode) + 1;
|
||||
};
|
||||
|
||||
if (group == null) {
|
||||
for (group = 0; group < el.getElementById("category_container").children.length; group++) {
|
||||
if (el.getElementById("category_container").children[group].style.display != "none") {
|
||||
break;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
while (index < el.getElementById("controls_container").children[group].children.length &&
|
||||
(el.getElementById("controls_container").children[group].children[index].children[0].className != "control" ||
|
||||
el.getElementById("controls_container").children[group].children[index].children[0].children[1].disabled ||
|
||||
el.getElementById("controls_container").children[group].children[index].style.display == "none")) {
|
||||
|
||||
index++;
|
||||
};
|
||||
|
||||
if (index < el.getElementById("controls_container").children[group].children.length) {
|
||||
el.getElementById("controls_container").children[group].children[index].children[0].children[1].focus();
|
||||
}
|
||||
else {
|
||||
el.getElementById("window_footer").children[0].focus();
|
||||
el.getElementById("window_footer_local").children[0].focus();
|
||||
};
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
function window_input_events(e) {
|
||||
el = document.getElementById("window_input");
|
||||
|
||||
switch (e.keyCode) {
|
||||
case 8: //BACK
|
||||
if (e.target.tagName != "INPUT") {
|
||||
e.preventDefault();
|
||||
dialog.closeall();
|
||||
};
|
||||
break;
|
||||
|
||||
case 38: //UP
|
||||
e.preventDefault();
|
||||
if (el.getElementById("window_footer").contains(e.target)) {
|
||||
el.getElementById("control_input").children[0].focus();
|
||||
}
|
||||
if (el.getElementById("control_input").contains(e.target)) {
|
||||
el.children[0].focus();
|
||||
};
|
||||
break;
|
||||
|
||||
case 37: //LEFT
|
||||
if (el.getElementById("window_footer").contains(e.target)) {
|
||||
var index = Array.prototype.indexOf.call(el.getElementById("window_footer").children, e.target);
|
||||
el.getElementById("window_footer").children[index - 1].focus();
|
||||
e.preventDefault();
|
||||
};
|
||||
break;
|
||||
|
||||
case 39: //RIGHT
|
||||
if (el.getElementById("window_footer").contains(e.target)) {
|
||||
var index = Array.prototype.indexOf.call(el.getElementById("window_footer").children, e.target);
|
||||
el.getElementById("window_footer").children[index + 1].focus();
|
||||
e.preventDefault();
|
||||
};
|
||||
break;
|
||||
|
||||
case 40: //DOWN
|
||||
e.preventDefault();
|
||||
if (e.target.parentNode == el) {
|
||||
el.getElementById("control_input").children[0].focus();
|
||||
};
|
||||
if (el.getElementById("control_input").contains(e.target)) {
|
||||
el.getElementById("window_footer").children[0].focus();
|
||||
};
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
function numeric_search(keyCode) {
|
||||
switch (keyCode) {
|
||||
case 96:
|
||||
keychar["keyCode"] = keyCode;
|
||||
keychar["Char"] = "0";
|
||||
break;
|
||||
|
||||
case 97:
|
||||
keychar["keyCode"] = keyCode;
|
||||
keychar["Char"] = "1";
|
||||
break;
|
||||
|
||||
case 98:
|
||||
if (keychar["keyCode"] == keyCode) {
|
||||
switch (keychar["Char"]) {
|
||||
case "a":
|
||||
keychar["Char"] = "b";
|
||||
break;
|
||||
case "b":
|
||||
keychar["Char"] = "c";
|
||||
break;
|
||||
case "c":
|
||||
keychar["Char"] = "2";
|
||||
break;
|
||||
case "2":
|
||||
keychar["Char"] = "a";
|
||||
break;
|
||||
};
|
||||
}
|
||||
else {
|
||||
keychar["keyCode"] = keyCode;
|
||||
keychar["Char"] = "a";
|
||||
};
|
||||
break;
|
||||
|
||||
case 99:
|
||||
if (keychar["keyCode"] == keyCode) {
|
||||
switch (keychar["Char"]) {
|
||||
case "d":
|
||||
keychar["Char"] = "e";
|
||||
break;
|
||||
case "e":
|
||||
keychar["Char"] = "f";
|
||||
break;
|
||||
case "f":
|
||||
keychar["Char"] = "3";
|
||||
break;
|
||||
case "3":
|
||||
keychar["Char"] = "d";
|
||||
break;
|
||||
};
|
||||
}
|
||||
else {
|
||||
keychar["keyCode"] = keyCode;
|
||||
keychar["Char"] = "d";
|
||||
};
|
||||
break;
|
||||
|
||||
case 100:
|
||||
if (keychar["keyCode"] == keyCode) {
|
||||
switch (keychar["Char"]) {
|
||||
case "g":
|
||||
keychar["Char"] = "h";
|
||||
break;
|
||||
case "h":
|
||||
keychar["Char"] = "i";
|
||||
break;
|
||||
case "i":
|
||||
keychar["Char"] = "4";
|
||||
break;
|
||||
case "4":
|
||||
keychar["Char"] = "g";
|
||||
break;
|
||||
};
|
||||
}
|
||||
else {
|
||||
keychar["keyCode"] = keyCode;
|
||||
keychar["Char"] = "g";
|
||||
};
|
||||
break;
|
||||
|
||||
case 101:
|
||||
if (keychar["keyCode"] == keyCode) {
|
||||
switch (keychar["Char"]) {
|
||||
case "j":
|
||||
keychar["Char"] = "k";
|
||||
break;
|
||||
case "k":
|
||||
keychar["Char"] = "l";
|
||||
break;
|
||||
case "l":
|
||||
keychar["Char"] = "5";
|
||||
break;
|
||||
case "5":
|
||||
keychar["Char"] = "j";
|
||||
break;
|
||||
};
|
||||
}
|
||||
else {
|
||||
keychar["keyCode"] = keyCode;
|
||||
keychar["Char"] = "j";
|
||||
};
|
||||
break;
|
||||
|
||||
case 102:
|
||||
if (keychar["keyCode"] == keyCode) {
|
||||
switch (keychar["Char"]) {
|
||||
case "m":
|
||||
keychar["Char"] = "n";
|
||||
break;
|
||||
case "n":
|
||||
keychar["Char"] = "o";
|
||||
break;
|
||||
case "o":
|
||||
keychar["Char"] = "6";
|
||||
break;
|
||||
case "6":
|
||||
keychar["Char"] = "m";
|
||||
break;
|
||||
};
|
||||
}
|
||||
else {
|
||||
keychar["keyCode"] = keyCode;
|
||||
keychar["Char"] = "m";
|
||||
};
|
||||
break;
|
||||
|
||||
case 103:
|
||||
if (keychar["keyCode"] == keyCode) {
|
||||
switch (keychar["Char"]) {
|
||||
case "p":
|
||||
keychar["Char"] = "q";
|
||||
break;
|
||||
case "q":
|
||||
keychar["Char"] = "r";
|
||||
break;
|
||||
case "r":
|
||||
keychar["Char"] = "s";
|
||||
break;
|
||||
case "s":
|
||||
keychar["Char"] = "7";
|
||||
break;
|
||||
case "7":
|
||||
keychar["Char"] = "p";
|
||||
break;
|
||||
};
|
||||
}
|
||||
else {
|
||||
keychar["keyCode"] = keyCode;
|
||||
keychar["Char"] = "p";
|
||||
};
|
||||
break;
|
||||
|
||||
case 104:
|
||||
if (keychar["keyCode"] == keyCode) {
|
||||
switch (keychar["Char"]) {
|
||||
case "t":
|
||||
keychar["Char"] = "u";
|
||||
break;
|
||||
case "u":
|
||||
keychar["Char"] = "u";
|
||||
break;
|
||||
case "v":
|
||||
keychar["Char"] = "8";
|
||||
break;
|
||||
case "8":
|
||||
keychar["Char"] = "t";
|
||||
break;
|
||||
};
|
||||
}
|
||||
else {
|
||||
keychar["keyCode"] = keyCode;
|
||||
keychar["Char"] = "t";
|
||||
};
|
||||
break;
|
||||
|
||||
case 105:
|
||||
if (keychar["keyCode"] == keyCode) {
|
||||
switch (keychar["Char"]) {
|
||||
case "x":
|
||||
keychar["Char"] = "y";
|
||||
break;
|
||||
case "y":
|
||||
keychar["Char"] = "z";
|
||||
break;
|
||||
case "z":
|
||||
keychar["Char"] = "w";
|
||||
break;
|
||||
case "w":
|
||||
keychar["Char"] = "9";
|
||||
break;
|
||||
case "9":
|
||||
keychar["Char"] = "x";
|
||||
break;
|
||||
};
|
||||
}
|
||||
else {
|
||||
keychar["keyCode"] = keyCode;
|
||||
keychar["Char"] = "x";
|
||||
};
|
||||
break;
|
||||
};
|
||||
|
||||
var el = document.getElementById('itemlist');
|
||||
|
||||
for (x = 0; x < el.children.length; x++) {
|
||||
if (el.children[x].children[0].children[2].innerHTML.toLowerCase().indexOf(keychar["Char"]) === 0) {
|
||||
el.children[x].children[0].focus();
|
||||
break;
|
||||
};
|
||||
if (el.children[x].children[0].children[0].innerHTML.toLowerCase().indexOf(keychar["Char"]) === 0) {
|
||||
el.children[x].children[0].focus();
|
||||
break;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
document.onkeypress = function (e) {
|
||||
if ((e || window.event).keyCode === 32) {
|
||||
if (media_player.paused) {
|
||||
media_player.play();
|
||||
}
|
||||
else {
|
||||
media_player.pause();
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
document.ondblclick = function () {
|
||||
if (media_player.requestFullscreen) {
|
||||
media_player.requestFullscreen();
|
||||
}
|
||||
else if (media_player.mozRequestFullScreen) {
|
||||
media_player.mozRequestFullScreen();
|
||||
}
|
||||
else if (media_player.webkitRequestFullscreen) {
|
||||
media_player.webkitRequestFullscreen();
|
||||
};
|
||||
};
|
||||
674
mediaserver/platformcode/template/js/protocol.js
Normal file
674
mediaserver/platformcode/template/js/protocol.js
Normal file
@@ -0,0 +1,674 @@
|
||||
function get_response(data) {
|
||||
var response = JSON.parse(data)
|
||||
var data = response.data;
|
||||
|
||||
switch (response.action) {
|
||||
case "connect":
|
||||
document.getElementById("version").innerHTML = data.version;
|
||||
document.getElementById("date").innerHTML = data.date;
|
||||
session_id = response.id;
|
||||
break;
|
||||
|
||||
case "EndItems":
|
||||
var item_list = [];
|
||||
|
||||
for (var item in data.itemlist) {
|
||||
context_items = [];
|
||||
item = data.itemlist[item];
|
||||
if (item.thumbnail && item.thumbnail.indexOf("http") != 0) {
|
||||
item.thumbnail = domain + "/local/" + encodeURIComponent(btoa(item.thumbnail));
|
||||
}
|
||||
else if (item.thumbnail & false){
|
||||
item.thumbnail = domain + "/proxy/" + encodeURIComponent(btoa(item.thumbnail));
|
||||
};
|
||||
if (item.fanart && item.fanart.indexOf("http") != 0) {
|
||||
item.fanart = domain + "/local/" + encodeURIComponent(btoa(item.fanart));
|
||||
}
|
||||
else if (item.fanart & false){
|
||||
item.fanart = domain + "/proxy/" + encodeURIComponent(btoa(item.fanart));
|
||||
};
|
||||
|
||||
if (item.action == "go_back") {
|
||||
item.url = "go_back";
|
||||
};
|
||||
|
||||
if (item.context.length ) {
|
||||
for (var x in item.context) {
|
||||
html_item = replace_list(html.dialog.select.item, {
|
||||
"item_action": "send_request('" + item.context[x].url + "')",
|
||||
"item_title": item.context[x].title
|
||||
});
|
||||
context_items.push(html_item);
|
||||
}
|
||||
var menu_button = replace_list(html.itemlist.menu, {
|
||||
"menu_items": btoa(context_items.join(""))
|
||||
});
|
||||
var menu_class = "item_with_menu";
|
||||
}
|
||||
else {
|
||||
var menu_button = "";
|
||||
var menu_class = "";
|
||||
};
|
||||
|
||||
var replace_dict = {
|
||||
"item_class": menu_class,
|
||||
"item_url": item.url,
|
||||
"item_thumbnail": item.thumbnail,
|
||||
"item_fanart": item.fanart,
|
||||
"item_title": item.title,
|
||||
"item_plot": item.plot,
|
||||
"item_menu": menu_button,
|
||||
"menu_items": btoa(context_items.join(""))
|
||||
};
|
||||
|
||||
if (html.itemlist[data.viewmode]) {
|
||||
var html_item = replace_list(html.itemlist[data.viewmode], replace_dict);
|
||||
}
|
||||
else {
|
||||
var html_item = replace_list(html.itemlist.movie, replace_dict);
|
||||
}
|
||||
item_list.push(html_item);
|
||||
|
||||
};
|
||||
|
||||
document.getElementById("itemlist").innerHTML = item_list.join("");
|
||||
set_category(data.category);
|
||||
document.getElementById("itemlist").children[0].children[0].focus();
|
||||
document.getElementById("itemlist").scrollTop = 0;
|
||||
show_images();
|
||||
|
||||
nav_history.newResponse(item_list, data.category);
|
||||
|
||||
//console.debug(nav_history)
|
||||
send_data({
|
||||
"id": response.id,
|
||||
"result": true
|
||||
});
|
||||
loading.close();
|
||||
break;
|
||||
|
||||
case "Refresh":
|
||||
nav_history.current -= 1
|
||||
send_request(nav_history.states[nav_history.current].url);
|
||||
send_data({
|
||||
"id": response.id,
|
||||
"result": true
|
||||
});
|
||||
break;
|
||||
|
||||
case "Alert":
|
||||
loading.close();
|
||||
dialog.ok(response.id, data);
|
||||
break;
|
||||
|
||||
case "notification":
|
||||
dialog.notification(response.id, data);
|
||||
break;
|
||||
|
||||
case "AlertYesNo":
|
||||
loading.close()
|
||||
dialog.yesno(response.id, data)
|
||||
break;
|
||||
|
||||
case "ProgressBG":
|
||||
dialog.progress_bg(response.id, data);
|
||||
send_data({
|
||||
"id": response.id,
|
||||
"result": true
|
||||
});
|
||||
break;
|
||||
|
||||
case "ProgressBGUpdate":
|
||||
dialog.progress_bg(response.id, data);
|
||||
break;
|
||||
|
||||
case "ProgressBGClose":
|
||||
dialog.progress_bg_close();
|
||||
send_data({
|
||||
"id": response.id,
|
||||
"result": true
|
||||
});
|
||||
break;
|
||||
|
||||
case "Progress":
|
||||
loading.close();
|
||||
dialog.progress(response.id, data);
|
||||
send_data({
|
||||
"id": response.id,
|
||||
"result": true
|
||||
});
|
||||
break;
|
||||
|
||||
case "ProgressUpdate":
|
||||
dialog.progress_update(response.id, data);
|
||||
break;
|
||||
|
||||
case "ProgressClose":
|
||||
dialog.progress_close();
|
||||
send_data({
|
||||
"id": response.id,
|
||||
"result": true
|
||||
});
|
||||
loading.close();
|
||||
break;
|
||||
|
||||
case "ProgressIsCanceled":
|
||||
send_data({
|
||||
"id": response.id,
|
||||
"result": document.getElementById("window_progress").getElementById("canceled").checked != ""
|
||||
});
|
||||
break;
|
||||
|
||||
case "isPlaying":
|
||||
send_data({
|
||||
"id": response.id,
|
||||
"result": document.getElementById("Player-popup").style.display == "block" || document.getElementById("Lista-popup").style.display == "block"
|
||||
});
|
||||
break;
|
||||
|
||||
case "Keyboard":
|
||||
loading.close();
|
||||
dialog.keyboard(response.id, data);
|
||||
break;
|
||||
|
||||
case "recaptcha":
|
||||
loading.close();
|
||||
dialog.recaptcha(response.id, data);
|
||||
break;
|
||||
|
||||
case "recaptcha_select":
|
||||
loading.close();
|
||||
dialog.recaptcha_select(response.id, data);
|
||||
break
|
||||
|
||||
case "List":
|
||||
loading.close();
|
||||
dialog.select(response.id, data);
|
||||
break;
|
||||
|
||||
case "Play":
|
||||
send_data({
|
||||
"id": response.id,
|
||||
"result": true
|
||||
});
|
||||
|
||||
loading.close();
|
||||
|
||||
if (settings.player_mode == 0) {
|
||||
var lista = [];
|
||||
for (var player in players) {
|
||||
lista.push(replace_list(html.dialog.select.item, {
|
||||
"item_title": players[player],
|
||||
"item_action": "play_mode('" + data.video_url + "','" + data.title + "','" + player + "')"
|
||||
}));
|
||||
};
|
||||
dialog.menu("Elige el Reproductor", btoa(lista.join("")));
|
||||
|
||||
}
|
||||
else {
|
||||
play_mode(data.video_url, data.title, Object.keys(players)[settings.player_mode - 1]);
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
case "Update":
|
||||
send_request(data.url);
|
||||
loading.close();
|
||||
break;
|
||||
|
||||
case "HideLoading":
|
||||
loading.close();
|
||||
break;
|
||||
|
||||
case "ShowLoading":
|
||||
loading.show();
|
||||
break;
|
||||
|
||||
case "OpenInfo":
|
||||
loading.close();
|
||||
dialog.info(response.id, data);
|
||||
break;
|
||||
|
||||
case "custom_button":
|
||||
dialog.custom_button(response.id, data);
|
||||
break;
|
||||
|
||||
case "OpenConfig":
|
||||
loading.close();
|
||||
var itemlist = {};
|
||||
default_settings = {};
|
||||
settings_controls = [];
|
||||
|
||||
for (var x in data.items) {
|
||||
|
||||
if (!itemlist[data.items[x].category]) {
|
||||
itemlist[data.items[x].category] = [];
|
||||
};
|
||||
if (data.items[x].id) {
|
||||
default_settings[data.items[x].id] = data.items[x]["default"];
|
||||
}
|
||||
if (!data.items[x].color || data.items[x].color == "auto") {
|
||||
data.items[x].color = "#FFFFFF";
|
||||
};
|
||||
if (!data.items[x].enabled && data.items[x].enable) {
|
||||
data.items[x].enabled = data.items[x].enable;
|
||||
};
|
||||
|
||||
settings_controls.push(data.items[x]);
|
||||
|
||||
switch (data.items[x].type) {
|
||||
case "sep":
|
||||
itemlist[data.items[x].category].push(replace_list(html.config.sep, {}));
|
||||
break;
|
||||
|
||||
case "lsep":
|
||||
case "label":
|
||||
itemlist[data.items[x].category].push(replace_list(html.config.label, {
|
||||
"item_color": data.items[x].color,
|
||||
"item_label": data.items[x].label
|
||||
}));
|
||||
break;
|
||||
|
||||
case "number":
|
||||
case "text":
|
||||
if (data.items[x].hidden) {
|
||||
var type = "password";
|
||||
}
|
||||
else {
|
||||
var type = "text";
|
||||
};
|
||||
if (data.items[x].type == 'number') {
|
||||
keypress = "if ('0123456789'.indexOf(event.key) == -1 && event.charCode){return false}"
|
||||
}
|
||||
else {
|
||||
keypress = "";
|
||||
};
|
||||
itemlist[data.items[x].category].push(replace_list(html.config.text, {
|
||||
"item_color": data.items[x].color,
|
||||
"item_label": data.items[x].label,
|
||||
"item_id": data.items[x].id,
|
||||
"item_value": data.items[x].value,
|
||||
"item_type": type,
|
||||
"keypress": keypress
|
||||
|
||||
}));
|
||||
break;
|
||||
|
||||
case "bool":
|
||||
if (data.items[x].value == "true" || data.items[x].value == true) {
|
||||
var value = "checked='checked'";
|
||||
}
|
||||
else {
|
||||
var value = "";
|
||||
};
|
||||
itemlist[data.items[x].category].push(replace_list(html.config.bool, {
|
||||
"item_color": data.items[x].color,
|
||||
"item_label": data.items[x].label,
|
||||
"item_id": data.items[x].id,
|
||||
"item_value": value
|
||||
}));
|
||||
break;
|
||||
|
||||
case "labelenum":
|
||||
if (!data.items[x].values) {
|
||||
var values = data.items[x].lvalues.split("|");
|
||||
}
|
||||
else {
|
||||
var values = data.items[x].values.split("|");
|
||||
};
|
||||
|
||||
var options = [];
|
||||
for (var y in values) {
|
||||
if (data.items[x].value == values[y]) {
|
||||
options.push("<option selected=selected>" + values[y] + "</option>");
|
||||
}
|
||||
else {
|
||||
options.push("<option>" + values[y] + "</option>");
|
||||
};
|
||||
};
|
||||
itemlist[data.items[x].category].push(replace_list(html.config.list, {
|
||||
"item_type": "labelenum",
|
||||
"item_color": data.items[x].color,
|
||||
"item_label": data.items[x].label,
|
||||
"item_id": data.items[x].id,
|
||||
"item_values": options
|
||||
}));
|
||||
break;
|
||||
|
||||
case "list":
|
||||
var options = [];
|
||||
for (var y in data.items[x].lvalues) {
|
||||
if (data.items[x].value == y) {
|
||||
options.push("<option selected=selected>" + data.items[x].lvalues[y] + "</option>");
|
||||
}
|
||||
else {
|
||||
options.push("<option>" + data.items[x].lvalues[y] + "</option>");
|
||||
};
|
||||
};
|
||||
|
||||
itemlist[data.items[x].category].push(replace_list(html.config.list, {
|
||||
"item_type": "enum",
|
||||
"item_color": data.items[x].color,
|
||||
"item_label": data.items[x].label,
|
||||
"item_id": data.items[x].id,
|
||||
"item_values": options
|
||||
}));
|
||||
break;
|
||||
|
||||
case "enum":
|
||||
if (!data.items[x].values) {
|
||||
var values = data.items[x].lvalues.split("|");
|
||||
}
|
||||
else {
|
||||
var values = data.items[x].values.split("|");
|
||||
};
|
||||
|
||||
var options = [];
|
||||
for (var y in values) {
|
||||
if (data.items[x].value == y) {
|
||||
options.push("<option selected=selected>" + values[y] + "</option>");
|
||||
}
|
||||
else {
|
||||
options.push("<option>" + values[y] + "</option>");
|
||||
};
|
||||
};
|
||||
|
||||
itemlist[data.items[x].category].push(replace_list(html.config.list, {
|
||||
"item_type": "enum",
|
||||
"item_color": data.items[x].color,
|
||||
"item_label": data.items[x].label,
|
||||
"item_id": data.items[x].id,
|
||||
"item_values": options
|
||||
}));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
var categories = [];
|
||||
var category_list = [];
|
||||
|
||||
for (var category in itemlist) {
|
||||
if (Object.keys(itemlist).length > 1 || category != "undefined") {
|
||||
categories.push(replace_list(html.config.category, {
|
||||
"item_label": category,
|
||||
"item_category": category
|
||||
}));
|
||||
};
|
||||
category_list.push(replace_list(html.config.container, {
|
||||
"item_id": "category_" + category,
|
||||
"item_value": itemlist[category].join("")
|
||||
}));
|
||||
|
||||
};
|
||||
dialog.config(response.id, data, categories.join(""), category_list.join(""));
|
||||
evaluate_controls();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
function custom_button(data) {
|
||||
if (data == null) {
|
||||
var controls = document.getElementById("window_settings").getControls();
|
||||
|
||||
for (var x in controls) {
|
||||
switch (controls[x].type) {
|
||||
case "text":
|
||||
controls[x].value = default_settings[controls[x].id];
|
||||
break;
|
||||
case "password":
|
||||
controls[x].value = default_settings[controls[x].id];
|
||||
break;
|
||||
case "checkbox":
|
||||
value = default_settings[controls[x].id];
|
||||
if (value == true) {
|
||||
value = "checked";
|
||||
}
|
||||
else {
|
||||
value = "";
|
||||
};
|
||||
controls[x].checked = value;
|
||||
break;
|
||||
case "select-one":
|
||||
if (controls[x].name == "enum") {
|
||||
controls[x].selectedIndex = default_settings[controls[x].id];
|
||||
}
|
||||
else if (controls[x].name == "labelenum") {
|
||||
controls[x].value = default_settings[controls[x].id];
|
||||
};
|
||||
break;
|
||||
};
|
||||
controls[x].onchange()
|
||||
};
|
||||
}
|
||||
else {
|
||||
send_data({
|
||||
"id": document.getElementById("window_settings").RequestID,
|
||||
"result": "custom_button"
|
||||
});
|
||||
if (data["close"] == true) {
|
||||
dialog.closeall();
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
function info_window(comando) {
|
||||
send_data({
|
||||
"id": document.getElementById("window_info").RequestID,
|
||||
"result": comando
|
||||
});
|
||||
};
|
||||
|
||||
function save_config(Guardar) {
|
||||
if (Guardar === true) {
|
||||
var JsonAjustes = {};
|
||||
var controls = document.getElementById("window_settings").getControls();
|
||||
|
||||
for (var x in controls) {
|
||||
switch (controls[x].type) {
|
||||
case "text":
|
||||
JsonAjustes[controls[x].id] = controls[x].value;
|
||||
break;
|
||||
case "password":
|
||||
JsonAjustes[controls[x].id] = controls[x].value;
|
||||
break;
|
||||
case "checkbox":
|
||||
JsonAjustes[controls[x].id] = controls[x].checked.toString();
|
||||
break;
|
||||
case "select-one":
|
||||
if (controls[x].name == "enum") {
|
||||
JsonAjustes[controls[x].id] = controls[x].selectedIndex.toString();
|
||||
}
|
||||
else if (controls[x].name == "labelenum") {
|
||||
JsonAjustes[controls[x].id] = controls[x].value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
send_data({
|
||||
"id": document.getElementById("window_settings").RequestID,
|
||||
"result": JsonAjustes
|
||||
});
|
||||
}
|
||||
else {
|
||||
send_data({
|
||||
"id": document.getElementById("window_settings").RequestID,
|
||||
"result": false
|
||||
});
|
||||
};
|
||||
|
||||
loading.show();
|
||||
};
|
||||
|
||||
function evaluate_controls(control_changed) {
|
||||
if (typeof control_changed != "undefined") {
|
||||
for (var x in settings_controls) {
|
||||
if (settings_controls[x].id == control_changed.id) {
|
||||
switch (control_changed.type) {
|
||||
case "text":
|
||||
settings_controls[x].value = control_changed.value;
|
||||
break;
|
||||
case "password":
|
||||
settings_controls[x].value = control_changed.value;
|
||||
break;
|
||||
case "checkbox":
|
||||
settings_controls[x].value = control_changed.checked;
|
||||
break;
|
||||
case "select-one":
|
||||
if (control_changed.name == "enum") {
|
||||
settings_controls[x].value = control_changed.selectedIndex;
|
||||
}
|
||||
else if (control_changed.name == "labelenum") {
|
||||
settings_controls[x].value = control_changed.value;
|
||||
};
|
||||
break;
|
||||
};
|
||||
break;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
for (var index in settings_controls) {
|
||||
control = get_control_group(index);
|
||||
set_visible(document.getElementById("window_settings").getElementById("controls_container").children[control[0]].children[control[1]], evaluate(index, settings_controls[index].visible));
|
||||
set_enabled(document.getElementById("window_settings").getElementById("controls_container").children[control[0]].children[control[1]], evaluate(index, settings_controls[index].enabled));
|
||||
};
|
||||
};
|
||||
|
||||
function set_visible(element, visible) {
|
||||
if (visible) {
|
||||
element.style.display = "block";
|
||||
}
|
||||
else {
|
||||
element.style.display = "none";
|
||||
};
|
||||
};
|
||||
|
||||
function set_enabled(element, enabled) {
|
||||
if (element.children[0].className == "control") {
|
||||
element.children[0].children[1].disabled = !enabled;
|
||||
};
|
||||
};
|
||||
|
||||
function get_control_group(index) {
|
||||
var group = 0;
|
||||
var pos = 0;
|
||||
var children = document.getElementById("window_settings").getElementById("controls_container").children;
|
||||
for (child in children) {
|
||||
if (pos + children[child].children.length <= index) {
|
||||
group ++;
|
||||
pos += children[child].children.length;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
};
|
||||
};
|
||||
return [group, index - pos];
|
||||
};
|
||||
|
||||
function evaluate(index, condition) {
|
||||
index = parseInt(index);
|
||||
|
||||
if (typeof condition == "undefined") {
|
||||
return true;
|
||||
};
|
||||
if (typeof condition == "boolean") {
|
||||
return condition;
|
||||
};
|
||||
|
||||
if (condition.toLocaleLowerCase() == "true") {
|
||||
return true;
|
||||
}
|
||||
else if (condition.toLocaleLowerCase() == "false") {
|
||||
return false;
|
||||
};
|
||||
|
||||
const regex = /(!?eq|!?gt|!?lt)?\(([^,]+),[\"|']?([^)|'|\"]*)['|\"]?\)[ ]*([+||])?/g;
|
||||
|
||||
while ((m = regex.exec(condition)) !== null) {
|
||||
// This is necessary to avoid infinite loops with zero-width matches
|
||||
if (m.index === regex.lastIndex) {
|
||||
regex.lastIndex++;
|
||||
};
|
||||
|
||||
var operator = m[1];
|
||||
var id = parseInt(m[2]);
|
||||
var value = m[3];
|
||||
var next = m[4];
|
||||
|
||||
if (isNaN(id)) {
|
||||
return false;
|
||||
};
|
||||
|
||||
if (index + id < 0 || index + id >= settings_controls.length) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if (settings_controls[index + id].type == "list" || settings_controls[index + id].type == "enum") {
|
||||
if (settings_controls[index + id].lvalues){
|
||||
control_value = settings_controls[index + id].lvalues[settings_controls[index + id].value];
|
||||
}
|
||||
else {
|
||||
control_value = settings_controls[index + id].values[settings_controls[index + id].value];
|
||||
};
|
||||
}
|
||||
else {
|
||||
control_value = settings_controls[index + id].value;
|
||||
};
|
||||
};
|
||||
|
||||
if (["lt", "!lt", "gt", "!gt"].indexOf(operator) > -1) {
|
||||
value = parseInt(value);
|
||||
if (isNaN(value)) {
|
||||
return false;
|
||||
};
|
||||
};
|
||||
|
||||
if (["eq", "!eq"].indexOf(operator) > -1) {
|
||||
if (typeof(value) == "string") {
|
||||
if (!isNaN(parseInt(value))) {
|
||||
value = parseInt(value);
|
||||
}
|
||||
else if (value.toLocaleLowerCase() == "true") {
|
||||
value = true;
|
||||
}
|
||||
else if (value.toLocaleLowerCase() == "false") {
|
||||
value = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
if (operator == "eq") {
|
||||
ok = (control_value == value);
|
||||
};
|
||||
if (operator == "!eq") {
|
||||
ok = !(control_value == value);
|
||||
};
|
||||
if (operator == "gt") {
|
||||
ok = (control_value > value);
|
||||
};
|
||||
if (operator == "!gt") {
|
||||
ok = !(control_value > value);
|
||||
};
|
||||
if (operator == "lt") {
|
||||
ok = (control_value < value);
|
||||
};
|
||||
if (operator == "!lt") {
|
||||
ok = !(control_value < value);
|
||||
};
|
||||
|
||||
if (next == "|" && ok == true) {
|
||||
break;
|
||||
};
|
||||
if (next == "+" && ok == false) {
|
||||
break;
|
||||
};
|
||||
};
|
||||
return ok;
|
||||
};
|
||||
79
mediaserver/platformcode/template/js/socket.js
Normal file
79
mediaserver/platformcode/template/js/socket.js
Normal file
@@ -0,0 +1,79 @@
|
||||
function websocket_connect() {
|
||||
if (websocket) {
|
||||
websocket.close();
|
||||
};
|
||||
var status = document.getElementById("footer").getElementById("status");
|
||||
status.innerHTML = "Conectando...";
|
||||
|
||||
loading.show("Estableciendo conexión...");
|
||||
websocket = new WebSocket(websocket_host);
|
||||
websocket.onopen = function (evt) {
|
||||
loading.show();
|
||||
status.innerHTML = "Conectado";
|
||||
};
|
||||
|
||||
websocket.onclose = function (evt) {
|
||||
status.innerHTML = "Desconectado";
|
||||
};
|
||||
|
||||
websocket.onmessage = function (evt) {
|
||||
get_response(evt.data);
|
||||
};
|
||||
|
||||
websocket.onerror = function (evt) {
|
||||
websocket.close();
|
||||
};
|
||||
};
|
||||
|
||||
function websocket_send(data, retry) {
|
||||
if (!retry) {
|
||||
connection_retry = true;
|
||||
};
|
||||
if (!websocket){
|
||||
websocket_connect();
|
||||
};
|
||||
if (websocket.readyState != 1) {
|
||||
if ((websocket.readyState == 2 || websocket.readyState == 3) && connection_retry) {
|
||||
websocket_connect();
|
||||
};
|
||||
setTimeout(websocket_send, 500, data, true);
|
||||
return;
|
||||
}
|
||||
else if (websocket.readyState == 1) {
|
||||
data["id"] = session_id;
|
||||
websocket.send(JSON.stringify(data));
|
||||
};
|
||||
};
|
||||
|
||||
function send_request(url) {
|
||||
if (url == "go_back") {
|
||||
nav_history.go(-1);
|
||||
return;
|
||||
};
|
||||
|
||||
nav_history.newRequest(url);
|
||||
|
||||
loading.show();
|
||||
var send = {};
|
||||
send["request"] = url;
|
||||
websocket_send(send);
|
||||
};
|
||||
|
||||
function send_data(dato) {
|
||||
var send = {};
|
||||
send["data"] = dato;
|
||||
websocket_send(send);
|
||||
};
|
||||
|
||||
function ajax_to_dict(url, obj, key) {
|
||||
var xhttp = new XMLHttpRequest();
|
||||
ajax_running.push(xhttp);
|
||||
xhttp.onreadystatechange = function () {
|
||||
if (this.readyState == 4 && this.status == 200) {
|
||||
eval("obj." + key + " = xhttp.responseText");
|
||||
ajax_running.remove(xhttp)
|
||||
};
|
||||
};
|
||||
xhttp.open("GET", url, true);
|
||||
xhttp.send();
|
||||
};
|
||||
225
mediaserver/platformcode/template/js/ui.js
Normal file
225
mediaserver/platformcode/template/js/ui.js
Normal file
@@ -0,0 +1,225 @@
|
||||
function dispose() {
|
||||
var height = document.getElementById("window").offsetHeight;
|
||||
var header = document.getElementById("header").offsetHeight;
|
||||
var footer = document.getElementById("footer").offsetHeight;
|
||||
var panelheight = height - header - footer;
|
||||
document.getElementById('content').style.height = panelheight + "px";
|
||||
if (document.getElementById("window").offsetWidth < 800) {
|
||||
document.getElementById('panel_items').className = "panel_items_vertical";
|
||||
document.getElementById('panel_info').className = "panel_info_vertical";
|
||||
}
|
||||
else {
|
||||
document.getElementById('panel_items').className = "panel_items";
|
||||
document.getElementById('panel_info').className = "panel_info";
|
||||
}
|
||||
};
|
||||
|
||||
function replace_list(data, list) {
|
||||
for (var key in list) {
|
||||
var re = new RegExp("%" + key, "g");
|
||||
data = data.replace(re, list[key]);
|
||||
};
|
||||
return data;
|
||||
};
|
||||
|
||||
function play_mode(url, title, player) {
|
||||
if (!new RegExp("^(.+://)").test(url)) {
|
||||
url = domain + "/local/" + encodeURIComponent(btoa(Utf8.encode(data.video_url))) + "/video.mp4";
|
||||
}
|
||||
else {
|
||||
var indirect_url = domain + "/proxy/" + encodeURIComponent(btoa(Utf8.encode(url))) + "/video.mp4";
|
||||
};
|
||||
|
||||
if (settings.play_mode == 0 && indirect_url) {
|
||||
var lista = [];
|
||||
lista.push(replace_list(html.dialog.select.item, {
|
||||
"item_title": "Indirecto",
|
||||
"item_action": player + "('" + indirect_url + "','" + title + "')"
|
||||
}));
|
||||
lista.push(replace_list(html.dialog.select.item, {
|
||||
"item_title": "Directo",
|
||||
"item_action": player + "('" + url + "','" + title + "')"
|
||||
}));
|
||||
dialog.menu("Metodo de reproducción", btoa(lista.join("")));
|
||||
}
|
||||
else if (settings.play_mode == 1 && indirect_url) {
|
||||
eval(player)(indirect_url, title);
|
||||
}
|
||||
else {
|
||||
eval(player)(url, title);
|
||||
};
|
||||
};
|
||||
|
||||
function play(url, title) {
|
||||
window.open(url);
|
||||
}
|
||||
|
||||
function vlc_play(url, title) {
|
||||
var html_code = replace_list(html.vlc_player, {
|
||||
"video_url": url
|
||||
});
|
||||
dialog.player(title, html_code);
|
||||
}
|
||||
|
||||
function flash_play(url, title) {
|
||||
var html_code = replace_list(html.flash_player, {
|
||||
"video_url": url
|
||||
});
|
||||
dialog.player(title, html_code);
|
||||
}
|
||||
|
||||
function html_play(url, title) {
|
||||
var html_code = replace_list(html.html_player, {
|
||||
"video_url": url
|
||||
});
|
||||
dialog.player(title, html_code);
|
||||
}
|
||||
|
||||
function set_category(category) {
|
||||
var el = document.getElementById("header");
|
||||
if (category) {
|
||||
el.getElementById("heading").innerHTML = "alfa / " + category;
|
||||
document.title = "alfa / " + category;
|
||||
}
|
||||
else {
|
||||
el.getElementById("heading").innerHTML = "alfa";
|
||||
document.title = "alfa";
|
||||
};
|
||||
};
|
||||
|
||||
function focus_element(element) {
|
||||
element.focus()
|
||||
};
|
||||
|
||||
function image_error(thumbnail) {
|
||||
var src = thumbnail.src;
|
||||
if (thumbnail.src.indexOf(domain) == 0) {
|
||||
thumbnail.src = "http://media.tvalacarta.info/pelisalacarta/thumb_folder2.png";
|
||||
}
|
||||
else {
|
||||
thumbnail.src = domain + "/proxy/" + encodeURIComponent(btoa(thumbnail.src));
|
||||
}
|
||||
if (thumbnail.parentNode == document.activeElement && document.activeElement.className != "item_menu"){
|
||||
document.activeElement.onfocus();
|
||||
};
|
||||
};
|
||||
|
||||
function show_images(){
|
||||
var container = document.getElementById("itemlist");
|
||||
var images = container.getElementsByTagName("img");
|
||||
var item_height = images[0].parentNode.parentNode.offsetHeight;
|
||||
|
||||
var first = Math.floor(container.scrollTop / item_height);
|
||||
var count = Math.ceil(container.offsetHeight / item_height + (container.scrollTop / item_height - first));
|
||||
|
||||
for (var x = first; x < first + count; x++){
|
||||
var image = images[x]
|
||||
if (image && !image.src){
|
||||
image.src = image.parentNode.getElementsByClassName("thumbnail")[1].innerHTML;
|
||||
if (image.parentNode == document.activeElement){
|
||||
document.activeElement.onfocus();
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
function load_info(item, viewmode) {
|
||||
var thumbnail = item.getElementsByClassName("thumbnail")[0];
|
||||
var fanart = item.getElementsByClassName("fanart")[0];
|
||||
var title = item.getElementsByClassName("label")[0];
|
||||
var plot = item.getElementsByClassName("plot")[0];
|
||||
var el = document.getElementById("media_info");
|
||||
|
||||
el.getElementById("media_poster").src = thumbnail.src;
|
||||
el.getElementById("media_plot").innerHTML = plot.innerHTML.replace(/\n/g, "<br>");
|
||||
el.getElementById("media_title").innerHTML = title.innerHTML;
|
||||
|
||||
if (fanart.innerHTML && settings.show_fanart) {
|
||||
document.getElementById("content").style.backgroundImage = "linear-gradient(rgba(255,255,255,0.5),rgba(255,255,255,0.5)), url(" + fanart.innerHTML + ")";
|
||||
document.getElementById("content").children[0].style.opacity = ".9";
|
||||
document.getElementById("content").children[1].style.opacity = ".9";
|
||||
}
|
||||
else {
|
||||
document.getElementById("content").style.backgroundImage = "";
|
||||
document.getElementById("content").children[0].style.opacity = "";
|
||||
document.getElementById("content").children[1].style.opacity = "";
|
||||
};
|
||||
|
||||
if (viewmode == "list") {
|
||||
el.getElementById("media_poster").style.display = "block";
|
||||
el.getElementById("media_plot").style.display = "block";
|
||||
el.getElementById("media_title").style.display = "none";
|
||||
document.getElementById("version_info").style.display = "none";
|
||||
}
|
||||
else if (viewmode == "banner" || viewmode == "channel") {
|
||||
el.getElementById("media_poster").style.display = "none";
|
||||
el.getElementById("media_plot").style.display = "none";
|
||||
el.getElementById("media_title").style.display = "none";
|
||||
document.getElementById("version_info").style.display = "block";
|
||||
}
|
||||
else {
|
||||
el.getElementById("media_poster").style.display = "block";
|
||||
el.getElementById("media_plot").style.display = "block";
|
||||
el.getElementById("media_title").style.display = "block";
|
||||
document.getElementById("version_info").style.display = "none";
|
||||
}
|
||||
auto_scroll(el.getElementById("media_plot"));
|
||||
};
|
||||
|
||||
function unload_info(obj) {
|
||||
var el = document.getElementById('media_info');
|
||||
document.getElementById("version_info").style.display = "block";
|
||||
el.getElementById("media_poster").style.display = "none";
|
||||
el.getElementById("media_plot").style.display = "none";
|
||||
el.getElementById("media_title").style.display = "none";
|
||||
el.getElementById("media_poster").src = "";
|
||||
el.getElementById("media_plot").innerHTML = "";
|
||||
el.getElementById("media_title").innerHTML = "";
|
||||
document.getElementById("content").style.backgroundImage = ""
|
||||
document.getElementById("content").children[0].style.opacity = "";
|
||||
document.getElementById("content").children[1].style.opacity = "";
|
||||
};
|
||||
|
||||
function change_category(category) {
|
||||
var el = document.getElementById('window_settings');
|
||||
el.getElementById("controls_container").scrollTop = 0;
|
||||
categories = el.getElementById("controls_container").getElementsByTagName("ul");
|
||||
for (var x in categories) {
|
||||
if (categories[x].id == "category_" + category) {
|
||||
categories[x].style.display = "block";
|
||||
}
|
||||
else if (categories[x].style) {
|
||||
categories[x].style.display = "none";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
function auto_scroll(element) {
|
||||
clearInterval(element.interval);
|
||||
element.scrollLeft = 0;
|
||||
element.scrollTop = 0;
|
||||
if (element.scrollWidth > element.offsetWidth) {
|
||||
initialscrollWidth = element.scrollWidth;
|
||||
element.innerHTML = element.innerHTML + " | " + element.innerHTML;
|
||||
element.interval = setInterval(function () {
|
||||
element.scrollLeft += 1;
|
||||
if (element.scrollLeft - 1 >= element.scrollWidth - initialscrollWidth) {
|
||||
element.scrollLeft = 0;
|
||||
};
|
||||
}, 80);
|
||||
};
|
||||
if (element.scrollHeight > element.offsetHeight) {
|
||||
initialscrollHeight = element.scrollHeight;
|
||||
element.innerHTML = element.innerHTML + "</br>" + element.innerHTML;
|
||||
element.interval = setInterval(function () {
|
||||
element.scrollTop += 1;
|
||||
if (element.scrollTop >= element.scrollHeight - initialscrollHeight) {
|
||||
element.scrollTop = 0;
|
||||
};
|
||||
}, 80);
|
||||
};
|
||||
};
|
||||
|
||||
function center_window(el) {
|
||||
el.style.top = document.getElementById("window").offsetHeight / 2 - el.offsetHeight / 2 + "px";
|
||||
};
|
||||
43
mediaserver/platformcode/template/js/utils.js
Normal file
43
mediaserver/platformcode/template/js/utils.js
Normal file
@@ -0,0 +1,43 @@
|
||||
var Utf8 = { // public method for url encoding
|
||||
encode: function(string) {
|
||||
string = string.replace(/\r\n/g, "\n");
|
||||
var utftext = "";
|
||||
for (var n = 0; n < string.length; n++) {
|
||||
var c = string.charCodeAt(n);
|
||||
if (c < 128) {
|
||||
utftext += String.fromCharCode(c);
|
||||
} else if ((c > 127) && (c < 2048)) {
|
||||
utftext += String.fromCharCode((c >> 6) | 192);
|
||||
utftext += String.fromCharCode((c & 63) | 128);
|
||||
} else {
|
||||
utftext += String.fromCharCode((c >> 12) | 224);
|
||||
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
|
||||
utftext += String.fromCharCode((c & 63) | 128);
|
||||
}
|
||||
}
|
||||
|
||||
return utftext;
|
||||
}, // public method for url decoding
|
||||
decode: function(utftext) {
|
||||
var string = "";
|
||||
var i = 0;
|
||||
var c = c1 = c2 = 0;
|
||||
while (i < utftext.length) {
|
||||
c = utftext.charCodeAt(i);
|
||||
if (c < 128) {
|
||||
string += String.fromCharCode(c);
|
||||
i++;
|
||||
} else if ((c > 191) && (c < 224)) {
|
||||
c2 = utftext.charCodeAt(i + 1);
|
||||
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
|
||||
i += 2;
|
||||
} else {
|
||||
c2 = utftext.charCodeAt(i + 1);
|
||||
c3 = utftext.charCodeAt(i + 2);
|
||||
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
|
||||
i += 3;
|
||||
}
|
||||
}
|
||||
return string;
|
||||
}
|
||||
};
|
||||
139
mediaserver/platformcode/template/js/vars.js
Normal file
139
mediaserver/platformcode/template/js/vars.js
Normal file
@@ -0,0 +1,139 @@
|
||||
var domain = window.location.href.split("/").slice(0, 3).join("/");
|
||||
var focused_item = null;
|
||||
var websocket = null;
|
||||
var session_id = null;
|
||||
var default_settings = {};
|
||||
var settings_controls = [];
|
||||
var connection_retry = true;
|
||||
var settings = {};
|
||||
var loading = {};
|
||||
var dialog = {};
|
||||
var ajax_running = [];
|
||||
var keychar = {
|
||||
"keyCode": 0,
|
||||
"Time": 0,
|
||||
"Char": ""
|
||||
};
|
||||
var html = {
|
||||
"dialog": {
|
||||
"select": {}
|
||||
},
|
||||
"config": {},
|
||||
"itemlist": {}
|
||||
};
|
||||
var players = {
|
||||
"play": "Abrir enlace",
|
||||
"vlc_play": "Plugin VLC",
|
||||
"flash_play": "Reproductor Flash",
|
||||
"html_play": "Video HTML"
|
||||
};
|
||||
var nav_history = {
|
||||
"newRequest": function (url) {
|
||||
if (this.confirmed) {
|
||||
if (this.states[this.current].url == url) {
|
||||
this.states[this.current].url;
|
||||
this.states[this.current].start;
|
||||
}
|
||||
else {
|
||||
this.states[this.current].scroll = document.getElementById("itemlist").scrollTop;
|
||||
this.states[this.current].focus = Array.prototype.indexOf.call(document.getElementById("itemlist").children, focused_item.parentNode);
|
||||
this.current += 1;
|
||||
this.states.splice(this.current, 0, {
|
||||
"start": new Date().getTime(),
|
||||
"url": url
|
||||
});
|
||||
this.confirmed = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.current == -1) {
|
||||
this.current = 0;
|
||||
this.states.push({
|
||||
"start": new Date().getTime(),
|
||||
"url": url
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.states[this.current].start = new Date().getTime();
|
||||
this.states[this.current].url = url;
|
||||
}
|
||||
}
|
||||
},
|
||||
"newResponse": function (data, category) {
|
||||
if (!this.confirmed) {
|
||||
if (this.states[this.current].focus >= 0) {
|
||||
document.getElementById("itemlist").children[this.states[this.current].focus].children[0].focus();
|
||||
document.getElementById("itemlist").scrollTop = this.states[this.current].scroll;
|
||||
}
|
||||
this.states[this.current].end = new Date().getTime();
|
||||
this.states[this.current].data = data;
|
||||
this.states[this.current].category = category;
|
||||
this.confirmed = true;
|
||||
if (settings.builtin_history && !this.from_nav) {
|
||||
if (this.current > 0) {
|
||||
history.pushState(this.current.toString(), "", "#" + this.states[this.current].url);
|
||||
}
|
||||
else {
|
||||
history.replaceState(this.current.toString(), "", "#" + this.states[this.current].url);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.states[this.current].focus >= 0) {
|
||||
document.getElementById("itemlist").children[this.states[this.current].focus].children[0].focus();
|
||||
document.getElementById("itemlist").scrollTop = this.states[this.current].scroll;
|
||||
}
|
||||
this.states[this.current].end = new Date().getTime();
|
||||
this.states[this.current].data = data;
|
||||
this.states[this.current].category = category;
|
||||
this.states = this.states.slice(0, this.current + 1);
|
||||
}
|
||||
this.from_nav = false;
|
||||
},
|
||||
|
||||
"go": function (index) {
|
||||
if (!this.confirmed) {
|
||||
this.current -= 1;
|
||||
this.confirmed = true;
|
||||
}
|
||||
this.states[this.current].scroll = document.getElementById("itemlist").scrollTop;
|
||||
this.states[this.current].focus = Array.prototype.indexOf.call(document.getElementById("itemlist").children, focused_item.parentNode);
|
||||
|
||||
if (this.current + index < 0) {
|
||||
this.current = -1;
|
||||
this.confirmed = false;
|
||||
send_request("");
|
||||
return;
|
||||
}
|
||||
|
||||
else if (this.current + index >= this.states.lenght) {
|
||||
this.current = this.states.lenght - 1;
|
||||
}
|
||||
else {
|
||||
this.current += index;
|
||||
}
|
||||
|
||||
if (this.states[this.current].end - this.states[this.current].start > this.cache) {
|
||||
document.getElementById("itemlist").innerHTML = this.states[this.current].data.join("");
|
||||
set_category(this.states[this.current].category)
|
||||
if (this.states[this.current].focus >= 0) {
|
||||
document.getElementById("itemlist").children[this.states[this.current].focus].children[0].focus();
|
||||
}
|
||||
if (this.states[this.current].scroll) {
|
||||
document.getElementById("itemlist").scrollTop = this.states[this.current].scroll;
|
||||
}
|
||||
show_images();
|
||||
this.confirmed = true;
|
||||
}
|
||||
else {
|
||||
this.confirmed = false;
|
||||
this.from_nav = true;
|
||||
send_request(this.states[this.current].url);
|
||||
}
|
||||
},
|
||||
"current": -1,
|
||||
"confirmed": false,
|
||||
"from_nav": false,
|
||||
"states": [],
|
||||
"cache": 2000 //Tiempo para determinar si se cargará la cache o se volvera a solicitar el item (el tiempo es el que tarda en responder el servidor)
|
||||
};
|
||||
15
mediaserver/platformcode/template/manifest.json
Normal file
15
mediaserver/platformcode/template/manifest.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "alfa",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/media/icon-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#00779F",
|
||||
"background_color": "#00779F",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"orientation": "any"
|
||||
}
|
||||
224
mediaserver/platformcode/template/page.html
Normal file
224
mediaserver/platformcode/template/page.html
Normal file
@@ -0,0 +1,224 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="shortcut icon" href="/media/favicon.ico" />
|
||||
|
||||
<!-- Web as app support -->
|
||||
<link rel="manifest" href="/media/manifest.json">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
|
||||
<!-- Navigation bar color -->
|
||||
<!-- Chrome, Firefox OS and Opera -->
|
||||
<meta name="theme-color" content="#01455c">
|
||||
<!-- Windows Phone -->
|
||||
<meta name="msapplication-navbutton-color" content="#01455c">
|
||||
<!-- iOS Safari -->
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="#01455c">
|
||||
|
||||
<title>alfa</title>
|
||||
|
||||
<link rel="stylesheet" href="/media/css/alfa.css" />
|
||||
<script type="text/javascript" src="/media/js/main.js"></script>
|
||||
<script type="text/javascript" src="/media/js/vars.js"></script>
|
||||
<script type="text/javascript" src="/media/js/ui.js"></script>
|
||||
<script type="text/javascript" src="/media/js/navigation.js"></script>
|
||||
<script type="text/javascript" src="/media/js/dialogs.js"></script>
|
||||
<script type="text/javascript" src="/media/js/protocol.js"></script>
|
||||
<script type="text/javascript" src="/media/js/socket.js"></script>
|
||||
<script type="text/javascript" src="/media/js/utils.js"></script>
|
||||
<script type="text/javascript">
|
||||
websocket_host = 'ws://' + window.location.hostname + ':{$WSPORT}'
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- loading -->
|
||||
<div class="window_loading" id="window_loading">
|
||||
<span class="loading_animation"></span>
|
||||
<a class="loading_message" id="loading_message" href="javascript:void(0)">Cargando...</a>
|
||||
</div>
|
||||
|
||||
<!--/window_progress -->
|
||||
<div class="window_background_progress" id="window_background_progress">
|
||||
<div Class="window_heading" id="window_heading"></div>
|
||||
<div Class="window_message" id="window_message"></div>
|
||||
<div Class="progressbar_background" id="progressbar_background">
|
||||
<div Class="progressbar" id="progressbar"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="window_overlay" id="window_overlay"></div>
|
||||
|
||||
<!-- window_select -->
|
||||
<div class="window_select" id="window_select">
|
||||
<a class="window_close" href="javascript:void(0)" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.RequestID, 'result':-1 });dialog.closeall();"></a>
|
||||
<div class="window_heading" id="window_heading"></div>
|
||||
<ul class="control_list" id="control_list"></ul>
|
||||
</div>
|
||||
|
||||
<!-- window_ok -->
|
||||
<div class="window_ok" id="window_ok">
|
||||
<a class="window_close" href="javascript:void(0)" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.RequestID, 'result':true });dialog.closeall();"></a>
|
||||
<div class="window_heading" id="window_heading"></div>
|
||||
<div Class="window_message" id="window_message"></div>
|
||||
<div class="window_footer" id="window_footer">
|
||||
<a href="javascript:void(0)" class="control_button button_ok" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result':true });dialog.closeall();">Aceptar</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- window_yesno -->
|
||||
<div class="window_yesno" id="window_yesno">
|
||||
<a class="window_close" href="javascript:void(0)" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.RequestID, 'result':false });dialog.closeall();"></a>
|
||||
<div class="window_heading" id="window_heading"></div>
|
||||
<div Class="window_message" id="window_message"></div>
|
||||
<div class="window_footer" id="window_footer">
|
||||
<a href="javascript:void(0)" class="control_button button_ok" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result':true });dialog.closeall();">Si</a>
|
||||
<a href="javascript:void(0)" class="control_button button_close" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result':false });dialog.closeall();">No</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- window_notification -->
|
||||
<div class="window_notification" id="window_notification">
|
||||
<div class="window_icon" id="window_icon"></div>
|
||||
<div Class="window_heading" id="window_heading"></div>
|
||||
<div Class="window_message" id="window_message"></div>
|
||||
</div>
|
||||
|
||||
<!--/window_progress -->
|
||||
<div class="window_progress" id="window_progress">
|
||||
<a class="window_close" href="javascript:void(0)" onmouseover="this.focus()" onclick="this.parentNode.querySelector('#canceled').checked='checked';this.parentNode.querySelector('#window_heading').innerHTML += ' Cancelando...';"></a>
|
||||
<div class="window_heading" id="window_heading"></div>
|
||||
<div Class="window_message" id="window_message"></div>
|
||||
<div Class="progress_background" id="progress_background">
|
||||
<div Class="progress" id="progress"></div>
|
||||
</div>
|
||||
<div class="window_footer" id="window_footer">
|
||||
<a href="javascript:void(0)" class="control_button button_close" onmouseover="this.focus()" onclick="this.parentNode.querySelector('#canceled').checked='checked';this.parentNode.parentNode.querySelector('#window_heading').innerHTML += ' Cancelando...';">Cancelar</a>
|
||||
<input type="checkbox" style="display:none" id="canceled">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- window_input -->
|
||||
<div class="window_input" id="window_input">
|
||||
<a class="window_close" href="javascript:void(0)" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.RequestID, 'result':null });dialog.closeall();"></a>
|
||||
<div class="window_heading" id="window_heading"></div>
|
||||
<div class="control_input" id="control_input">
|
||||
<input class="control_input" id="window_value" type="text" onkeypress="if(event.keyCode == 13){send_data({'id':this.parentNode.parentNode.RequestID, 'result':this.value });dialog.closeall();loading.show();}">
|
||||
<label class="control_input"></label>
|
||||
</div>
|
||||
<div class="window_footer" id="window_footer">
|
||||
<a href="javascript:void(0)" class="control_button button_ok" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result':this.parentNode.parentNode.getElementById('window_value').value});dialog.closeall();loading.show();">Aceptar</a>
|
||||
<a href="javascript:void(0)" class="control_button button_close" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result':null });dialog.closeall();">Cancelar</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- window_captcha -->
|
||||
<div class="window_recaptcha" id="window_recaptcha">
|
||||
<a class="window_close" href="javascript:void(0)" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.RequestID, 'result':null });dialog.closeall();"></a>
|
||||
<div class="window_heading" id="window_heading"></div>
|
||||
<div Class="window_message" id="window_message"></div>
|
||||
<div class="window_image" id= "window_image">
|
||||
<a href="javascript:void(0)" onmouseover="this.focus()" onmouseout="this.blur()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result': 0})"></a>
|
||||
<a href="javascript:void(0)" onmouseover="this.focus()" onmouseout="this.blur()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result': 1})"></a>
|
||||
<a href="javascript:void(0)" onmouseover="this.focus()" onmouseout="this.blur()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result': 2})"></a>
|
||||
<a href="javascript:void(0)" onmouseover="this.focus()" onmouseout="this.blur()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result': 3})"></a>
|
||||
<a href="javascript:void(0)" onmouseover="this.focus()" onmouseout="this.blur()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result': 4})"></a>
|
||||
<a href="javascript:void(0)" onmouseover="this.focus()" onmouseout="this.blur()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result': 5})"></a>
|
||||
<a href="javascript:void(0)" onmouseover="this.focus()" onmouseout="this.blur()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result': 6})"></a>
|
||||
<a href="javascript:void(0)" onmouseover="this.focus()" onmouseout="this.blur()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result': 7})"></a>
|
||||
<a href="javascript:void(0)" onmouseover="this.focus()" onmouseout="this.blur()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result': 8})"></a>
|
||||
</div>
|
||||
<div class="window_footer" id="window_footer">
|
||||
<a href="javascript:void(0)" class="control_button button_ok" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result':true});dialog.closeall();loading.show();">Aceptar</a>
|
||||
<a href="javascript:void(0)" class="control_button button_close" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result':null });dialog.closeall();">Cancelar</a>
|
||||
<a href="javascript:void(0)" class="control_button button_ok" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result':'refresh'});dialog.closeall();loading.show();">Recargar</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--/window_settings -->
|
||||
<div id="window_settings" class="window_settings">
|
||||
<a class="window_close" href="javascript:void(0)" onmouseover="this.focus()" onclick="dialog.closeall();if(this.parentNode.getElementById('window_footer').style.display != 'none'){save_config(false)}"></a>
|
||||
<div class="window_heading" id="window_heading"></div>
|
||||
<div class="category_container" id="category_container"></div>
|
||||
<div class="controls_container" id="controls_container"></div>
|
||||
<div class="window_footer" id="window_footer_local" style="display:none">
|
||||
<a href="javascript:void(0)" class="control_button button_ok" onmouseover="this.focus()" onclick="save_settings();dialog.closeall()">Guardar</a>
|
||||
<a href="javascript:void(0)" class="control_button button_close" onmouseover="this.focus()" onclick="dialog.closeall()">Cerrar</a>
|
||||
</div>
|
||||
<div class="window_footer" id="window_footer">
|
||||
<a href="javascript:void(0)" class="control_button button_ok" onmouseover="this.focus()" onclick="dialog.closeall();save_config(true);">Guardar</a>
|
||||
<a href="javascript:void(0)" class="control_button button_close" onmouseover="this.focus()" onclick="dialog.closeall();save_config(false);">Cerrar</a>
|
||||
<a href="javascript:void(0)" class="control_button" onmouseover="this.focus()" onclick="custom_button();" id="custom_button"></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--/window_info -->
|
||||
<div class="window_info" id="window_info">
|
||||
<a class="window_close" href="javascript:void(0)" onmouseover="this.focus()" onclick="dialog.closeall();info_window('close')"></a>
|
||||
<div class="window_heading" id="window_heading"></div>
|
||||
<div class="window_content">
|
||||
<img class="info_fanart" id="info_fanart">
|
||||
<img class="info_poster" id="info_poster">
|
||||
<span class="line1_head" id="line1_head"></span><span class="line1" id="line1"></span>
|
||||
<span class="line2_head" id="line2_head"></span><span class="line2" id="line2"></span>
|
||||
<span class="line3_head" id="line3_head"></span><span class="line3" id="line3"></span>
|
||||
<span class="line4_head" id="line4_head"></span><span class="line4" id="line4"></span>
|
||||
<span class="line5_head" id="line5_head"></span><span class="line5" id="line5"></span>
|
||||
<span class="line6_head" id="line6_head"></span><span class="line6" id="line6"></span>
|
||||
<span class="line7_head" id="line7_head"></span><span class="line7" id="line7"></span>
|
||||
<span class="line8_head" id="line8_head"></span><span class="line8" id="line8"></span>
|
||||
<span class="page_info" id="page_info"></span>
|
||||
</div>
|
||||
<div class="window_footer" id="window_footer">
|
||||
<a href="javascript:void(0)" class="control_button" id="previous" onmouseover="this.focus()" onclick="info_window('previous')">Anterior</a>
|
||||
<a href="javascript:void(0)" class="control_button" id="next" onmouseover="this.focus()" onclick="info_window('next')">Siguiente</a>
|
||||
<a href="javascript:void(0)" class="control_button button_close" onmouseover="this.focus()" onclick="dialog.closeall();info_window('close')">Cancelar</a>
|
||||
<a href="javascript:void(0)" class="control_button button_close" onmouseover="this.focus()" onclick="dialog.closeall();info_window('ok')">Aceptar</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- window_player -->
|
||||
<div class="window_player" id="window_player">
|
||||
<a class="window_close" href="javascript:void(0)" onmouseover="this.focus()" onclick="dialog.closeall()"></a>
|
||||
<div class="window_heading" id="window_heading"></div>
|
||||
<div id="media_content" class="media_content"></div>
|
||||
</div>
|
||||
|
||||
<div class="window" id="window">
|
||||
<div class="header" id="header">
|
||||
<div class="logo"></div>
|
||||
<h1 class="heading" id="heading">alfa</h1>
|
||||
<a class="settings" href="javascript:void(0)" onclick="dialog.settings()"></a>
|
||||
</div>
|
||||
<div class="content" id="content">
|
||||
<div class="panel_info" id="panel_info">
|
||||
<div class="media_info" id="media_info">
|
||||
<img id="media_poster" src="" />
|
||||
<h3 id="media_title"></h3>
|
||||
<div id="media_plot"></div>
|
||||
</div>
|
||||
<div class="version_info" id="version_info">
|
||||
<span class="Version" id="version"></span><br/>
|
||||
<span class="Version" id="date"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel_items" id="panel_items">
|
||||
<ul class="itemlist" id="itemlist" onscroll="show_images()">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer" id="footer">
|
||||
<div class="left">
|
||||
</div>
|
||||
<div class="links">
|
||||
<a href="#">Saber más sobre Alfa</a> | <a href="#">Foro</a>
|
||||
</div>
|
||||
<div class="status" id="status">Desconectado</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user