def set_skinshortcuts_property(self, setting="", window_header="", property_name=""): '''allows the user to make a setting for skinshortcuts using the special skinsettings dialogs''' cur_value = try_decode(xbmc.getInfoLabel( "$INFO[Container(211).ListItem.Property(%s)]" % property_name)) cur_value_label = try_decode(xbmc.getInfoLabel( "$INFO[Container(211).ListItem.Property(%s.name)]" % property_name)) if setting == "||IMAGE||": # select image label, value = self.select_image(setting, allow_multi=True, windowheader=windowheader) if setting: # use skin settings select dialog value, label = self.set_skin_setting( setting, window_header=window_header, sublevel="", cur_value_label=cur_value_label, skip_skin_string=True, cur_value=cur_value) else: # manually input string if not cur_value: cur_value = "None" value = try_decode(xbmcgui.Dialog().input(window_header, cur_value, type=xbmcgui.INPUT_ALPHANUM)) label = value if label: from .skinshortcuts import set_skinshortcuts_property set_skinshortcuts_property(property_name, value, label)
def selectview(self, content_type="other", current_view=None, display_none=False): '''reads skinfile with all views to present a dialog to choose from''' cur_view_select_id = None label = "" all_views = [] if display_none: listitem = xbmcgui.ListItem(label="None") listitem.setProperty("id", "None") all_views.append(listitem) # read the special skin views file if sys.version_info.major == 3: views_file = try_decode( xbmcvfs.translatePath('special://skin/extras/views.xml')) else: views_file = try_decode( xbmc.translatePath('special://skin/extras/views.xml')) if xbmcvfs.exists(views_file): doc = parse(views_file) listing = doc.documentElement.getElementsByTagName('view') itemcount = 0 for view in listing: label = xbmc.getLocalizedString( int(view.attributes['languageid'].nodeValue)) viewid = view.attributes['value'].nodeValue mediatypes = view.attributes['type'].nodeValue.lower().split( ",") if label.lower() == current_view.lower( ) or viewid == current_view: cur_view_select_id = itemcount if display_none: cur_view_select_id += 1 if (("all" in mediatypes or content_type.lower() in mediatypes) and (not "!" + content_type.lower() in mediatypes) and not getCondVisibility( "Skin.HasSetting(SkinHelper.view.Disabled.%s)" % viewid)): image = "special://skin/extras/viewthumbs/%s.jpg" % viewid listitem = xbmcgui.ListItem(label=label, iconImage=image) listitem.setProperty("viewid", viewid) listitem.setProperty("icon", image) all_views.append(listitem) itemcount += 1 dialog = DialogSelect("DialogSelect.xml", "", listing=all_views, windowtitle=self.addon.getLocalizedString(32012), richlayout=True) dialog.autofocus_id = cur_view_select_id dialog.doModal() result = dialog.result del dialog if result: viewid = result.getProperty("viewid") label = try_decode(result.getLabel()) return (viewid, label) else: return (None, None)
def save_skin_image(self, skinstring="", multi_image=False, header=""): '''let the user select an image and save it to addon_data for easy backup''' cur_value = try_decode(xbmc.getInfoLabel("Skin.String(%s)" % skinstring)) cur_value_org = try_decode(xbmc.getInfoLabel("Skin.String(%s.org)" % skinstring)) if not multi_image: # single image (allow copy to addon_data) value = try_decode(xbmcgui.Dialog().browse(2, header, 'files', '', True, True, cur_value_org)) if value: ext = value.split(".")[-1] newfile = ("special://profile/addon_data/%s/custom_images/%s.%s" % (xbmc.getSkinDir(), skinstring + time.strftime("%Y%m%d%H%M%S", time.gmtime()), ext)) if "special://profile/addon_data/%s/custom_images/" % xbmc.getSkinDir() in cur_value: xbmcvfs.delete(cur_value) xbmcvfs.copy(value, newfile) xbmc.executebuiltin("Skin.SetString(%s.org,%s)" % (try_encode(skinstring), try_encode(value))) value = newfile else: # multi image if not cur_value_org.startswith("$"): delim = "\\" if "\\" in cur_value_org else "/" curdir = cur_value_org.rsplit(delim, 1)[0] + delim else: curdir = "" value = try_decode(xbmcgui.Dialog().browse(0, self.addon.getLocalizedString(32005), 'files', '', True, True, curdir)) return value
def get_skinsettings(filters=None): '''get all active skin settings''' all_skinsettings = [] guisettings_path = 'special://profile/addon_data/%s/settings.xml' % xbmc.getSkinDir() if xbmcvfs.exists(guisettings_path): if sys.version_info.major == 3: doc = try_decode(parse(xbmcvfs.translatePath(guisettings_path))) else: doc = try_decode(parse(xbmc.translatePath(guisettings_path))) skinsettings = doc.documentElement.getElementsByTagName('setting') for skinsetting in skinsettings: settingname = skinsetting.attributes['id'].nodeValue settingtype = skinsetting.attributes['type'].nodeValue if sys.version_info.major < 3: if isinstance(settingname, unicode): settingname = settingname.encode("utf-8") # we must grab the actual values because the xml file only updates at restarts if settingtype == "bool": if "$INFO" not in settingname and xbmc.getCondVisibility("Skin.HasSetting(%s)" % settingname): settingvalue = "true" else: settingvalue = "false" else: settingvalue = xbmc.getInfoLabel("Skin.String(%s)" % settingname) if not filters: # no filter - just add all settings we can find all_skinsettings.append((settingtype, settingname, settingvalue)) else: # only select settings defined in our filters for filteritem in filters: if filteritem.lower() in settingname.lower(): all_skinsettings.append((settingtype, settingname, settingvalue)) return all_skinsettings
def get_folderandprefix(self): '''get the current folder and prefix''' cur_folder = "" cont_prefix = "" try: widget_container = try_decode( self.win.getProperty("SkinHelper.WidgetContainer")) if getCondVisibility( "Window.IsActive(movieinformation)|Window.IsActive(DialogPVRInfo.xml)|Window.IsActive(DialogMusicInfo.xml)|Window.IsActive(script-script.extendedinfo-DialogVideoInfo.xml)" ): cont_prefix = "" cur_folder = try_decode( xbmc.getInfoLabel( "$INFO[Window.Property(xmlfile)]$INFO[Container.FolderPath]" "$INFO[Container.NumItems]$INFO[Container.Content]")) elif widget_container: cont_prefix = "Container(%s)." % widget_container cur_folder = try_decode( xbmc.getInfoLabel( "widget-%s-$INFO[Container(%s).NumItems]-$INFO[Container(%s).ListItemAbsolute(1).Label]" % (widget_container, widget_container, widget_container))) else: cont_prefix = "" cur_folder = try_decode( xbmc.getInfoLabel( "$INFO[Window.Property(xmlfile)]$INFO[Container.FolderPath]$INFO[Container.NumItems]$INFO[Container.Content]" )) except Exception as exc: log_exception(__name__, exc) cur_folder = "" cont_prefix = "" return (cur_folder, cont_prefix)
def monitor_livetv(self): ''' for livetv we are not notified when the program changes so we have to monitor that ourself ''' if self.monitoring_stream: # another monitoring already in progress... return last_title = "" while not self.abortRequested() and getCondVisibility("Player.HasVideo"): self.monitoring_stream = True li_title = try_decode(xbmc.getInfoLabel("Player.Title")) if li_title and li_title != last_title: all_props = [] last_title = li_title self.reset_win_props() li_channel = try_decode(xbmc.getInfoLabel("VideoPlayer.ChannelName")) # pvr artwork if getCondVisibility("Skin.HasSetting(SkinHelper.EnablePVRThumbs)"): li_genre = try_decode(xbmc.getInfoLabel("VideoPlayer.Genre")) pvrart = self.metadatautils.get_pvr_artwork(li_title, li_channel, li_genre) if sys.version_info.major == 3: all_props = prepare_win_props(pvrart, "SkinHelper.Player.") else: all_props = prepare_win_props(pvrart, u"SkinHelper.Player.") # pvr channellogo channellogo = self.metadatautils.get_channellogo(li_channel) all_props.append(("SkinHelper.Player.ChannelLogo", channellogo)) all_props.append(("SkinHelper.Player.Art.ChannelLogo", channellogo)) if last_title == li_title: self.metadatautils.process_method_on_list(self.set_win_prop, all_props) # show infopanel if needed self.show_info_panel() self.waitForAbort(2) self.monitoring_stream = False
def get_skin_constants(): '''gets a list of all skin constants as set in the special xml file''' all_constants = {} all_variables = {} if sys.version_info.major == 3: addonpath = try_decode( xbmcvfs.translatePath( try_encode(os.path.join("special://skin/", 'addon.xml')))) else: addonpath = try_decode( xbmc.translatePath( try_encode(os.path.join("special://skin/", 'addon.xml')))) addon = xmltree.parse(addonpath) extensionpoints = addon.findall("extension") for extensionpoint in extensionpoints: if extensionpoint.attrib.get("point") == "xbmc.gui.skin": resolutions = extensionpoint.findall("res") for resolution in resolutions: if sys.version_info.major == 3: includes_file = try_decode( xbmcvfs.translatePath( try_encode( os.path.join( "special://skin/", try_decode( resolution.attrib.get("folder")), "script-skin_helper_service-includes.xml" )))) else: includes_file = try_decode( xbmc.translatePath( try_encode( os.path.join( "special://skin/", try_decode( resolution.attrib.get("folder")), "script-skin_helper_service-includes.xml" )))) if xbmcvfs.exists(includes_file): doc = parse(includes_file) listing = doc.documentElement.getElementsByTagName( 'constant') # constants for item in listing: name = try_decode( item.attributes['name'].nodeValue) value = try_decode(item.firstChild.nodeValue) all_constants[name] = value # variables listing = doc.documentElement.getElementsByTagName( 'variable') for item in listing: name = try_decode( item.attributes['name'].nodeValue) value_item = item.getElementsByTagName('value')[0] value = try_decode(value_item.firstChild.nodeValue) all_variables[name] = value return all_constants, all_variables
def get_player_infolabels(self): '''collect basic infolabels for the current item in the videoplayer''' details = {"art": {}} # normal properties props = [ "title", "filenameandpath", "year", "genre", "duration", "plot", "plotoutline", "studio", "tvshowtitle", "premiered", "director", "writer", "season", "episode", "artist", "album", "rating", "albumartist", "discnumber", "firstaired", "mpaa", "tagline", "rating", "imdbnumber" ] for prop in props: propvalue = try_decode(xbmc.getInfoLabel('VideoPlayer.%s' % prop)) details[prop] = propvalue # art properties props = [ "fanart", "poster", "clearlogo", "clearart", "landscape", "characterart", "thumb", "banner", "discart", "tvshow.landscape", "tvshow.clearlogo", "tvshow.poster", "tvshow.fanart", "tvshow.banner" ] for prop in props: propvalue = try_decode(xbmc.getInfoLabel('Player.Art(%s)' % prop)) if propvalue: prop = prop.replace("tvshow.", "") propvalue = self.metadatautils.get_clean_image(propvalue) details["art"][prop] = propvalue return details
def __init__(self): self.win = xbmcgui.Window(10000) self.addon = xbmcaddon.Addon(ADDON_ID) self.metadatautils = MetadataUtils() self.addonname = try_decode(self.addon.getAddonInfo('name')) self.addonversion = try_decode(self.addon.getAddonInfo('version')) self.kodimonitor = KodiMonitor(metadatautils=self.metadatautils, win=self.win) self.listitem_monitor = ListItemMonitor( metadatautils=self.metadatautils, win=self.win, monitor=self.kodimonitor) self.webservice = WebService(self.metadatautils) self.win.clearProperty("SkinHelperShutdownRequested") # start the extra threads self.listitem_monitor.start() self.webservice.start() log_msg('%s version %s started' % (self.addonname, self.addonversion), xbmc.LOGINFO) # run as service, check skin every 10 seconds and keep the other threads alive while not self.kodimonitor.abortRequested(): # check skin version info self.check_skin_version() # sleep for 10 seconds self.kodimonitor.waitForAbort(10) # Abort was requested while waiting. We should exit self.close()
def get_backuppath(self): '''get the file location where backups should be stored''' backuppath = try_decode(self.addon.getSetting("backup_path")) if not backuppath: backuppath = try_decode(xbmcgui.Dialog().browse(3, self.addon.getLocalizedString(32002), 'files')) self.addon.setSetting("backup_path", try_encode(backuppath)) return backuppath
def get_restorefilename(self): '''browse for backup file''' backuppath = try_decode(self.addon.getSetting("backup_path")) filename = try_decode(xbmcgui.Dialog().browse( 1, self.addon.getLocalizedString(32008), 'files', '.zip', False, False, try_encode(backuppath))) filename = filename.replace( "//", "") # possible fix for strange path issue on atv/ftv ? return filename
def enableviews(self): '''show select dialog to enable/disable views''' all_views = [] if sys.version_info.major == 3: views_file = try_decode( xbmcvfs.translatePath('special://skin/extras/views.xml')) else: views_file = try_decode( xbmc.translatePath('special://skin/extras/views.xml')) richlayout = self.params.get("richlayout", "") == "true" if xbmcvfs.exists(views_file): doc = parse(views_file) listing = doc.documentElement.getElementsByTagName('view') for view in listing: view_id = view.attributes['value'].nodeValue label = xbmc.getLocalizedString( int(view.attributes['languageid'].nodeValue)) desc = label + " (" + str(view_id) + ")" image = "special://skin/extras/viewthumbs/%s.jpg" % view_id listitem = xbmcgui.ListItem(label=label, label2=desc, iconImage=image) listitem.setProperty("viewid", view_id) if not getCondVisibility( "Skin.HasSetting(SkinHelper.view.Disabled.%s)" % view_id): listitem.select(selected=True) excludefromdisable = False try: excludefromdisable = view.attributes[ 'excludefromdisable'].nodeValue == "true" except Exception: pass if not excludefromdisable: all_views.append(listitem) dialog = DialogSelect("DialogSelect.xml", "", listing=all_views, windowtitle=self.addon.getLocalizedString(32013), multiselect=True, richlayout=richlayout) dialog.doModal() result = dialog.result del dialog if result: for item in result: view_id = item.getProperty("viewid") if item.isSelected(): # view is enabled xbmc.executebuiltin( "Skin.Reset(SkinHelper.view.Disabled.%s)" % view_id) else: # view is disabled xbmc.executebuiltin( "Skin.SetBool(SkinHelper.view.Disabled.%s)" % view_id)
def correct_skin_settings(self): '''correct any special skin settings''' skinconstants = {} for settingid, settingvalues in list(self.skinsettings.items()): curvalue = try_decode(xbmc.getInfoLabel("Skin.String(%s)" % settingid)) curlabel = try_decode(xbmc.getInfoLabel("Skin.String(%s.label)" % settingid)) # first check if we have a sublevel if settingvalues and settingvalues[0]["value"].startswith("||SUBLEVEL||"): sublevel = settingvalues[0]["value"].replace("||SUBLEVEL||", "") settingvalues = self.skinsettings.get(sublevel) for settingvalue in settingvalues: value = settingvalue["value"] label = settingvalue["label"] if "%" in label: label = label % value # only correct the label if value already set if value and value == curvalue: xbmc.executebuiltin( "Skin.SetString(%s.label,%s)" % (try_encode(settingid), try_encode(label))) # set the default value if current value is empty if not (curvalue or curlabel): if settingvalue["default"] and getCondVisibility(settingvalue["default"]): xbmc.executebuiltin( "Skin.SetString(%s.label,%s)" % (try_encode(settingid), try_encode(label))) xbmc.executebuiltin( "Skin.SetString(%s,%s)" % (try_encode(settingid), try_encode(value))) # additional onselect actions for action in settingvalue["onselectactions"]: if action["condition"] and getCondVisibility(action["condition"]): command = action["command"] if "$" in command: command = xbmc.getInfoLabel(command) xbmc.executebuiltin(try_encode(command)) # process any multiselects for option in settingvalue["settingoptions"]: settingid = option["id"] if (not xbmc.getInfoLabel("Skin.String(defaultset_%s)" % settingid) and option["default"] and getCondVisibility(option["default"])): xbmc.executebuiltin("Skin.SetBool(%s)" % settingid) xbmc.executebuiltin("Skin.SetString(defaultset_%s,defaultset)" % settingid) # set the default constant value if current value is empty if (not curvalue and settingvalue["constantdefault"] and getCondVisibility(settingvalue["constantdefault"])): skinconstants[settingid] = value # update skin constants if needed only if skinconstants: self.update_skin_constants(skinconstants)
def backup(self, filters=None, backup_file="", silent=False): '''create skin backup''' if not filters: filters = [] if not backup_file: return # create temp path temp_path = self.create_temp() zip_temp = try_encode( '%sskinbackup-%s.zip' % (temp_path, datetime.now().strftime('%Y-%m-%d %H.%M'))) temp_path = temp_path + "skinbackup/" # backup skinshortcuts preferences if not filters or (filters and "skinshortcuts" in filters): self.backup_skinshortcuts(temp_path + "skinshortcuts/") # backup skin settings if "skinshortcutsonly" not in filters: skinsettings_path = os.path.join(temp_path, try_encode("guisettings.txt")) self.backup_skinsettings(skinsettings_path, filters, temp_path) # zip the backup if sys.version_info.major == 3: zip_temp = try_decode(xbmcvfs.translatePath(zip_temp)) else: zip_temp = try_decode(xbmc.translatePath(zip_temp)) zip_tofile(temp_path, zip_temp) # copy file to destination - wait until it's really copied xbmc.log("Skin Helper Backup --> Saving Backup to %s" % backup_file, level=xbmc.LOGINFO) copy_file(zip_temp, backup_file, True) if not xbmcvfs.exists(backup_file): if not silent: raise IOError('Failed to copy ' + zip_temp + " to " + backup_file) # cleanup temp recursive_delete_dir(temp_path) xbmcvfs.delete(zip_temp) # clean old backups self.clean_oldbackups() self.create_temp() # show success message if not silent: xbmcgui.Dialog().ok(self.addon.getLocalizedString(32004), self.addon.getLocalizedString(32005))
def backuprestore(self): '''show dialog with all options for skin backups''' listitems = [] # create backup option label = self.addon.getLocalizedString(32013) listitem = xbmcgui.ListItem(label=label) listitem.setArt({"icon": "DefaultFolder.png"}) listitem.setPath("backup") listitems.append(listitem) # list existing backups backuppath = self.get_backuppath() if backuppath: for backupfile in sorted(xbmcvfs.listdir(backuppath)[1], reverse=True): backupfile = try_decode(backupfile) if "Skinbackup" in backupfile and backupfile.endswith(".zip"): label = "%s: %s" % (self.addon.getLocalizedString(32015), backupfile[26:-5]) listitem = xbmcgui.ListItem(label=label) listitem.setArt({"icon": "DefaultFile.png"}) listitem.setPath(backuppath + backupfile) listitems.append(listitem) # show dialog and list options header = self.addon.getLocalizedString(32016) extrabutton = self.addon.getLocalizedString(32012) dialog = DialogSelect("DialogSelect.xml", "", windowtitle=header, extrabutton=extrabutton, richlayout=True, listing=listitems) dialog.doModal() result = dialog.result del dialog if result: if isinstance(result, bool): # show settings xbmc.executebuiltin("Addon.OpenSettings(%s)" % ADDON_ID) else: if result.getPath() == "backup": # create new backup self.backup(backup_file=self.get_backupfilename()) else: # restore backup self.restore(try_decode(result.getPath())) # always open the dialog again self.backuprestore()
def monitor_listitem(self): '''Monitor listitem details''' cur_folder, cont_prefix = self.get_folderandprefix() # identify current listitem - prefer parent folder (tvshows, music) cur_listitem = try_decode( xbmc.getInfoLabel( "$INFO[%sListItem.TvshowTitle]$INFO[%sListItem.Artist]$INFO[%sListItem.Album]" % (cont_prefix, cont_prefix, cont_prefix))) if not cur_listitem: # fallback to generic approach cur_listitem = try_decode( xbmc.getInfoLabel( "$INFO[%sListItem.Label]$INFO[%sListItem.DBID]$INFO[%sListItem.Title]" % (cont_prefix, cont_prefix, cont_prefix))) if self.exit: return # perform actions if the container path has changed if cur_folder != self.last_folder and not ( cur_listitem and cur_listitem == self.last_listitem): self.reset_win_props() self.get_settings() self.last_folder = cur_folder self.last_listitem = None content_type = self.get_content_type(cur_folder, cur_listitem, cont_prefix) # additional actions to perform when we have a valid contenttype and no widget container if not cont_prefix and content_type: self.set_forcedview(content_type) self.set_content_header(content_type) else: content_type = self.get_content_type(cur_folder, cur_listitem, cont_prefix) if self.exit: return # only perform actions when the listitem has actually changed if cur_listitem != self.last_listitem: self.last_listitem = cur_listitem self.win.setProperty("curlistitem", cur_listitem) if cur_listitem and cur_listitem != "..": # set listitem details in background thread thread.start_new_thread( self.set_listitem_details, (cur_listitem, content_type, cont_prefix))
def get_cur_listitem(cont_prefix): '''gets the current selected listitem details''' if getCondVisibility("Window.IsActive(busydialog)"): xbmc.executebuiltin("Dialog.Close(busydialog)") xbmc.sleep(500) dbid = try_decode(xbmc.getInfoLabel("%sListItem.DBID" % cont_prefix)) if not dbid or dbid == "-1": dbid = try_decode(xbmc.getInfoLabel("%sListItem.Property(DBID)" % cont_prefix)) if dbid == "-1": dbid = "" dbtype = try_decode(xbmc.getInfoLabel("%sListItem.DBTYPE" % cont_prefix)) if not dbtype: dbtype = try_decode(xbmc.getInfoLabel("%sListItem.Property(DBTYPE)" % cont_prefix)) if not dbtype: dbtype = get_current_content_type(cont_prefix) return (dbid, dbtype)
def set_video_properties(self, mediatype, li_dbid): '''sets the window props for a playing video item''' if not mediatype: mediatype = self.get_mediatype() details = self.get_player_infolabels() li_title = details["title"] li_year = details["year"] li_imdb = details["imdbnumber"] li_showtitle = details["tvshowtitle"] details = {"art": {}} # video content if mediatype in ["movie", "episode", "musicvideo"]: # get imdb_id li_imdb, li_tvdb = self.metadatautils.get_imdbtvdb_id( li_title, mediatype, li_year, li_imdb, li_showtitle) # generic video properties (studio, streamdetails, omdb, top250) details = self.metadatautils.extend_dict( details, self.metadatautils.get_omdb_info(li_imdb)) if li_dbid: details = self.metadatautils.extend_dict( details, self.metadatautils.get_streamdetails(li_dbid, mediatype)) details = self.metadatautils.extend_dict( details, self.metadatautils.get_top250_rating(li_imdb)) # tvshows-only properties (tvdb) if mediatype == "episode": details = self.metadatautils.extend_dict( details, self.metadatautils.get_tvdb_details(li_imdb, li_tvdb)) # movies-only properties (tmdb, animated art) if mediatype == "movie": details = self.metadatautils.extend_dict( details, self.metadatautils.get_tmdb_details(li_imdb)) if li_imdb and getCondVisibility( "Skin.HasSetting(SkinHelper.EnableAnimatedPosters)"): details = self.metadatautils.extend_dict( details, self.metadatautils.get_animated_artwork(li_imdb)) # extended art if getCondVisibility( "Skin.HasSetting(SkinHelper.EnableExtendedArt)"): tmdbid = details.get("tmdb_id", "") details = self.metadatautils.extend_dict( details, self.metadatautils.get_extended_artwork( li_imdb, li_tvdb, tmdbid, mediatype)) if li_title == try_decode(xbmc.getInfoLabel("Player.Title")): if sys.version_info.major == 3: all_props = prepare_win_props(details, "SkinHelper.Player.") else: all_props = prepare_win_props(details, u"SkinHelper.Player.") self.metadatautils.process_method_on_list(self.set_win_prop, all_props)
def backup_skinshortcuts(self, dest_path): '''backup skinshortcuts including images''' source_path = try_encode('special://profile/addon_data/script.skinshortcuts/') if not xbmcvfs.exists(dest_path): xbmcvfs.mkdir(dest_path) for file in xbmcvfs.listdir(source_path)[1]: file = try_decode(file) sourcefile = source_path + file destfile = dest_path + file if xbmc.getCondVisibility("SubString(Skin.String(skinshortcuts-sharedmenu),false)"): # User is not sharing menu, so strip the skin name out of the destination file destfile = destfile.replace("%s." % (xbmc.getSkinDir()), "") if (file.endswith(".DATA.xml") and (not xbmc.getCondVisibility( "SubString(Skin.String(skinshortcuts-sharedmenu),false)") or file.startswith(xbmc.getSkinDir()))): xbmcvfs.copy(sourcefile, destfile) # parse shortcuts file and look for any images - if found copy them to addon folder self.backup_skinshortcuts_images(destfile, dest_path) elif file.endswith(".properties") and xbmc.getSkinDir() in file: if xbmc.getSkinDir() in file: destfile = dest_path + file.replace(xbmc.getSkinDir(), "SKINPROPERTIES") copy_file(sourcefile, destfile) self.backup_skinshortcuts_properties(destfile, dest_path) else: # just copy the remaining files copy_file(sourcefile, destfile)
def __init__(self, e): if isinstance(e, str): try: e = xml.fromstring(e) except Exception: LOGGER.exception("Skipping malformed line") return if isinstance(e, xml.Element): e = etree_to_dict(e) if isinstance(e, dict): e = DictObject.objectify(e) assert isinstance(e, DictObject) assert hasattr(e.item, "type") self.type = ascii_integers_to_string(e.item.type) self.code = ascii_integers_to_string(e.item.code) self.length = int(e.item.length) if "data" in e.item: assert self.length > 0 # length is zero if data is undefined. self.data = encoded_to_str(e.item.data["#text"], e.item.data["@encoding"], as_bytes=True) if e.item.data["@encoding"] == "base64": self._data_base64 = try_decode(e.item.data["#text"]) else: self._data_base64 = None else: assert self.length == 0 # length is zero if data is undefined. self.data = try_encode("") self._data_base64 = None
def setview(self): '''sets the selected viewmode for the container''' xbmc.executebuiltin("ActivateWindow(busydialog)") content_type = get_current_content_type() if not content_type: content_type = "files" current_view = try_decode(xbmc.getInfoLabel("Container.Viewmode")) view_id, view_label = self.selectview(content_type, current_view) current_forced_view = xbmc.getInfoLabel( "Skin.String(SkinHelper.ForcedViews.%s)" % content_type) if view_id is not None: # also store forced view if (content_type and current_forced_view and current_forced_view != "None" and getCondVisibility( "Skin.HasSetting(SkinHelper.ForcedViews.Enabled)")): xbmc.executebuiltin( "Skin.SetString(SkinHelper.ForcedViews.%s,%s)" % (content_type, view_id)) xbmc.executebuiltin( "Skin.SetString(SkinHelper.ForcedViews.%s.label,%s)" % (content_type, view_label)) self.win.setProperty("SkinHelper.ForcedView", view_id) if not getCondVisibility( "Control.HasFocus(%s)" % current_forced_view): xbmc.sleep(100) xbmc.executebuiltin("Container.SetViewMode(%s)" % view_id) xbmc.executebuiltin("SetFocus(%s)" % view_id) else: self.win.clearProperty("SkinHelper.ForcedView") # set view xbmc.executebuiltin("Container.SetViewMode(%s)" % view_id)
def load_widget(self): '''legacy entrypoint called (widgets are moved to seperate addon), start redirect...''' action = self.params.get("action", "") newaddon = "script.skin.helper.widgets" log_msg( "Deprecated method: %s. Please reassign your widgets to get rid of this message. -" "This automatic redirect will be removed in the future" % (action), xbmc.LOGWARNING) paramstring = "" if sys.version_info.major == 3: for key, value in self.params.items(): paramstring += ",%s=%s" % (key, value) else: for key, value in self.params.iteritems(): paramstring += ",%s=%s" % (key, value) if getCondVisibility("System.HasAddon(%s)" % newaddon): # TEMP !!! for backwards compatability reasons only - to be removed in the near future!! import imp addon = xbmcaddon.Addon(newaddon) addon_path = try_decode(addon.getAddonInfo('path')) imp.load_source('plugin', os.path.join(addon_path, "plugin.py")) from plugin import main main.Main() del addon else: # trigger install of the addon if KODI_VERSION > 16: xbmc.executebuiltin("InstallAddon(%s)" % newaddon) else: xbmc.executebuiltin("RunPlugin(plugin://%s)" % newaddon)
def onNotification(self, sender, method, data): '''builtin function for the xbmc.Monitor class''' try: log_msg("Kodi_Monitor: sender %s - method: %s - data: %s" % (sender, method, data)) data = json.loads(try_decode(data)) mediatype = "" dbid = 0 transaction = False if data and isinstance(data, dict): if data.get("item"): mediatype = data["item"].get("type", "") dbid = data["item"].get("id", 0) elif data.get("type"): mediatype = data["type"] dbid = data.get("id", 0) if data.get("transaction"): transaction = True if method == "System.OnQuit": self.win.setProperty("SkinHelperShutdownRequested", "shutdown") if method == "VideoLibrary.OnUpdate": self.process_db_update(mediatype, dbid, transaction) if method == "AudioLibrary.OnUpdate": self.process_db_update(mediatype, dbid, transaction) if method == "Player.OnStop": self.monitoring_stream = False self.infopanelshown = False self.win.clearProperty("Skinhelper.PlayerPlaying") self.win.clearProperty("TrailerPlaying") self.reset_win_props() if method == "Player.OnPlay": if not self.monitoring_stream and not getCondVisibility( "Player.DisplayAfterSeek"): self.reset_win_props() if self.wait_for_player(): if getCondVisibility("Player.HasAudio"): if getCondVisibility("Player.IsInternetStream"): self.monitor_radiostream() else: self.set_music_properties() if getCondVisibility("Pvr.IsPlayingRadio"): if getCondVisibility("!Player.IsInternetStream"): self.monitor_radiostream() else: self.set_music_properties() elif getCondVisibility( "VideoPlayer.Content(livetv) | String.StartsWith(Player.FileNameAndPath,pvr://)" ): self.monitor_livetv() else: self.set_video_properties(mediatype, dbid) self.show_info_panel() except Exception as exc: log_exception(__name__, exc)
def setskinsetting(self): '''allows the user to set a skin setting with a select dialog''' setting = self.params.get("setting", "") org_id = self.params.get("id", "") if "$" in org_id: org_id = try_decode(xbmc.getInfoLabel(org_id)) header = self.params.get("header", "") SkinSettings().set_skin_setting(setting=setting, window_header=header, original_id=org_id)
def videosearch(self): '''show the special search dialog''' from resources.lib.searchdialog import SearchDialog search_dialog = SearchDialog( "script-skin_helper_service-CustomSearch.xml", try_decode(self.addon.getAddonInfo('path')), "Default", "1080i") search_dialog.doModal() del search_dialog
def write_skin_constants(self, constants=None, variables=None): '''writes the list of all skin constants''' if sys.version_info.major == 3: addonpath = try_decode( xbmcvfs.translatePath( try_encode(os.path.join("special://skin/", 'addon.xml')))) else: addonpath = try_decode( xbmc.translatePath( try_encode(os.path.join("special://skin/", 'addon.xml')))) addon = xmltree.parse(addonpath) extensionpoints = addon.findall("extension") for extensionpoint in extensionpoints: if extensionpoint.attrib.get("point") == "xbmc.gui.skin": resolutions = extensionpoint.findall("res") for resolution in resolutions: includes_file = xbmcvfs.translatePath( os.path.join( "special://skin/", try_decode(resolution.attrib.get("folder")), "script-skin_helper_service-includes.xml").encode( "utf-8")) tree = xmltree.ElementTree(xmltree.Element("includes")) root = tree.getroot() if constants: for key, value in list(constants.items()): if value: child = xmltree.SubElement(root, "constant") child.text = value child.attrib["name"] = key # also write to skin strings xbmc.executebuiltin("Skin.SetString(%s,%s)" % (key, value)) if variables: for key, value in list(variables.items()): if value: child = xmltree.SubElement(root, "variable") child.attrib["name"] = key child2 = xmltree.SubElement(child, "value") child2.text = value self.indent_xml(tree.getroot()) xmlstring = xmltree.tostring(tree.getroot()) fileobj = xbmcvfs.File(includes_file, 'w') fileobj.write(xmlstring) fileobj.close() xbmc.executebuiltin("ReloadSkin()")
def backup_skinshortcuts_images(shortcutfile, dest_path): '''parse skinshortcuts file and copy images to backup location''' if sys.version_info.major == 3: shortcutfile = try_decode(xbmcvfs.translatePath(shortcutfile)) else: shortcutfile = try_decode(xbmc.translatePath(shortcutfile)) doc = parse(shortcutfile) listing = doc.documentElement.getElementsByTagName('shortcut') for shortcut in listing: defaultid = shortcut.getElementsByTagName('defaultID') if defaultid: defaultid = defaultid[0].firstChild if defaultid: defaultid = defaultid.data if not defaultid: defaultid = shortcut.getElementsByTagName( 'label')[0].firstChild.data thumb = shortcut.getElementsByTagName('thumb') if thumb: thumb = thumb[0].firstChild if thumb: thumb = thumb.data if thumb and (thumb.endswith(".jpg") or thumb.endswith(".png") or thumb.endswith(".gif")): thumb = get_clean_image(thumb) extension = thumb.split(".")[-1] newthumb = os.path.join( dest_path, "%s-thumb-%s.%s" % (xbmc.getSkinDir(), normalize_string(defaultid), extension)) newthumb_vfs = "special://profile/addon_data/script.skinshortcuts/%s-thumb-%s.%s" % ( xbmc.getSkinDir(), normalize_string(defaultid), extension) if xbmcvfs.exists(thumb): copy_file(thumb, newthumb) shortcut.getElementsByTagName( 'thumb')[0].firstChild.data = newthumb_vfs # write changes to skinshortcuts file shortcuts_file = xbmcvfs.File(shortcutfile, "w") if sys.version_info.major == 3: shortcuts_file.write(doc.toxml()) else: shortcuts_file.write(doc.toxml(encoding='utf-8')) shortcuts_file.close()
def get_backupfilename(self, promptfilename=False): '''get the filename for the new backup''' backupfile = "%s Skinbackup (%s)" % (get_skin_name().capitalize( ), datetime.now().strftime('%Y-%m-%d %H.%M.%S')) if promptfilename: header = self.addon.getLocalizedString(32003) backupfile = try_decode(xbmcgui.Dialog().input(header, backupfile)) backupfile += ".zip" return self.get_backuppath() + backupfile
def setskinsetting(self): setting = self.params.get('setting', '') org_id = self.params.get('id', '') if '$' in org_id: org_id = try_decode(xbmc.getInfoLabel(org_id)) header = self.params.get('header', '') SkinSettings().set_skin_setting(setting=setting, window_header=header, original_id=org_id)
def walk_directory(browsedir, recursive=False, label2=""): images = [] if xbmcvfs.exists(browsedir): dirs = xbmcvfs.listdir(browsedir)[0] subdirs = [browsedir] for directory in dirs: directory = try_decode(directory) cur_dir = "%s%s/" % (browsedir, directory) if recursive: subdirs.append(cur_dir) else: label = directory images.append((label, cur_dir, label2, "DefaultFolder.png")) for subdir in subdirs: for imagefile in xbmcvfs.listdir(subdir)[1]: imagefile = try_decode(imagefile) label = imagefile imagepath = subdir + imagefile images.append((label, imagepath, label2, imagepath)) return images