def start(self, list_controls=None, dict_values=None, title="Opciones", callback=None, item=None, custom_button=None, channelpath=None): logger.info("[xbmc_config_menu] start") # Ruta para las imagenes de la ventana self.mediapath = os.path.join(config.get_runtime_path(), 'resources', 'skins', 'Default', 'media') # Capturamos los parametros self.list_controls = list_controls self.values = dict_values self.title = title self.callback = callback self.item = item if type(custom_button) == dict: self.custom_button = {} self.custom_button["label"] = custom_button.get("label", "") self.custom_button["function"] = custom_button.get("function", "") self.custom_button["visible"] = bool(custom_button.get("visible", True)) self.custom_button["close"] = bool(custom_button.get("close", False)) else: self.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 self.channel = os.path.basename(channelpath).replace(".py", "") # Si no tenemos list_controls, hay que sacarlos del xml del canal if not self.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 self.list_controls, default_values = channeltools.get_channel_controls_settings(self.channel) # En caso contrario salimos else: return None # Si no se pasan dict_values, creamos un dict en blanco if self.values is None: self.values = {} # Ponemos el titulo if self.title == "": self.title = str(config.get_localized_string(30100)) + " -- " + self.channel.capitalize() elif self.title.startswith('@') and unicode(self.title[1:]).isnumeric(): self.title = config.get_localized_string(int(self.title[1:])) # Muestra la ventana self.return_value = None self.doModal() return self.return_value
def show_channel_settings(list_controls=None, dict_values=None, caption="", callback=None, item=None, custom_button=None, channelpath=None): """ Muestra un cuadro de configuracion personalizado para cada canal y guarda los datos al cerrarlo. Parametros: ver descripcion en xbmc_config_menu.SettingsWindow @param list_controls: lista de elementos a mostrar en la ventana. @type list_controls: list @param dict_values: valores que tienen la lista de elementos. @type dict_values: dict @param caption: titulo de la ventana @type caption: str @param callback: función que se llama tras cerrarse la ventana. @type callback: str @param item: item para el que se muestra la ventana de configuración. @type item: Item @param custom_button: botón personalizado, que se muestra junto a "OK" y "Cancelar". @type custom_button: dict @return: devuelve la ventana con los elementos @rtype: SettingsWindow """ from xbmc_config_menu import SettingsWindow return SettingsWindow("ChannelSettings.xml", config.get_runtime_path()) \ .start(list_controls=list_controls, dict_values=dict_values, title=caption, callback=callback, item=item, custom_button=custom_button, channelpath=channelpath)
def get_servers_list(): logger.info("from resources.lib.httpkir.servertools get_servers_list") ServersPath = os.path.join(config.get_runtime_path(),"servers") ServerList={} for server in os.listdir(ServersPath): if server.endswith(".xml"): if is_server_enabled(server): server_parameters = get_server_parameters(server) ServerList[server_parameters["id"]] = server_parameters return ServerList
def onInit(self): try: self.getControl(401).addLabel( "Presiona la tecla a usar para abrir la ventana") self.getControl(402).addLabel("Tienes %s segundos" % self.TIMEOUT) except AttributeError: self.getControl(401).setLabel( "Presiona la tecla a usar para abrir la ventana") self.getControl(402).setLabel("Tienes %s segundos" % self.TIMEOUT) self.getControl(400).setImage( filetools.join(config.get_runtime_path(), "resources", "images", "matchcenter", "matchcenter.png"))
def get_server_parameters(server): server=scrapertools.find_single_match(server,'([^\.]+)') try: JSONFile = xml2dict(os.path.join(config.get_runtime_path(),"servers", server + ".xml"))["server"] if type(JSONFile["premium"]) == dict: JSONFile["premium"]=JSONFile["premium"]["value"] if JSONFile["premium"] == "": JSONFile["premium"]=[] if type(JSONFile["premium"]) == str and not JSONFile["premium"] == "": JSONFile["premium"]=[JSONFile["premium"]] return JSONFile except: logger.info("Error al cargar el servidor: " + server) import traceback logger.info(traceback.format_exc()) return {}
def start(): tecla_guardada = config.get_setting("keymap_edit", "editor_keymap") nuevakey = KeyListener().record_key() if nuevakey and tecla_guardada != nuevakey: from resources.lib.httpkir import filetools from platformcode import platformtools import xbmc file_xml = "special://profile/keymaps/deportesalacarta.xml" data = '<keymap><global><keyboard><key id="%s">' % nuevakey + 'runplugin(plugin://' \ 'plugin.video.dss/?ewogICAgImFjdGlvbiI6ICJzdGFydCIsIAogICAgImNoYW5uZWwiOiAibWF0Y2hjZ' \ 'W50ZXIiLCAKICAgICJpbmZvTGFiZWxzIjoge30KfQ%3D%3D))</key></keyboard></global></keymap>' filetools.write(xbmc.translatePath(file_xml), data) platformtools.dialog_notification( "Tecla guardada", "Reinicia Kodi para que se apliquen los cambios") from resources.lib.httpkir import scrapertools config.set_setting("keymap_edit", nuevakey, "editor_keymap") file_idioma = filetools.join(config.get_runtime_path(), 'resources', 'language', 'Spanish', 'strings.xml') data = filetools.read(file_idioma) value_xml = scrapertools.find_single_match( data, '<string id="31100">([^<]+)<') if "tecla" in value_xml: data = data.replace( value_xml, 'Cambiar tecla/botón para abrir la ventana (Guardada: %s)' % nuevakey) elif "key" in value_xml: data = data.replace( value_xml, 'Change key/button to open the window (Saved: %s)' % nuevakey) else: data = data.replace( value_xml, 'Cambiamento di chiave/pulsante per aprire la finestra (Salvato: %s)' % nuevakey) filetools.write(file_idioma, data) return
def download_file_megacrypter(self): logger.info("DownloadThread.download_file Megacrypter downloader") comando = "./megacrypter.sh" logger.info("DownloadThread.download_file comando="+comando) oldcwd = os.getcwd() logger.info("DownloadThread.download_file oldcwd="+oldcwd) cwd = os.path.join( config.get_runtime_path() , "tools") logger.info("DownloadThread.download_file cwd="+cwd) os.chdir(cwd) logger.info("DownloadThread.download_file directory changed to="+os.getcwd()) logger.info("DownloadThread.download_file destino="+self.download_path) os.system( comando+" '"+self.url+ "' \"" + self.download_path+"\"" ) #p = subprocess.Popen([comando , self.url , self.download_path], cwd=cwd, stdout=subprocess.PIPE , stderr=subprocess.PIPE ) #out, err = p.communicate() #logger.info("DownloadThread.download_file out="+out) os.chdir(oldcwd)
def run(): logger.info("dss.platformcode.launcher run") # Extract item from sys.argv if sys.argv[2]: item = Item().fromurl(sys.argv[2]) # If no item, this is mainlist else: item = Item(channel="channelselector", action="getmainlist", viewmode="movie") if item.action != "actualiza": logger.info("dss.platformcode.launcher " + item.tostring()) try: if item.action == "editor_keymap": from platformcode import editor_keymap return editor_keymap.start() # If item has no action, stops here if item.action == "": logger.info("dss.platformcode.launcher Item sin accion") return # Action for main menu in channelselector if item.action == "getmainlist": import channelselector itemlist = channelselector.getmainlist() # Check for updates only on first screen if config.get_setting("updatecheck") == "true": logger.info("Check for plugin updates enabled") from core import updater try: update, version_publicada, message, url_repo, serv = updater.check( ) if update: new_item = Item( title="Descargar versión " + version_publicada, channel="updater", action="actualiza", thumbnail=channelselector.get_thumbnail_path() + "Crystal_Clear_action_info.png", version=version_publicada, url=url_repo, server=serv) if config.get_setting("updateauto") == "true": updater.actualiza(new_item) new_item = Item( title= "Info para ver los cambios en la nueva versión instalada", plot=message, action="", channel="", thumbnail=channelselector.get_thumbnail_path() + "Crystal_Clear_action_info.png", text_color="red") itemlist.insert(0, new_item) else: platformtools.dialog_ok( "Versión " + version_publicada + " disponible", message) itemlist.insert(0, new_item) except: import traceback logger.info(traceback.format_exc()) logger.info( "dss.platformcode.launcher Fallo al verificar la actualización" ) else: logger.info( "dss.platformcode.launcher Check for plugin updates disabled" ) if not config.get_setting("primer_uso_matchcenter"): config.set_setting("primer_uso_matchcenter", "true") platformtools.dialog_ok( "MatchCenter activado", "Reinicia Kodi para usarlo (pulsar tecla U)", "La tecla, botones y otras opciones pueden cambiarse en Configuración -> Preferencias -> MatchCenter" ) file_keyboard = xbmc.translatePath( "special://profile/keymaps/deportesalacarta.xml") if config.get_setting( "matchcenter_enabled" ) == "true" and not os.path.exists(file_keyboard): tecla = "61525" tecla_guardada = config.get_setting("keymap_edit", "editor_keymap") if tecla_guardada: tecla = tecla_guardada from core import filetools data = '<keymap><global><keyboard><key id="%s">' % tecla + 'runplugin(plugin://plugin.video.dss/?ewogICAgImFjdGlvbiI6ICJzdGFydCIsIAogICAgImNoYW5uZWwiOiAibWF0Y2hjZW50ZXIiLCAKICAgICJpbmZvTGFiZWxzIjoge30KfQ%3D%3D))</key></keyboard></global></keymap>' filetools.write(file_keyboard, data) elif config.get_setting( "matchcenter_enabled") == "false" and os.path.exists( file_keyboard): from core import filetools try: filetools.remove(file_keyboard) except: pass platformtools.render_items(itemlist, item) # Action for updating plugin elif item.action == "actualiza": from core import updater updater.actualiza(item) xbmc.executebuiltin("Container.Refresh") # Action for channel listing on channelselector elif item.action == "filterchannels": import channelselector itemlist = channelselector.filterchannels(item.channel_type) platformtools.render_items(itemlist, item) # Action in certain channel specified in "action" and "channel" parameters else: can_open_channel = True # Checks if channel exists channel_file = os.path.join(config.get_runtime_path(), 'channels', item.channel + ".py") logger.info("dss.platformcode.launcher channel_file=%s" % channel_file) channel = None if os.path.exists(channel_file): try: channel = __import__('channels.%s' % item.channel, None, None, ["channels.%s" % item.channel]) except ImportError: exec "import channels." + item.channel + " as channel" logger.info( "deportesalacarta.platformcode.launcher running channel " + channel.__name__ + " " + channel.__file__) # Special play action if item.action == "play": logger.info("dss.platformcode.launcher play") # logger.debug("item_toPlay: " + "\n" + item.tostring('\n')) # First checks if channel has a "play" function if hasattr(channel, 'play'): logger.info( "dss.platformcode.launcher executing channel 'play' method" ) itemlist = channel.play(item) b_favourite = item.isFavourite # Play should return a list of playable URLS if len(itemlist) > 0 and isinstance(itemlist[0], Item): item = itemlist[0] if b_favourite: item.isFavourite = True platformtools.play_video(item) #Permitir varias calidades desde play en el canal elif len(itemlist) > 0 and isinstance(itemlist[0], list): item.video_urls = itemlist platformtools.play_video(item) # If not, shows user an error message else: platformtools.dialog_ok("plugin", "There is nothing to play") # If player don't have a "play" function, not uses the standard play from platformtools else: logger.info( "dss.platformcode.launcher executing core 'play' method" ) platformtools.play_video(item) # Special action for findvideos, where the plugin looks for known urls elif item.action == "findvideos": # First checks if channel has a "findvideos" function if hasattr(channel, 'findvideos'): itemlist = getattr(channel, item.action)(item) # If not, uses the generic findvideos function else: logger.info( "dss.platformcode.launcher no channel 'findvideos' method, " "executing core method") from core import servertools itemlist = servertools.find_video_items(item) platformtools.render_items(itemlist, item) # Special action for searching, first asks for the words then call the "search" function elif item.action == "search": logger.info("dss.platformcode.launcher search") tecleado = platformtools.dialog_input("") if tecleado is not None: tecleado = tecleado.replace(" ", "+") # TODO revisar 'personal.py' porque no tiene función search y daría problemas itemlist = channel.search(item, tecleado) else: itemlist = [] platformtools.render_items(itemlist, item) # For all other actions else: logger.info("dss.platformcode.launcher executing channel '" + item.action + "' method") itemlist = getattr(channel, item.action)(item) platformtools.render_items(itemlist, item) except urllib2.URLError, e: import traceback logger.error("dss.platformcode.launcher " + traceback.format_exc()) # Grab inner and third party errors if hasattr(e, 'reason'): logger.info("dss.platformcode.launcher Razon del error, codigo: " + str(e.reason[0]) + ", Razon: " + str(e.reason[1])) texto = config.get_localized_string( 30050) # "No se puede conectar con el sitio web" platformtools.dialog_ok("plugin", texto) # Grab server response errors elif hasattr(e, 'code'): logger.info("dss.platformcode.launcher codigo de error HTTP : %d" % e.code) # "El sitio web no funciona correctamente (error http %d)" platformtools.dialog_ok( "plugin", config.get_localized_string(30051) % e.code)
platformtools.dialog_ok("plugin", texto) # Grab server response errors elif hasattr(e, 'code'): logger.info("dss.platformcode.launcher codigo de error HTTP : %d" % e.code) # "El sitio web no funciona correctamente (error http %d)" platformtools.dialog_ok( "plugin", config.get_localized_string(30051) % e.code) except: import traceback logger.error("dss.platformcode.launcher " + traceback.format_exc()) patron = 'File "' + os.path.join(config.get_runtime_path(), "channels", "").replace("\\", "\\\\") + '([^.]+)\.py"' canal = scrapertools.find_single_match(traceback.format_exc(), patron) try: xbmc_version = int( xbmc.getInfoLabel("System.BuildVersion").split(".", 1)[0]) if xbmc_version > 13: log_name = "kodi.log" else: log_name = "xbmc.log" log_message = "Ruta: " + xbmc.translatePath( "special://logpath") + log_name except: log_message = ""
def render_items(itemlist, parent_item): """ Función encargada de mostrar el itemlist en kodi, 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: if config.get_platform() == "boxee": xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=True) return # Si no hay ningun item, mostramos un aviso if not len(itemlist): itemlist.append(Item(title="There are no items to show")) # Recorremos el itemlist for item in itemlist: # 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 # Formatear titulo if item.text_color: item.title = '[COLOR %s]%s[/COLOR]' % (item.text_color, item.title) if item.text_blod: item.title = '[B]%s[/B]' % item.title if item.text_italic: item.title = '[I]%s[/I]' % item.title # IconImage para folder y video if item.folder: icon_image = "DefaultFolder.png" else: icon_image = "DefaultVideo.png" # Creamos el listitem listitem = xbmcgui.ListItem(item.title, iconImage=icon_image, thumbnailImage=item.thumbnail) # Ponemos el fanart if item.fanart: listitem.setProperty('fanart_image', item.fanart) else: listitem.setProperty( 'fanart_image', os.path.join(config.get_runtime_path(), "fanart.jpg")) # TODO: ¿Se puede eliminar esta linea? yo no he visto que haga ningun efecto. xbmcplugin.setPluginFanart( int(sys.argv[1]), os.path.join(config.get_runtime_path(), "fanart.jpg")) # Añadimos los infoLabels set_infolabels(listitem, item) # Montamos el menu contextual context_commands = set_context_commands(item, parent_item) # Añadimos el item if config.get_platform() == "boxee": xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url='%s?%s' % (sys.argv[0], item.tourl()), listitem=listitem, isFolder=item.folder) else: listitem.addContextMenuItems(context_commands, replaceItems=True) if not item.totalItems: item.totalItems = 0 xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url='%s?%s' % (sys.argv[0], item.tourl()), listitem=listitem, isFolder=item.folder, totalItems=item.totalItems) # Vista 5x3 hasta llegar al listado de canales if parent_item.channel not in ["channelselector", ""]: xbmcplugin.setContent(int(sys.argv[1]), "movies") # Fijamos el "breadcrumb" xbmcplugin.setPluginCategory(handle=int(sys.argv[1]), category=parent_item.category.capitalize()) # No ordenar items xbmcplugin.addSortMethod(handle=int(sys.argv[1]), sortMethod=xbmcplugin.SORT_METHOD_NONE) # Viewmodes: # Creo que es mas lógico que al item se le especifique que vista tendra al abrirlo. # El cambio puede provocar que algun canal no muestre los items en la vista deseada, pero es mejor ir corrigiendolo # que arrastrar algo que no tiene sentido if config.get_setting("forceview") == "true": if parent_item.viewmode == "list": xbmc.executebuiltin("Container.SetViewMode(50)") elif parent_item.viewmode == "movie_with_plot": xbmc.executebuiltin("Container.SetViewMode(503)") elif parent_item.viewmode == "movie": xbmc.executebuiltin("Container.SetViewMode(500)") # Cerramos el directorio xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=True)