def hasVideoExtras(self, target, dbid, file, title=None): # If the service is on, then we can just check to see if the overlay image exists if Settings.isServiceEnabled(): # Get the path where the file exists rootPath = os_path_join(PROFILE_DIR, target) if not dir_exists(rootPath): # Directory does not exist yet, so can't have extras return False # Generate the name of the file that the overlay will be copied to targetFile = os_path_join(rootPath, ("%d.png" % dbid)) if xbmcvfs.exists(targetFile): return True # Otherwise, need to do the lookup the old fashioned way of looking for the # extras files on the file system (This is much slower) else: videoExtras = VideoExtrasBase(file, target, title) # We are only checking for existence of extras, no need for fanart firstExtraFile = videoExtras.findExtras(True) del videoExtras if firstExtraFile: log("MenuNavigator: Extras found for (%d) %s" % (dbid, file)) return True return False
def _moveToThemeFolder(self, directory): log("moveToThemeFolder: path = %s" % directory) # Handle the case where we have a disk image if (os_path_split(directory)[1] == 'VIDEO_TS') or (os_path_split(directory)[1] == 'BDMV'): directory = os_path_split(directory)[0] dirs, files = list_dir(directory) for aFile in files: m = re.search(Settings.getThemeFileRegEx(directory), aFile, re.IGNORECASE) if m: srcpath = os_path_join(directory, aFile) log("fetchAllMissingThemes: Found match: %s" % srcpath) targetpath = os_path_join(directory, Settings.getThemeDirectory()) # Make sure the theme directory exists if not dir_exists(targetpath): try: xbmcvfs.mkdir(targetpath) except: log("fetchAllMissingThemes: Failed to create directory: %s" % targetpath, True, xbmc.LOGERROR) break else: log("moveToThemeFolder: directory already exists %s" % targetpath) # Add the filename to the path targetpath = os_path_join(targetpath, aFile) if not xbmcvfs.rename(srcpath, targetpath): log("moveToThemeFolder: Failed to move file from %s to %s" % (srcpath, targetpath))
def _getAllFilesInDirectory(self, baseDir, includeSubDirs=True): videoFiles = [] dirs, files = list_dir(baseDir) # Get the list of files that are to be excluded collectionCtrl = CollectSets() disabledVideos = collectionCtrl.getDisabledVideos() del collectionCtrl # Get all the files in the current directory for vidFile in files: # Check if this file is excluded if vidFile in disabledVideos: log("Ignoring disabled screensaver video %s" % vidFile) continue fullPath = os_path_join(baseDir, vidFile) videoFiles.append(fullPath) # Now check each directory if includeSubDirs and Settings.isFolderNested(): for aDir in dirs: fullPath = os_path_join(baseDir, aDir) dirContents = self._getAllFilesInDirectory(fullPath) videoFiles = videoFiles + dirContents return videoFiles
def __init__(self): # special://skin - This path points to the currently active skin's root directory. skinExtrasOverlayBase = xbmc.translatePath("special://skin").decode("utf-8") skinExtrasOverlayBase = os_path_join(skinExtrasOverlayBase, "media") # Now check to see if the user has defines a different overlay image in the # settings, as that is the main one that will be used self.skinExtrasOverlay = Settings.getCustomOverlayImage() self.skinExtrasOverlayList = Settings.getCustomListImage() # Next check the skin specific overlay if self.skinExtrasOverlay in [None, '']: self.skinExtrasOverlay = os_path_join(skinExtrasOverlayBase, "videoextras_overlay.png") if self.skinExtrasOverlayList in [None, '']: self.skinExtrasOverlayList = os_path_join(skinExtrasOverlayBase, "videoextras_overlay_list.png") log("VideoExtrasService: Looking for image overlay file: %s" % self.skinExtrasOverlay) if not xbmcvfs.exists(self.skinExtrasOverlay): log("VideoExtrasService: No custom image, using default") # Add default image setting to skinExtrasOverlay self.skinExtrasOverlay = os_path_join(RES_DIR, "skins") self.skinExtrasOverlay = os_path_join(self.skinExtrasOverlay, "icons") self.skinExtrasOverlay = os_path_join(self.skinExtrasOverlay, "overlay1.png") log("VideoExtrasService: Looking for list image overlay file: %s" % self.skinExtrasOverlayList) if not xbmcvfs.exists(self.skinExtrasOverlayList): log("VideoExtrasService: No custom wide image, using default") # Add default image setting to skinExtrasOverlay self.skinExtrasOverlayList = os_path_join(RES_DIR, "skins") self.skinExtrasOverlayList = os_path_join(self.skinExtrasOverlayList, "icons") self.skinExtrasOverlayList = os_path_join(self.skinExtrasOverlayList, "list1.png") self.forceOverlayOverwrite = False # We now know the file that we are going to use for the overlay # Check to see if this is different from the last overlay file used filename = os_path_join(PROFILE_DIR, "overlay_image_used.txt") try: previousOverlay = None if xbmcvfs.exists(filename): fileHandle = xbmcvfs.File(filename, 'r') previousOverlay = fileHandle.read() fileHandle.close() # Check if the overlay has changed if self.skinExtrasOverlay != previousOverlay: self.forceOverlayOverwrite = True # Update the record of the file we are now using if xbmcvfs.exists(filename): xbmcvfs.delete(filename) fileHandle = xbmcvfs.File(filename, 'w') fileHandle.write(self.skinExtrasOverlay.encode("UTF-8")) fileHandle.close() except: log("VideoExtrasService: Failed to write: %s" % filename, xbmc.LOGERROR) log("VideoExtrasService: %s" % traceback.format_exc(), xbmc.LOGERROR)
def _createTargetPath(self, target, dbid, postfix=''): # Get the path where the file exists rootPath = os_path_join(PROFILE_DIR, target) if not dir_exists(rootPath): # Directory does not exist yet, create one xbmcvfs.mkdirs(rootPath) # Generate the name of the file that the overlay will be copied to targetFile = os_path_join(rootPath, ("%d%s.png" % (dbid, postfix))) return targetFile
def _addIncludeFile(self): # copy over the video extras include file skinsDir = xbmc.translatePath(os_path_join(RES_DIR, 'skins').encode("utf-8")).decode("utf-8") incFile = os_path_join(skinsDir, 'IncludesVideoExtras.xml') # Work out where it is going to go tgtFile = os_path_join(self.confpath, 'IncludesVideoExtras.xml') log("IncludesVideoExtras: Copy from %s to %s" % (incFile, tgtFile)) xbmcvfs.copy(incFile, tgtFile) # Now the file should be copied to the target location # Check to make sure it worked, if it did not then the directory may not # have the correct permissions for us to write to return xbmcvfs.exists(tgtFile)
def _getVideoLocation(self, folder, filename): log("VideoScreensaverPlugin: Checking if %s already downloaded to %s" % (filename, folder)) videoLocation = os_path_join(folder, filename) if xbmcvfs.exists(videoLocation): return videoLocation # Check nested directories if Settings.isFolderNested(): dirs, files = list_dir(folder) for aDir in dirs: fullPath = os_path_join(folder, aDir) filePath = self._getVideoLocation(fullPath, filename) if filePath not in [None, ""]: return filePath return None
def _doesThemeExist(self, directory, checkParent=False, incAudioThemes=True, incVideoThemes=True): log("doesThemeExist: Checking directory: %s" % directory) # Check for custom theme directory if Settings.isThemeDirEnabled(): themeDir = os_path_join(directory, Settings.getThemeDirectory()) # Check if this directory exists if not dir_exists(themeDir): workingPath = directory # If the path currently ends in the directory separator # then we need to clear an extra one if (workingPath[-1] == os.sep) or (workingPath[-1] == os.altsep): workingPath = workingPath[:-1] # If not check to see if we have a DVD VOB if (os_path_split(workingPath)[1] == 'VIDEO_TS') or (os_path_split(workingPath)[1] == 'BDMV'): # Check the parent of the DVD Dir themeDir = os_path_split(workingPath)[0] themeDir = os_path_join(themeDir, Settings.getThemeDirectory()) directory = themeDir # Check to see if we need to check the parent directory if checkParent: directory = os_path_split(directory)[0] # check if the directory exists before searching if dir_exists(directory): # Generate the regex audioOnly = False videoOnly = False if not incAudioThemes: videoOnly = True if not incVideoThemes: audioOnly = True themeFileRegEx = Settings.getThemeFileRegEx(audioOnly=audioOnly, videoOnly=videoOnly) dirs, files = list_dir(directory) for aFile in files: m = re.search(themeFileRegEx, aFile, re.IGNORECASE) if m: log("doesThemeExist: Found match: " + aFile) return True # Check if an NFO file exists nfoFileName = os_path_join(directory, "tvtunes.nfo") if xbmcvfs.exists(nfoFileName): log("doesThemeExist: Found match: " + nfoFileName) return True return False
def _updateViewsFileMode(self): # Get the location of the information dialog XML file dialogXml = os_path_join(self.confpath, 'ViewsFileMode.xml') log("ViewsVideoLibrary: Confluence dialog XML file: %s" % dialogXml) # Make sure the file exists (It should always exist) if not xbmcvfs.exists(dialogXml): log("ViewsVideoLibrary: Unable to find the file ViewsFileMode.xml, skipping file", xbmc.LOGERROR) self.errorToLog = True return # Load the DialogVideoInfo.xml into a string dialogXmlFile = xbmcvfs.File(dialogXml, 'r') dialogXmlStr = dialogXmlFile.read() dialogXmlFile.close() # Now check to see if the skin file has already had the video extras bits added if 'IncludesVideoExtras' in dialogXmlStr: # Already have video extras referenced, so we do not want to do anything else # to this file log("ViewsFileMode: Video extras already referenced in %s, skipping file" % dialogXml, xbmc.LOGINFO) self.errorToLog = True return # Update the different view sections dialogXmlStr = self._updateCommonRootView(dialogXmlStr) dialogXmlStr = self._updateThumbnailView(dialogXmlStr) dialogXmlStr = self._updateWideIconView(dialogXmlStr) dialogXmlStr = self._updateFullWidthList(dialogXmlStr) # Now add the include link to the file dialogXmlStr = self._addIncludeToXml(dialogXmlStr) self._saveNewFile(dialogXml, dialogXmlStr)
def removeCollection(self, name, link): if name in [None, ""]: return collectionCtrl = CollectSets() collectionDetails = collectionCtrl.loadCollection(link) filesToDelete = [] # If the file was not processed just don't display anything if collectionDetails not in [None, ""]: screensaverFolder = Settings.getScreensaverFolder() for videoItem in collectionDetails['videos']: # If theme exists we need to check if we want to delete it if screensaverFolder not in [None, ""]: videoLocation = os_path_join(screensaverFolder, videoItem['filename']) log("VideoScreensaverPlugin: Checking if %s already downloaded to %s" % (videoItem['filename'], videoLocation)) if xbmcvfs.exists(videoLocation): filesToDelete.append(videoLocation) # If there are possible files to delete, then prompt the user to see if we should if len(filesToDelete) > 0: needDelete = xbmcgui.Dialog().yesno(ADDON.getLocalizedString(32005), ADDON.getLocalizedString(32086)) if needDelete: for vidFile in filesToDelete: xbmcvfs.delete(vidFile) # Now remove the actual collection collectionCtrl.removeCustomCollection(name) del collectionCtrl # Now reload the screen to reflect the change xbmc.executebuiltin("Container.Refresh")
def _updateDialogVideoInfo(self): # Get the location of the information dialog XML file dialogXml = os_path_join(self.confpath, 'DialogVideoInfo.xml') log("DialogVideoInfo: Confluence dialog XML file: %s" % dialogXml) # Make sure the file exists (It should always exist) if not xbmcvfs.exists(dialogXml): log("DialogVideoInfo: Unable to find the file DialogVideoInfo.xml, skipping file", xbmc.LOGERROR) self.errorToLog = True return # Load the DialogVideoInfo.xml into a string dialogXmlFile = xbmcvfs.File(dialogXml, 'r') dialogXmlStr = dialogXmlFile.read() dialogXmlFile.close() # Now check to see if the skin file has already had the suitability bits added if 'script.suitability' in dialogXmlStr: # Already have suitability referenced, so we do not want to do anything else # to this file log("DialogVideoInfo: Suitability already referenced in %s, skipping file" % dialogXml, xbmc.LOGINFO) self.errorToLog = True return # Now we need to add the button after the Final button previousButton = '<label>13511</label>' if previousButton not in dialogXmlStr: # The file has had a standard component deleted, so quit log("DialogVideoInfo: Could not find final button, skipping file", xbmc.LOGERROR) self.errorToLog = True return # Check to make sure we use a unique ID value for the button idOK = False idval = 102 while not idOK: idStr = "id=\"%d\"" % idval if idStr not in dialogXmlStr: idOK = True else: idval = idval + 1 # Now add the Suitability button after the Final one DIALOG_VIDEO_INFO_BUTTON = '''\n\t\t\t\t\t</control>\n\t\t\t\t\t<control type="button" id="%d"> \t\t\t\t\t\t<description>Suitability</description> \t\t\t\t\t\t<include>ButtonInfoDialogsCommonValues</include> \t\t\t\t\t\t<label>$ADDON[script.suitability 32001]</label> \t\t\t\t\t\t<onclick>RunScript(script.suitability)</onclick> \t\t\t\t\t\t<visible>System.HasAddon(script.suitability) + [Container.Content(movies) | Container.Content(tvshows)]</visible>''' insertTxt = previousButton + (DIALOG_VIDEO_INFO_BUTTON % idval) dialogXmlStr = dialogXmlStr.replace(previousButton, insertTxt) self._saveNewFile(dialogXml, dialogXmlStr)
def __init__(self): # Find out where the confluence skin files are located confAddon = xbmcaddon.Addon(id='skin.confluence') self.confpath = xbmc.translatePath(confAddon.getAddonInfo('path')) self.confpath = os_path_join(self.confpath, '720p') log("Confluence Location: %s" % self.confpath) # Create the timestamp centrally, as we want all files changed for a single # run to have the same backup timestamp so it can be easily undone if the # user wishes to switch it back self.bak_timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S") self.errorToLog = False
def getPathForVideoItem(self, videoItem): path = "" # Get the path where the theme should be stored if Settings.isCustomPathEnabled(): path = os_path_join(Settings.getCustomPath(), normalize_string(videoItem['title'])) else: path = videoItem['file'] # Handle stacked files that have a custom file name format if path.startswith("stack://"): path = path.replace("stack://", "").split(" , ", 1)[0] # Need to remove the filename from the end as we just want the directory fileExt = os.path.splitext(path)[1] # If this is a file, then get it's parent directory if fileExt is not None and fileExt != "": path = os_path_split(path)[0] return path
def delete(self, fullpath): log("AudioBooksPlugin: Delete for %s" % fullpath) # make sure that delete is enabled if not Settings.isDeleteSupported(): return # Prompt the user to make sure they really want to delete the given location okToDelete = xbmcgui.Dialog().yesno(ADDON.getLocalizedString(32001), ADDON.getLocalizedString(32033), fullpath) if not okToDelete: return try: # Check if this is a file or directory # Support special paths like smb:// means that we can not just call # os.path.isfile as it will return false even if it is a file fileExt = os.path.splitext(fullpath)[1] # If this is a file, then get it's parent directory if fileExt not in [None, ""]: # This is just a file, so delete just the file xbmcvfs.delete(fullpath) else: # Delete all the files in the directory and then the directory itself dirs, files = xbmcvfs.listdir(fullpath) for aFile in files: if aFile.startswith('.'): continue log("AudioBooksPlugin: Removing file %s" % aFile) abookFile = os_path_join(fullpath, aFile) xbmcvfs.delete(abookFile) # Now remove the actual directory xbmcvfs.rmdir(fullpath) except: log("AudioBooksPlugin: Failed to delete %s with error %s" % (fullpath, traceback.format_exc())) # Tell the user that the delete failed xbmcgui.Dialog().ok(ADDON.getLocalizedString(32001), ADDON.getLocalizedString(32034), fullpath) # Refresh the page without the file that was deleted xbmc.executebuiltin("Container.Refresh")
def _updateViewsVideoLibrary(self): # Get the location of the information dialog XML file dialogXml = os_path_join(self.confpath, 'ViewsVideoLibrary.xml') log("ViewsVideoLibrary: Confluence dialog XML file: %s" % dialogXml) # Make sure the file exists (It should always exist) if not xbmcvfs.exists(dialogXml): log( "ViewsVideoLibrary: Unable to find the file ViewsVideoLibrary.xml, skipping file", xbmc.LOGERROR) self.errorToLog = True return # Load the DialogVideoInfo.xml into a string dialogXmlFile = xbmcvfs.File(dialogXml, 'r') dialogXmlStr = dialogXmlFile.read() dialogXmlFile.close() # Now check to see if the skin file has already had the video extras bits added if 'IncludesVideoExtras' in dialogXmlStr: # Already have video extras referenced, so we do not want to do anything else # to this file log( "ViewsVideoLibrary: Video extras already referenced in %s, skipping file" % dialogXml, xbmc.LOGINFO) self.errorToLog = True return # Update the different view sections dialogXmlStr = self._updatePosterWrapView(dialogXmlStr) dialogXmlStr = self._updatePosterWrapView2_Fanart(dialogXmlStr) dialogXmlStr = self._updateMediaListView3(dialogXmlStr) dialogXmlStr = self._updateMediaListView2(dialogXmlStr) dialogXmlStr = self._updateMediaListView4(dialogXmlStr) # Now add the include link to the file dialogXmlStr = self._addIncludeToXml(dialogXmlStr) self._saveNewFile(dialogXml, dialogXmlStr)
def removeCollection(self, name, link): if name in [None, ""]: return collectionCtrl = CollectSets() collectionDetails = collectionCtrl.loadCollection(link) filesToDelete = [] # If the file was not processed just don't display anything if collectionDetails not in [None, ""]: screensaverFolder = Settings.getScreensaverFolder() for videoItem in collectionDetails['videos']: # If theme exists we need to check if we want to delete it if screensaverFolder not in [None, ""]: videoLocation = os_path_join(screensaverFolder, videoItem['filename']) log("VideoScreensaverPlugin: Checking if %s already downloaded to %s" % (videoItem['filename'], videoLocation)) if xbmcvfs.exists(videoLocation): filesToDelete.append(videoLocation) # If there are possible files to delete, then prompt the user to see if we should if len(filesToDelete) > 0: needDelete = xbmcgui.Dialog().yesno( ADDON.getLocalizedString(32005), ADDON.getLocalizedString(32086)) if needDelete: for vidFile in filesToDelete: xbmcvfs.delete(vidFile) # Now remove the actual collection collectionCtrl.removeCustomCollection(name) del collectionCtrl # Now reload the screen to reflect the change xbmc.executebuiltin("Container.Refresh")
def getCollections(self): collectionMap = {} # Add the default set of collections collectionsDir = ADDON.getAddonInfo('path') collectionsDir = xbmc.translatePath( os_path_join(collectionsDir, 'resources')) collectionsDir = os_path_join(collectionsDir, 'collections') collectionMap['Aquarium'] = { 'name': 'Aquarium', 'filename': os_path_join(collectionsDir, 'aquarium.xml'), 'image': ICON, 'default': True } collectionMap['Beach'] = { 'name': 'Beach', 'filename': os_path_join(collectionsDir, 'beach.xml'), 'image': ICON, 'default': True } collectionMap['Clock'] = { 'name': 'Clock', 'filename': os_path_join(collectionsDir, 'clock.xml'), 'image': ICON, 'default': True } collectionMap['Fireplace'] = { 'name': 'Fireplace', 'filename': os_path_join(collectionsDir, 'fireplace.xml'), 'image': ICON, 'default': True } collectionMap['Miscellaneous'] = { 'name': 'Miscellaneous', 'filename': os_path_join(collectionsDir, 'miscellaneous.xml'), 'image': ICON, 'default': True } collectionMap['Snow'] = { 'name': 'Snow', 'filename': os_path_join(collectionsDir, 'snow.xml'), 'image': ICON, 'default': True } collectionMap['Space'] = { 'name': 'Space', 'filename': os_path_join(collectionsDir, 'space.xml'), 'image': ICON, 'default': True } collectionMap['Waterfall'] = { 'name': 'Waterfall', 'filename': os_path_join(collectionsDir, 'waterfall.xml'), 'image': ICON, 'default': True } collectionMap['Woodland'] = { 'name': 'Woodland', 'filename': os_path_join(collectionsDir, 'woodland.xml'), 'image': ICON, 'default': True } # http://a1.phobos.apple.com/us/r1000/000/Features/atv/AutumnResources/videos/entries.json collectionMap['Apple TV'] = { 'name': 'Apple TV', 'filename': os_path_join(collectionsDir, 'appletv.xml'), 'image': ICON, 'default': True } # Now add any custom collections customCollections = self.getCustomCollectionSets() collectionMap.update(customCollections) return collectionMap
from resources.lib.settings import Settings from resources.lib.database import AudioBooksDB from resources.lib.ffmpegLib import FFMpegLib ADDON = xbmcaddon.Addon(id='script.audiobooks') ######################### # Main ######################### if __name__ == '__main__': log("AudioBookService: Checking audiobook database version (version %s)" % ADDON.getAddonInfo('version')) configPath = xbmc.translatePath(ADDON.getAddonInfo('profile')) databasefile = os_path_join(configPath, "audiobooks_database.db") log("AudioBookService: Checking database file = %s" % databasefile) # If the database file exists, check if it needs updating if xbmcvfs.exists(databasefile): audiobookDB = AudioBooksDB() audiobookDB.createDatabase() del audiobookDB if Settings.isFFmpegAutoDetect(): log("AudioBookService: Performing refresh check on FFmpeg") # Turn off the search at startup as we do not want to do this every time Settings.clearFFmpegAutoDetect() # Clear the existing settings Settings.setFFmpegLibraryLocation("")
def showAudiobooks(self, directory=None): # Get the setting for the audio book directory audioBookFolder = Settings.getAudioBookFolder() if audioBookFolder in [None, ""]: # Prompt the user to set the eBooks Folder audioBookFolder = xbmcgui.Dialog().browseSingle( 0, ADDON.getLocalizedString(32005), 'files') # Check to make sure the directory is set now if audioBookFolder in [None, ""]: xbmcgui.Dialog().ok(ADDON.getLocalizedString(32001), ADDON.getLocalizedString(32006)) return # Save the directory in settings for future use log("AudioBooksPlugin: Setting Audio Books folder to %s" % audioBookFolder) Settings.setAudioBookFolder(audioBookFolder) # We may be looking at a subdirectory if directory not in [None, ""]: audioBookFolder = directory dirs, files = xbmcvfs.listdir(audioBookFolder) files.sort() dirs.sort() bookDirs = [] # For each directory list allow the user to navigate into it for adir in dirs: if adir.startswith('.'): continue fullDir = os_path_join(audioBookFolder, adir) # Check if this directory is a book directory if self._isAudioBookDir(fullDir): bookDirs.append(fullDir) continue log("AudioBooksPlugin: Adding directory %s" % adir) try: displayName = "[%s]" % adir.encode("utf-8") except: displayName = "[%s]" % adir try: fullDir = fullDir.encode("utf-8") except: pass plot = "" try: plot = "[B]%s[/B]" % adir.encode("utf-8") except: plot = adir # Check if there are any images for this directory iconImage = 'DefaultFolder.png' fanartImage = FANART subDirs, subFiles = xbmcvfs.listdir(fullDir) for fileInDir in subFiles: if fileInDir.lower() in ['fanart.jpg', 'fanart.png']: fanartImage = os_path_join(fullDir, fileInDir) elif fileInDir.lower() in ['folder.jpg', 'folder.png']: iconImage = os_path_join(fullDir, fileInDir) url = self._build_url({'mode': 'directory', 'directory': fullDir}) li = xbmcgui.ListItem(displayName, iconImage=iconImage) li.setProperty("Fanart_Image", fanartImage) li.setInfo('video', {'Plot': plot}) li.addContextMenuItems([], replaceItems=True) xbmcplugin.addDirectoryItem(handle=self.addon_handle, url=url, listitem=li, isFolder=True) m4bAudioBooks = [] for m4bBookFile in files: # Check to ensure that this is an eBook if not m4bBookFile.lower().endswith('.m4b'): log("AudioBooksPlugin: Skipping non audiobook file: %s" % m4bBookFile) continue fullpath = os_path_join(audioBookFolder, m4bBookFile) m4bAudioBooks.append(fullpath) # Get all the audiobook in a nicely sorted order allAudioBooks = sorted(bookDirs + m4bAudioBooks) audioBookHandlers = [] # Now list all of the books for audioBookFile in allAudioBooks: log("AudioBooksPlugin: Adding audiobook %s" % audioBookFile) audioBookHandlers.append( AudioBookHandler.createHandler(audioBookFile)) # Now sort the list by title audioBookHandlers.sort() # Now list all of the books for audioBookHandler in audioBookHandlers: log("AudioBooksPlugin: Processing audiobook %s" % audioBookHandler.getFile()) title = audioBookHandler.getTitle() coverTargetName = audioBookHandler.getCoverImage(True) isRead = False if Settings.isMarkCompletedItems(): if audioBookHandler.isCompleted(): isRead = True displayString = title try: displayString = title.encode("utf-8") except: displayString = title try: log("AudioBooksPlugin: Display title is %s for %s" % (displayString, audioBookFile)) except: # No need to have an error for logging pass plot = "" try: plot = "[B]%s[/B]" % displayString except: plot = displayString if isRead: displayString = '* %s' % displayString url = self._build_url({ 'mode': 'chapters', 'filename': audioBookHandler.getFile(True), 'cover': coverTargetName }) li = xbmcgui.ListItem(displayString, iconImage=coverTargetName) li.setProperty("Fanart_Image", audioBookHandler.getFanArt()) li.setInfo('video', {'Plot': plot}) li.addContextMenuItems(self._getContextMenu(audioBookHandler), replaceItems=True) xbmcplugin.addDirectoryItem(handle=self.addon_handle, url=url, listitem=li, isFolder=True) del audioBookHandler xbmcplugin.endOfDirectory(self.addon_handle)
def showEbooksDirectory(self, directory=''): log("EBooksPlugin: Showing eBooks for directory %s" % str(directory)) # Get the setting for the ebook directory eBookFolder = Settings.getEbookFolder() if eBookFolder in [None, ""]: # Prompt the user to set the eBooks Folder eBookFolder = xbmcgui.Dialog().browseSingle( 0, ADDON.getLocalizedString(32005), 'files') # Check to make sure the directory is set now if eBookFolder in [None, ""]: xbmcgui.Dialog().ok(ADDON.getLocalizedString(32001), ADDON.getLocalizedString(32006)) return # Save the directory in settings for future use log("EBooksPlugin: Setting eBooks folder to %s" % eBookFolder) Settings.setEbookFolder(eBookFolder) # We may be looking at a subdirectory if directory.strip() not in [None, ""]: eBookFolder = directory dirs, files = xbmcvfs.listdir(eBookFolder) dirs.sort() files.sort() # For each directory list allow the user to navigate into it for adir in dirs: if adir.startswith('.'): continue log("EBooksPlugin: Adding directory %s" % adir) nextDir = os_path_join(eBookFolder, adir) displayName = "[%s]" % adir try: displayName = "[%s]" % adir.encode("utf-8") except: displayName = "[%s]" % adir try: nextDir = nextDir.encode("utf-8") except: pass # Check if there is a folder image in the directory folderImage = 'DefaultFolder.png' fanartImage = FANART subdirs, filesInDir = xbmcvfs.listdir(nextDir) for fileInDir in filesInDir: if fileInDir.lower() in [ 'folder.jpg', 'cover.jpg', 'folder.png', 'cover.png' ]: folderImage = os_path_join(nextDir, fileInDir) elif fileInDir.lower() in ['fanart.jpg', 'fanart.png']: fanartImage = os_path_join(nextDir, fileInDir) url = self._build_url({'mode': 'directory', 'directory': nextDir}) li = xbmcgui.ListItem(displayName, iconImage=folderImage) li.setProperty("Fanart_Image", fanartImage) plotDisplay = "[B]%s[/B]" % adir li.setInfo('video', {'Plot': plotDisplay}) li.addContextMenuItems([], replaceItems=True) xbmcplugin.addDirectoryItem(handle=self.addon_handle, url=url, listitem=li, isFolder=True) # Now list all of the books for eBookFile in files: log("EBooksPlugin: Processing file %s" % eBookFile) # Check to ensure that this is an eBook if not Settings.isEbookFormat(eBookFile): log("EBooksPlugin: Skipping non ebook file: %s" % eBookFile) continue fullpath = os_path_join(eBookFolder, eBookFile) # Check in the database to see if this book is already recorded bookDB = EbooksDB() bookDetails = bookDB.getBookDetails(fullpath) title = "" author = "" description = "" isRead = False if bookDetails in [None, ""]: # Need the details of this book # Get the details of this book eBook = EBookBase.createEBookObject(fullpath) title = eBook.getTitle() author = eBook.getAuthor() description = eBook.getDescription() eBook.tidyUp() del eBook # Add this book to the list bookDB.addBook(fullpath, title, author, description) else: isRead = bookDetails['complete'] title = bookDetails['title'] author = bookDetails['author'] description = bookDetails['description'] del bookDB displayString = eBookFile try: displayString = title.encode("utf-8") except: displayString = title if author not in [None, ""]: try: author = author.encode("utf-8") except: pass try: displayString = "%s - %s" % (author, displayString) except: pass try: # With some text, logging is causing issues log("EBookBase: Display title is %s for %s" % (displayString, fullpath)) except: pass if isRead: try: displayString = '* %s' % displayString except: log("EBookBase: Unable to mark as read") coverTargetName = EBookBase.getCoverImage(fullpath, eBookFile) if coverTargetName in [None, ""]: coverTargetName = Settings.getFallbackCoverImage() try: fullpath = fullpath.encode("utf-8") except: pass if coverTargetName not in [None, ""]: try: coverTargetName = coverTargetName.encode("utf-8") except: pass url = self._build_url({ 'mode': 'chapters', 'filename': fullpath, 'cover': coverTargetName }) li = xbmcgui.ListItem(displayString, iconImage=coverTargetName) li.setProperty("Fanart_Image", EBookBase.getFanArt(fullpath)) if description not in [None, ""]: li.setInfo('video', {'Plot': description}) li.addContextMenuItems(self._getContextMenu(fullpath), replaceItems=True) xbmcplugin.addDirectoryItem(handle=self.addon_handle, url=url, listitem=li, isFolder=True) xbmcplugin.endOfDirectory(self.addon_handle)
def download(self, name, filename, downloadURL): log("VideoScreensaverPlugin: Downloading %s" % name) tmpdestination = os_path_join(Settings.getTempFolder(), filename) destination = os_path_join(Settings.getScreensaverFolder(), filename) # Check to see if there is already a file present if xbmcvfs.exists(destination): useExisting = xbmcgui.Dialog().yesno(ADDON.getLocalizedString(32005), ADDON.getLocalizedString(32301), name, ADDON.getLocalizedString(32302)) if useExisting: # Don't want to overwrite, so nothing to do log("Download: Reusing existing video file %s" % destination) return else: log("Download: Removing existing file %s ready for fresh download" % destination) xbmcvfs.delete(destination) # Create a progress dialog for the download downloadProgressDialog = xbmcgui.DialogProgress() downloadProgressDialog.create(ADDON.getLocalizedString(32303), name, filename, destination) # Callback method to report progress def _report_hook(count, blocksize, totalsize): percent = int(float(count * blocksize * 100) / totalsize) downloadProgressDialog.update(percent, name, filename, destination) if downloadProgressDialog.iscanceled(): log("Download: Operation cancelled") raise ValueError('Download Cancelled') try: log("Download: Using server: %s" % downloadURL) # Now retrieve the actual file fp, h = urllib.urlretrieve(downloadURL, tmpdestination, _report_hook) log(h) # Check to make sure that the file created downloaded correctly st = xbmcvfs.Stat(tmpdestination) fileSize = st.st_size() log("Download: Size of file %s is %d" % (tmpdestination, fileSize)) # Check for something that has a size greater than zero (in case some OSs do not # support looking at the size), but less that 1,000,000 (As all our files are # larger than that if (fileSize > 0) and (fileSize < 1000000): log("Download: Detected that file %s did not download correctly as file size is only %d" % (downloadURL, fileSize)) xbmcgui.Dialog().ok(ADDON.getLocalizedString(32005), ADDON.getLocalizedString(32306)) else: log("Download: Copy from %s to %s" % (tmpdestination, destination)) copy = xbmcvfs.copy(tmpdestination, destination) if copy: log("Download: Copy Successful") else: log("Download: Copy Failed") xbmcvfs.delete(tmpdestination) except ValueError: # This was a cancel by the user, so remove any file that may be part downloaded if xbmcvfs.exists(tmpdestination): xbmcvfs.delete(tmpdestination) except: log("Download: Theme download Failed!!!", xbmc.LOGERROR) log("Download: %s" % traceback.format_exc(), xbmc.LOGERROR) # Make sure the progress dialog has been closed downloadProgressDialog.close() # Now reload the screen to reflect the change xbmc.executebuiltin("Container.Refresh")
def _setClassificationList(self, type="", subtype=""): classifications = () securityDetails = {} # Make the call to the DB to get all the specific security settings pinDB = PinSentryDB() if type == MenuNavigator.CLASSIFICATIONS_MOVIES: classifications = Settings.movieCassificationsNames securityDetails = pinDB.getAllMovieClassificationSecurity() elif type == MenuNavigator.CLASSIFICATIONS_TV: classifications = Settings.tvCassificationsNames securityDetails = pinDB.getAllTvClassificationSecurity() del pinDB # Check if we are showing the root classification listing if type in [None, ""]: url = self._build_url({ 'mode': 'folder', 'foldername': MenuNavigator.CLASSIFICATIONS, 'type': MenuNavigator.CLASSIFICATIONS_MOVIES }) li = xbmcgui.ListItem(ADDON.getLocalizedString(32207), iconImage=ICON) li.setProperty("Fanart_Image", FANART) li.addContextMenuItems([], replaceItems=True) xbmcplugin.addDirectoryItem(handle=self.addon_handle, url=url, listitem=li, isFolder=True) url = self._build_url({ 'mode': 'folder', 'foldername': MenuNavigator.CLASSIFICATIONS, 'type': MenuNavigator.CLASSIFICATIONS_TV }) li = xbmcgui.ListItem(ADDON.getLocalizedString(32208), iconImage=ICON) li.setProperty("Fanart_Image", FANART) li.addContextMenuItems([], replaceItems=True) xbmcplugin.addDirectoryItem(handle=self.addon_handle, url=url, listitem=li, isFolder=True) elif subtype in [None, ""]: # Get all the different language that are supported languages = [] for classification in classifications: if classification['lang'] not in languages: languages.append(classification['lang']) # Check to see if we can sort all the entries alphabetically for the given language try: languages = sorted(languages, key=ADDON.getLocalizedString) except: # If it fails to sort, then we just list them unsorted log("PinSentryPlugin: Failed to sort language list") # Now print out the item for each language for lang in languages: url = self._build_url({ 'mode': 'folder', 'foldername': MenuNavigator.CLASSIFICATIONS, 'type': type, 'subtype': str(lang) }) iconImage = ICON for flag in Settings.flags: if flag['lang'] == lang: iconImage = os_path_join(ICON_DIR, flag['icon']) li = xbmcgui.ListItem(ADDON.getLocalizedString(lang), iconImage=iconImage) li.setProperty("Fanart_Image", FANART) li.addContextMenuItems([], replaceItems=True) xbmcplugin.addDirectoryItem(handle=self.addon_handle, url=url, listitem=li, isFolder=True) else: for classification in classifications: # Check if we are looking for a specific country if subtype != str(classification['lang']): continue fullName = classification['name'] % ADDON.getLocalizedString( classification['lang']) idStr = str(classification['id']) securityLevel = 0 if idStr in securityDetails: securityLevel = securityDetails[idStr] log("PinSentryPlugin: Classification %s has security level %d" % (fullName, securityLevel)) # Set the icon to the certificate one if available iconImage = ICON if classification['icon'] not in [None, ""]: iconImage = os_path_join(ICON_DIR, classification['icon']) li = xbmcgui.ListItem(fullName, iconImage=iconImage) # Add a tick if security is set if securityLevel > 0: li.setInfo('video', {'PlayCount': 1}) li.setProperty("Fanart_Image", FANART) li.addContextMenuItems([], replaceItems=True) url = self._build_url({ 'mode': 'setsecurity', 'type': type, 'id': classification['id'], 'title': classification['match'], 'level': securityLevel }) xbmcplugin.addDirectoryItem(handle=self.addon_handle, url=url, listitem=li, isFolder=False) xbmcplugin.endOfDirectory(self.addon_handle)
def _updateDialogVideoInfo(self): # Get the location of the information dialog XML file dialogXml = os_path_join(self.confpath, 'DialogVideoInfo.xml') log("DialogVideoInfo: Confluence dialog XML file: %s" % dialogXml) # Make sure the file exists (It should always exist) if not xbmcvfs.exists(dialogXml): log("DialogVideoInfo: Unable to find the file DialogVideoInfo.xml, skipping file", xbmc.LOGERROR) self.errorToLog = True return # Load the DialogVideoInfo.xml into a string dialogXmlFile = xbmcvfs.File(dialogXml, 'r') dialogXmlStr = dialogXmlFile.read() dialogXmlFile.close() # Now check to see if the skin file has already had the video extras bits added if 'script.videoextras' in dialogXmlStr: # Already have video extras referenced, so we do not want to do anything else # to this file log("DialogVideoInfo: Video extras already referenced in %s, skipping file" % dialogXml, xbmc.LOGINFO) self.errorToLog = True return # Now add the include link to the file dialogXmlStr = self._addIncludeToXml(dialogXmlStr) # Start by adding the onLoad section previousOnLoad = '<controls>' if previousOnLoad not in dialogXmlStr: # The file has had a standard component deleted, so quit log("DialogVideoInfo: Could not find controls command, skipping file", xbmc.LOGERROR) self.errorToLog = True return # Now add the Video Extras onLoad command after the allowoverlay one DIALOG_VIDEO_INFO_ONLOAD = '<onload condition="System.HasAddon(script.videoextras)">RunScript(script.videoextras,check,"$INFO[ListItem.FilenameAndPath]")</onload>\n\t' insertTxt = DIALOG_VIDEO_INFO_ONLOAD + previousOnLoad dialogXmlStr = dialogXmlStr.replace(previousOnLoad, insertTxt) # Now we need to add the button after the Final button previousButton = '<label>13511</label>' if previousButton not in dialogXmlStr: # The file has had a standard component deleted, so quit log("DialogVideoInfo: Could not find final button, skipping file", xbmc.LOGERROR) self.errorToLog = True return # Check to make sure we use a unique ID value for the button idOK = False idval = 101 while not idOK: idStr = "id=\"%d\"" % idval if idStr not in dialogXmlStr: idOK = True else: idval = idval + 1 # Now add the Video Extras button after the Final one DIALOG_VIDEO_INFO_BUTTON = '''\n\t\t\t\t\t</control>\n\t\t\t\t\t<control type="button" id="%d"> \t\t\t\t\t\t<description>Extras</description> \t\t\t\t\t\t<include>ButtonInfoDialogsCommonValues</include> \t\t\t\t\t\t<label>$ADDON[script.videoextras 32001]</label> \t\t\t\t\t\t<onclick>RunScript(script.videoextras,display,"$INFO[ListItem.FilenameAndPath]")</onclick> \t\t\t\t\t\t<visible>System.HasAddon(script.videoextras) + [Container.Content(movies) | Container.Content(episodes) | Container.Content(TVShows) | Container.Content(musicvideos)] + IsEmpty(Window(movieinformation).Property("HideVideoExtrasButton"))</visible>''' insertTxt = previousButton + (DIALOG_VIDEO_INFO_BUTTON % idval) dialogXmlStr = dialogXmlStr.replace(previousButton, insertTxt) # Now add the section for the icon overlay iconPrevious = 'VideoTypeHackFlaggingConditions</include>' if iconPrevious not in dialogXmlStr: log("DialogVideoInfo: Could not find point to add icon overlay, skipping overlay addition", xbmc.LOGERROR) self.errorToLog = True return DIALOG_VIDEO_INFO_ICON = '''\n\t\t\t\t\t<!-- Add the Video Extras Icon --> \t\t\t\t\t<include>VideoExtrasLargeIcon</include> \t\t\t\t</control> \t\t\t\t<control type="grouplist"> \t\t\t\t\t<description>Add the Video Extras Icon</description> \t\t\t\t\t<left>210</left> \t\t\t\t\t<top>480</top> \t\t\t\t\t<width>600</width> \t\t\t\t\t<align>left</align> \t\t\t\t\t<itemgap>2</itemgap> \t\t\t\t\t<orientation>horizontal</orientation> \t\t\t\t\t<include>VisibleFadeEffect</include> \t\t\t\t\t<visible>!Control.IsVisible(50) + Container.Content(tvshows) + !Container.Content(Episodes)</visible> \t\t\t\t\t<include>VideoExtrasLargeIcon</include>''' insertTxt = iconPrevious + DIALOG_VIDEO_INFO_ICON dialogXmlStr = dialogXmlStr.replace(iconPrevious, insertTxt) self._saveNewFile(dialogXml, dialogXmlStr)
######################### # Main ######################### if __name__ == '__main__': log("AudioBookCoverCleanup: Cover cache cleanup called (version %s)" % ADDON.getAddonInfo('version')) coverCache = Settings.getCoverCacheLocation() if dir_exists(coverCache): try: log("AudioBookCoverCleanup: Checking cache files %s" % coverCache) # Remove the jpg and png files in the directory first dirs, files = xbmcvfs.listdir(coverCache) for aFile in files: log("AudioBookCoverCleanup: Removing file %s" % aFile) if aFile.endswith('.jpg') or aFile.endswith( '.jpeg') or aFile.endswith('.png'): coverFile = os_path_join(coverCache, aFile) xbmcvfs.delete(coverFile) # Now remove the actual directory xbmcvfs.rmdir(coverCache) except: log("AudioBookCoverCleanup: %s" % traceback.format_exc(), xbmc.LOGERROR) xbmcgui.Dialog().ok(ADDON.getLocalizedString(32001), ADDON.getLocalizedString(32009))
def _updateDialogVideoInfo(self): # Get the location of the information dialog XML file dialogXml = os_path_join(self.confpath, 'DialogVideoInfo.xml') log("DialogVideoInfo: Confluence dialog XML file: %s" % dialogXml) # Make sure the file exists (It should always exist) if not xbmcvfs.exists(dialogXml): log("DialogVideoInfo: Unable to find the file DialogVideoInfo.xml, skipping file", xbmc.LOGERROR) self.errorToLog = True return # Load the DialogVideoInfo.xml into a string dialogXmlFile = xbmcvfs.File(dialogXml, 'r') dialogXmlStr = dialogXmlFile.read() dialogXmlFile.close() # Now check to see if the skin file has already had the video extras bits added if 'script.videoextras' in dialogXmlStr: # Already have video extras referenced, so we do not want to do anything else # to this file log("DialogVideoInfo: Video extras already referenced in %s, skipping file" % dialogXml, xbmc.LOGINFO) self.errorToLog = True return # Now add the include link to the file dialogXmlStr = self._addIncludeToXml(dialogXmlStr) # Start by adding the onLoad section previousOnLoad = '<controls>' if previousOnLoad not in dialogXmlStr: # The file has had a standard component deleted, so quit log("DialogVideoInfo: Could not find controls command, skipping file", xbmc.LOGERROR) self.errorToLog = True return # Now add the Video Extras onLoad command after the allowoverlay one DIALOG_VIDEO_INFO_ONLOAD = '<onload condition="System.HasAddon(script.videoextras)">RunScript(script.videoextras,check,"$INFO[ListItem.FilenameAndPath]")</onload>\n\t' insertTxt = DIALOG_VIDEO_INFO_ONLOAD + previousOnLoad dialogXmlStr = dialogXmlStr.replace(previousOnLoad, insertTxt) # Now we need to add the button after the Final button previousButton = '<label>13511</label>' if previousButton not in dialogXmlStr: # The file has had a standard component deleted, so quit log("DialogVideoInfo: Could not find final button, skipping file", xbmc.LOGERROR) self.errorToLog = True return # Check to make sure we use a unique ID value for the button idOK = False idval = 101 while not idOK: idStr = "id=\"%d\"" % idval if idStr not in dialogXmlStr: idOK = True else: idval = idval + 1 # Now add the Video Extras button after the Final one DIALOG_VIDEO_INFO_BUTTON = '''\n\t\t\t\t\t</control>\n\t\t\t\t\t<control type="button" id="%d"> \t\t\t\t\t\t<description>Extras</description> \t\t\t\t\t\t<include>ButtonInfoDialogsCommonValues</include> \t\t\t\t\t\t<label>$ADDON[script.videoextras 32001]</label> \t\t\t\t\t\t<onclick>RunScript(script.videoextras,display,"$INFO[ListItem.FilenameAndPath]")</onclick> \t\t\t\t\t\t<visible>System.HasAddon(script.videoextras) + [Container.Content(movies) | Container.Content(episodes) | Container.Content(TVShows) | Container.Content(musicvideos)] + String.IsEmpty(Window(movieinformation).Property("HideVideoExtrasButton"))</visible>''' insertTxt = previousButton + (DIALOG_VIDEO_INFO_BUTTON % idval) dialogXmlStr = dialogXmlStr.replace(previousButton, insertTxt) # Now add the section for the icon overlay iconPrevious = 'VideoTypeHackFlaggingConditions</include>' if iconPrevious not in dialogXmlStr: log("DialogVideoInfo: Could not find point to add icon overlay, skipping overlay addition", xbmc.LOGERROR) self.errorToLog = True return DIALOG_VIDEO_INFO_ICON = '''\n\t\t\t\t\t<!-- Add the Video Extras Icon --> \t\t\t\t\t<include>VideoExtrasLargeIcon</include> \t\t\t\t</control> \t\t\t\t<control type="grouplist"> \t\t\t\t\t<description>Add the Video Extras Icon</description> \t\t\t\t\t<left>210</left> \t\t\t\t\t<top>480</top> \t\t\t\t\t<width>600</width> \t\t\t\t\t<align>left</align> \t\t\t\t\t<itemgap>2</itemgap> \t\t\t\t\t<orientation>horizontal</orientation> \t\t\t\t\t<include>VisibleFadeEffect</include> \t\t\t\t\t<visible>!Control.IsVisible(50) + Container.Content(tvshows) + !Container.Content(Episodes)</visible> \t\t\t\t\t<include>VideoExtrasLargeIcon</include>''' insertTxt = iconPrevious + DIALOG_VIDEO_INFO_ICON dialogXmlStr = dialogXmlStr.replace(iconPrevious, insertTxt) self._saveNewFile(dialogXml, dialogXmlStr)
def _updateDialogVideoInfo(self): # Get the location of the information dialog XML file dialogXml = os_path_join(self.estuarypath, 'DialogVideoInfo.xml') log("DialogVideoInfo: Estuary dialog XML file: %s" % dialogXml) # Make sure the file exists (It should always exist) if not xbmcvfs.exists(dialogXml): log( "DialogVideoInfo: Unable to find the file DialogVideoInfo.xml, skipping file", xbmc.LOGERROR) self.errorToLog = True return # Load the DialogVideoInfo.xml into a string dialogXmlFile = xbmcvfs.File(dialogXml, 'r') dialogXmlStr = dialogXmlFile.read() dialogXmlFile.close() # Now check to see if the skin file has already had the video extras bits added if 'script.videoextras' in dialogXmlStr: # Already have video extras referenced, so we do not want to do anything else # to this file log( "DialogVideoInfo: Video extras already referenced in %s, skipping file" % dialogXml, xbmc.LOGINFO) self.errorToLog = True return # Start by adding the onLoad section previousOnLoad = '<controls>' if previousOnLoad not in dialogXmlStr: # The file has had a standard component deleted, so quit log( "DialogVideoInfo: Could not find controls command, skipping file", xbmc.LOGERROR) self.errorToLog = True return # Now add the Video Extras onLoad command after the allowoverlay one DIALOG_VIDEO_INFO_ONLOAD = '<onload condition="System.HasAddon(script.videoextras)">RunScript(script.videoextras,check,"$INFO[ListItem.FilenameAndPath]")</onload>\n\t' insertTxt = DIALOG_VIDEO_INFO_ONLOAD + previousOnLoad dialogXmlStr = dialogXmlStr.replace(previousOnLoad, insertTxt) # Now we need to add the button after the Final button previousButton = '<param name="label" value="$VAR[VideoInfoPlayButtonLabelVar]" />' if previousButton not in dialogXmlStr: # The file has had a standard component deleted, so quit log("DialogVideoInfo: Could not find play button, skipping file", xbmc.LOGERROR) self.errorToLog = True return # Check to make sure we use a unique ID value for the button idOK = False idval = 200 while not idOK: idStr = '<param name="id" value="%d"' % idval if idStr not in dialogXmlStr: idOK = True else: idval = idval + 1 # Now add the Video Extras button after the Play one DIALOG_VIDEO_INFO_BUTTON = '''\n\t\t\t\t\t</include>\n\t\t\t\t\t<include content="InfoDialogButton"> \t\t\t\t\t\t<param name="id" value="%d" /> \t\t\t\t\t\t<param name="icon" value="special://masterprofile/../addons/script.videoextras/resources/skins/icons/overlay3.png" /> \t\t\t\t\t\t<param name="label" value="$ADDON[script.videoextras 32001]" /> \t\t\t\t\t\t<param name="onclick_1" value="Action(close)" /> \t\t\t\t\t\t<param name="onclick_2" value="RunScript(script.videoextras,display,$INFO[ListItem.FilenameAndPath])" /> \t\t\t\t\t\t<param name="visible" value="System.HasAddon(script.videoextras) + [String.IsEqual(ListItem.DBType,movie) | String.IsEqual(ListItem.DBType,tvshow) | String.IsEqual(ListItem.DBType,season) | String.IsEqual(ListItem.DBType,episode)] + String.IsEmpty(Window(movieinformation).Property(HideVideoExtrasButton))" />''' insertTxt = previousButton + (DIALOG_VIDEO_INFO_BUTTON % idval) dialogXmlStr = dialogXmlStr.replace(previousButton, insertTxt) self._saveNewFile(dialogXml, dialogXmlStr)
import xbmc import xbmcaddon import xbmcvfs import xbmcgui # Import the common settings from resources.lib.settings import log from resources.lib.settings import os_path_join ADDON = xbmcaddon.Addon(id='script.audiobooks') ######################### # Main ######################### if __name__ == '__main__': log("AudioBookDeleteDb: Delete audiobook database called (version %s)" % ADDON.getAddonInfo('version')) configPath = xbmc.translatePath(ADDON.getAddonInfo('profile')) databasefile = os_path_join(configPath, "audiobooks_database.db") log("AudioBookDeleteDb: Database file location = %s" % databasefile) # If the database file exists, delete it if xbmcvfs.exists(databasefile): xbmcvfs.delete(databasefile) log("AudioBookDeleteDb: Removed database: %s" % databasefile) else: log("AudioBookDeleteDb: No database exists: %s" % databasefile) xbmcgui.Dialog().ok(ADDON.getLocalizedString(32001), ADDON.getLocalizedString(32013))
import xbmc import xbmcaddon import xbmcvfs import xbmcgui # Import the common settings from resources.lib.settings import log from resources.lib.settings import os_path_join ADDON = xbmcaddon.Addon(id='script.game.filmwise') ######################### # Main ######################### if __name__ == '__main__': log("FilmwiseDeleteDb: Delete filmwise database called (version %s)" % ADDON.getAddonInfo('version')) configPath = xbmc.translatePath(ADDON.getAddonInfo('profile')) databasefile = os_path_join(configPath, "filmwise_database.db") log("FilmwiseDeleteDb: Database file location = %s" % databasefile) # If the database file exists, delete it if xbmcvfs.exists(databasefile): xbmcvfs.delete(databasefile) log("FilmwiseDeleteDb: Removed database: %s" % databasefile) else: log("FilmwiseDeleteDb: No database exists: %s" % databasefile) xbmcgui.Dialog().ok(ADDON.getLocalizedString(32001), ADDON.getLocalizedString(32009))
def _updateDialogVideoInfo(self): # Get the location of the information dialog XML file dialogXml = os_path_join(self.estuarypath, 'DialogVideoInfo.xml') log("DialogVideoInfo: Estuary dialog XML file: %s" % dialogXml) # Make sure the file exists (It should always exist) if not xbmcvfs.exists(dialogXml): log( "DialogVideoInfo: Unable to find the file DialogVideoInfo.xml, skipping file", xbmc.LOGERROR) self.errorToLog = True return # Load the DialogVideoInfo.xml into a string dialogXmlFile = xbmcvfs.File(dialogXml, 'r') dialogXmlStr = dialogXmlFile.read() dialogXmlFile.close() # Now check to see if the skin file has already had the tvtunes bits added if 'script.tvtunes' in dialogXmlStr: # Already have tvtunes referenced, so we do not want to do anything else # to this file log( "DialogVideoInfo: TvTunes already referenced in %s, skipping file" % dialogXml, xbmc.LOGINFO) self.errorToLog = True return # Now we need to add the button after the Final button previousButton = '<param name="label" value="$LOCALIZE[13511]" />' if previousButton not in dialogXmlStr: # The file has had a standard component deleted, so quit log("DialogVideoInfo: Could not find final button, skipping file", xbmc.LOGERROR) self.errorToLog = True return # Check to make sure we use a unique ID value for the button idOK = False idval = 201 while not idOK: idStr = '<param name="id" value="%d"' % idval if idStr not in dialogXmlStr: idOK = True else: idval = idval + 1 # Now add the Video Extras button after the Final one DIALOG_VIDEO_INFO_BUTTON = '''\n\t\t\t\t\t</include>\n\t\t\t\t\t<include content="InfoDialogButton"> \t\t\t\t\t\t<param name="id" value="%d" /> \t\t\t\t\t\t<param name="icon" value="icons/sidemenu/musicvideos.png" /> \t\t\t\t\t\t<param name="label" value="$ADDON[script.tvtunes 32105]" /> \t\t\t\t\t\t<param name="onclick_1" value="Action(close)" /> \t\t\t\t\t\t<param name="onclick_2" value="RunScript(script.tvtunes,mode=solo)" /> \t\t\t\t\t\t<param name="visible" value="System.HasAddon(script.tvtunes) + [String.IsEqual(ListItem.DBType,movie) | String.IsEqual(ListItem.DBType,tvshow) | String.IsEqual(ListItem.DBType,season) | String.IsEqual(ListItem.DBType,episode) | String.IsEqual(ListItem.DBType,musicvideo)] + IsEmpty(Window(movieinformation).Property(TvTunes_HideVideoInfoButton))" />''' insertTxt = previousButton + (DIALOG_VIDEO_INFO_BUTTON % idval) dialogXmlStr = dialogXmlStr.replace(previousButton, insertTxt) self._saveNewFile(dialogXml, dialogXmlStr)
def addCustomCollection(self, customXmlFile): log("CollectSets: Checking custom xml file: %s" % customXmlFile) # Try and load the collection file to ensure all the data is correct collectionDetails = self.loadCollection(customXmlFile, False) if collectionDetails in [None, ""]: log("CollectSets: No collection details returned for %s" % customXmlFile) # TODO: Show error return False collectionName = collectionDetails['name'] if collectionName.lower() in [ 'aquarium', 'beach', 'clock', 'fireplace', 'miscellaneous', 'snow', 'space', 'waterfall', 'apple tv' ]: log("CollectSets: Collection name clashes %s" % collectionName) # We return True here, as we have already displayed an error msg = "%s: %s" % (ADDON.getLocalizedString(32084), collectionName) xbmcgui.Dialog().notification(ADDON.getLocalizedString(32005), msg, ICON, 5000, False) return True # check the number of videos if len(collectionDetails['videos']) < 1: log("CollectSets: Collection contains no videos %s" % customXmlFile) # TODO: Show error return False # Check each of the settings for a video, must have name, filename and primary for videoItem in collectionDetails['videos']: if videoItem['name'] in [None, ""]: log("CollectSets: Video without a name in collection %s" % customXmlFile) # TODO: Show error return False if videoItem['filename'] in [None, ""]: log("CollectSets: Video without a filename in collection %s" % customXmlFile) # TODO: Show error return False if videoItem['primary'] in [None, ""]: log("CollectSets: Video without a primary in collection %s" % customXmlFile) # TODO: Show error return False customCollections = self.getCustomCollectionSets() # Add check to see if it clashes with a different custom collection if collectionName in customCollections.keys(): log("CollectSets: Custom collection name clashes %s" % collectionName) # We return True here, as we have already displayed an error msg = "%s: %s" % (ADDON.getLocalizedString(32084), collectionName) xbmcgui.Dialog().notification(ADDON.getLocalizedString(32005), msg, ICON, 5000, False) return True # If we have reached here then we are OK to add the custom set, so take a copy of # it to the addon settings directory finalCustomXmlFile = os_path_join(Settings.getCustomFolder(), os_path_split(customXmlFile)[-1]) log("CollectSets: Copy from %s to %s" % (customXmlFile, finalCustomXmlFile)) copy = xbmcvfs.copy(customXmlFile, finalCustomXmlFile) if copy: # Now get the details that are required for the collection customCollections[collectionName] = { 'name': collectionName, 'filename': finalCustomXmlFile, 'image': collectionDetails['image'], 'default': False } # save the new set of custom collections self.saveCustomCollections(customCollections) return True
# Record if the Context menu should be displayed if Settings.showOnContextMenu(): xbmcgui.Window(10025).setProperty("VideoExtrasShowContextMenu", "true") else: xbmcgui.Window(10025).clearProperty("VideoExtrasShowContextMenu") log("VideoExtrasService: Directory for overlay images is %s" % PROFILE_DIR) # This is a bit of a hack, but we want to force the default paths for the # images if they are not set. This way it will point to the directory containing # all the overlay images to start with, meaning that it will be the directory # shown to the user if they choose to change the icons if ADDON.getSetting("useCustomImages") != "true": if ADDON.getSetting('overlayImage') in [None, '']: skinExtrasOverlay = os_path_join(RES_DIR, "skins") skinExtrasOverlay = os_path_join(skinExtrasOverlay, "icons") skinExtrasOverlay = os_path_join(skinExtrasOverlay, "overlay1.png") ADDON.setSetting('overlayImage', skinExtrasOverlay) if ADDON.getSetting('listImage') in [None, '']: skinExtrasList = os_path_join(RES_DIR, "skins") skinExtrasList = os_path_join(skinExtrasList, "icons") skinExtrasList = os_path_join(skinExtrasList, "list1.png") ADDON.setSetting('listImage', skinExtrasList) # Check the YouTube settings are correct, we will automatically disable the # option if the YouTube addon is not installed checkYouTubeSettings() # Check the Vimeo settings are correct, we will automatically disable the # option if the Vimeo addon is not installed
def _setClassificationList(self, type="", subtype=""): classifications = () securityDetails = {} # Make the call to the DB to get all the specific security settings pinDB = PinSentryDB() if type == MenuNavigator.CLASSIFICATIONS_MOVIES: classifications = Settings.movieCassificationsNames securityDetails = pinDB.getAllMovieClassificationSecurity() elif type == MenuNavigator.CLASSIFICATIONS_TV: classifications = Settings.tvCassificationsNames securityDetails = pinDB.getAllTvClassificationSecurity() del pinDB # Check if we are showing the root classification listing if type in [None, ""]: url = self._build_url({'mode': 'folder', 'foldername': MenuNavigator.CLASSIFICATIONS, 'type': MenuNavigator.CLASSIFICATIONS_MOVIES}) li = xbmcgui.ListItem(ADDON.getLocalizedString(32207), iconImage=ICON) li.setProperty("Fanart_Image", FANART) li.addContextMenuItems([], replaceItems=True) xbmcplugin.addDirectoryItem(handle=self.addon_handle, url=url, listitem=li, isFolder=True) url = self._build_url({'mode': 'folder', 'foldername': MenuNavigator.CLASSIFICATIONS, 'type': MenuNavigator.CLASSIFICATIONS_TV}) li = xbmcgui.ListItem(ADDON.getLocalizedString(32208), iconImage=ICON) li.setProperty("Fanart_Image", FANART) li.addContextMenuItems([], replaceItems=True) xbmcplugin.addDirectoryItem(handle=self.addon_handle, url=url, listitem=li, isFolder=True) elif subtype in [None, ""]: # Get all the different language that are supported languages = [] for classification in classifications: if classification['lang'] not in languages: languages.append(classification['lang']) # Check to see if we can sort all the entries alphabetically for the given language try: languages = sorted(languages, key=ADDON.getLocalizedString) except: # If it fails to sort, then we just list them unsorted log("PinSentryPlugin: Failed to sort language list") # Now print out the item for each language for lang in languages: url = self._build_url({'mode': 'folder', 'foldername': MenuNavigator.CLASSIFICATIONS, 'type': type, 'subtype': str(lang)}) iconImage = ICON for flag in Settings.flags: if flag['lang'] == lang: iconImage = os_path_join(ICON_DIR, flag['icon']) li = xbmcgui.ListItem(ADDON.getLocalizedString(lang), iconImage=iconImage) li.setProperty("Fanart_Image", FANART) li.addContextMenuItems([], replaceItems=True) xbmcplugin.addDirectoryItem(handle=self.addon_handle, url=url, listitem=li, isFolder=True) else: for classification in classifications: # Check if we are looking for a specific country if subtype != str(classification['lang']): continue fullName = classification['name'] % ADDON.getLocalizedString(classification['lang']) idStr = str(classification['id']) securityLevel = 0 if idStr in securityDetails: securityLevel = securityDetails[idStr] log("PinSentryPlugin: Classification %s has security level %d" % (fullName, securityLevel)) # Set the icon to the certificate one if available iconImage = ICON if classification['icon'] not in [None, ""]: iconImage = os_path_join(ICON_DIR, classification['icon']) li = xbmcgui.ListItem(fullName, iconImage=iconImage) # Add a tick if security is set if securityLevel > 0: li.setInfo('video', {'PlayCount': 1}) li.setProperty("Fanart_Image", FANART) li.addContextMenuItems([], replaceItems=True) url = self._build_url({'mode': 'setsecurity', 'type': type, 'id': classification['id'], 'title': classification['match'], 'level': securityLevel}) xbmcplugin.addDirectoryItem(handle=self.addon_handle, url=url, listitem=li, isFolder=False) xbmcplugin.endOfDirectory(self.addon_handle)
def showAudiobooks(self, directory=None): # Get the setting for the audio book directory audioBookFolder = Settings.getAudioBookFolder() if audioBookFolder in [None, ""]: # Prompt the user to set the eBooks Folder audioBookFolder = xbmcgui.Dialog().browseSingle(0, ADDON.getLocalizedString(32005), 'files') # Check to make sure the directory is set now if audioBookFolder in [None, ""]: xbmcgui.Dialog().ok(ADDON.getLocalizedString(32001), ADDON.getLocalizedString(32006)) return # Save the directory in settings for future use log("AudioBooksPlugin: Setting Audio Books folder to %s" % audioBookFolder) Settings.setAudioBookFolder(audioBookFolder) # We may be looking at a subdirectory if directory not in [None, ""]: audioBookFolder = directory dirs, files = xbmcvfs.listdir(audioBookFolder) files.sort() dirs.sort() bookDirs = [] # For each directory list allow the user to navigate into it for adir in dirs: if adir.startswith('.'): continue fullDir = os_path_join(audioBookFolder, adir) # Check if this directory is a book directory if self._isAudioBookDir(fullDir): bookDirs.append(fullDir) continue log("AudioBooksPlugin: Adding directory %s" % adir) try: displayName = "[%s]" % adir.encode("utf-8") except: displayName = "[%s]" % adir try: fullDir = fullDir.encode("utf-8") except: pass url = self._build_url({'mode': 'directory', 'directory': fullDir}) li = xbmcgui.ListItem(displayName, iconImage='DefaultFolder.png') li.setProperty("Fanart_Image", FANART) li.addContextMenuItems([], replaceItems=True) xbmcplugin.addDirectoryItem(handle=self.addon_handle, url=url, listitem=li, isFolder=True) m4bAudioBooks = [] for m4bBookFile in files: # Check to ensure that this is an eBook if not m4bBookFile.lower().endswith('.m4b'): log("AudioBooksPlugin: Skipping non audiobook file: %s" % m4bBookFile) continue fullpath = os_path_join(audioBookFolder, m4bBookFile) m4bAudioBooks.append(fullpath) # Get all the audiobook in a nicely sorted order allAudioBooks = sorted(bookDirs + m4bAudioBooks) audioBookHandlers = [] # Now list all of the books for audioBookFile in allAudioBooks: log("AudioBooksPlugin: Adding audiobook %s" % audioBookFile) audioBookHandlers.append(AudioBookHandler.createHandler(audioBookFile)) # Now sort the list by title audioBookHandlers.sort() # Now list all of the books for audioBookHandler in audioBookHandlers: log("AudioBooksPlugin: Processing audiobook %s" % audioBookHandler.getFile()) title = audioBookHandler.getTitle() coverTargetName = audioBookHandler.getCoverImage(True) isRead = False if Settings.isMarkCompletedItems(): if audioBookHandler.isCompleted(): isRead = True displayString = title try: displayString = title.encode("utf-8") except: displayString = title try: log("AudioBooksPlugin: Display title is %s for %s" % (displayString, audioBookFile)) except: # No need to have an error for logging pass if isRead: displayString = '* %s' % displayString url = self._build_url({'mode': 'chapters', 'filename': audioBookHandler.getFile(True), 'cover': coverTargetName}) li = xbmcgui.ListItem(displayString, iconImage=coverTargetName) li.setProperty("Fanart_Image", FANART) li.addContextMenuItems(self._getContextMenu(audioBookHandler), replaceItems=True) xbmcplugin.addDirectoryItem(handle=self.addon_handle, url=url, listitem=li, isFolder=True) del audioBookHandler xbmcplugin.endOfDirectory(self.addon_handle)
def _updateDialogVideoInfo(self): # Get the location of the information dialog XML file dialogXml = os_path_join(self.estuarypath, 'DialogVideoInfo.xml') log("DialogVideoInfo: Estuary dialog XML file: %s" % dialogXml) # Make sure the file exists (It should always exist) if not xbmcvfs.exists(dialogXml): log("DialogVideoInfo: Unable to find the file DialogVideoInfo.xml, skipping file", xbmc.LOGERROR) self.errorToLog = True return # Load the DialogVideoInfo.xml into a string dialogXmlFile = xbmcvfs.File(dialogXml, 'r') dialogXmlStr = dialogXmlFile.read() dialogXmlFile.close() # Now check to see if the skin file has already had the video extras bits added if 'script.videoextras' in dialogXmlStr: # Already have video extras referenced, so we do not want to do anything else # to this file log("DialogVideoInfo: Video extras already referenced in %s, skipping file" % dialogXml, xbmc.LOGINFO) self.errorToLog = True return # Start by adding the onLoad section previousOnLoad = '<controls>' if previousOnLoad not in dialogXmlStr: # The file has had a standard component deleted, so quit log("DialogVideoInfo: Could not find controls command, skipping file", xbmc.LOGERROR) self.errorToLog = True return # Now add the Video Extras onLoad command after the allowoverlay one DIALOG_VIDEO_INFO_ONLOAD = '<onload condition="System.HasAddon(script.videoextras)">RunScript(script.videoextras,check,"$INFO[ListItem.FilenameAndPath]")</onload>\n\t' insertTxt = DIALOG_VIDEO_INFO_ONLOAD + previousOnLoad dialogXmlStr = dialogXmlStr.replace(previousOnLoad, insertTxt) # Now we need to add the button after the Final button previousButton = '<param name="label" value="$LOCALIZE[208]" />' if previousButton not in dialogXmlStr: # The file has had a standard component deleted, so quit log("DialogVideoInfo: Could not find play button, skipping file", xbmc.LOGERROR) self.errorToLog = True return # Check to make sure we use a unique ID value for the button idOK = False idval = 200 while not idOK: idStr = '<param name="id" value="%d"' % idval if idStr not in dialogXmlStr: idOK = True else: idval = idval + 1 # Now add the Video Extras button after the Play one DIALOG_VIDEO_INFO_BUTTON = '''\n\t\t\t\t\t</include>\n\t\t\t\t\t<include content="InfoDialogButton"> \t\t\t\t\t\t<param name="id" value="%d" /> \t\t\t\t\t\t<param name="icon" value="special://masterprofile/../addons/script.videoextras/resources/skins/icons/overlay3.png" /> \t\t\t\t\t\t<param name="label" value="$ADDON[script.videoextras 32001]" /> \t\t\t\t\t\t<param name="onclick_1" value="Action(close)" /> \t\t\t\t\t\t<param name="onclick_2" value="RunScript(script.videoextras,display,$INFO[ListItem.FilenameAndPath])" /> \t\t\t\t\t\t<param name="visible" value="System.HasAddon(script.videoextras) + [String.IsEqual(ListItem.DBType,movie) | String.IsEqual(ListItem.DBType,tvshow) | String.IsEqual(ListItem.DBType,season) | String.IsEqual(ListItem.DBType,episode)] + IsEmpty(Window(movieinformation).Property(HideVideoExtrasButton))" />''' insertTxt = previousButton + (DIALOG_VIDEO_INFO_BUTTON % idval) dialogXmlStr = dialogXmlStr.replace(previousButton, insertTxt) self._saveNewFile(dialogXml, dialogXmlStr)
ADDON = xbmcaddon.Addon(id='script.audiobooks') ######################### # Main ######################### if __name__ == '__main__': log("AudioBookCoverCleanup: Cover cache cleanup called (version %s)" % ADDON.getAddonInfo('version')) coverCache = Settings.getCoverCacheLocation() if dir_exists(coverCache): try: log("AudioBookCoverCleanup: Checking cache files %s" % coverCache) # Remove the jpg and png files in the directory first dirs, files = xbmcvfs.listdir(coverCache) for aFile in files: log("AudioBookCoverCleanup: Removing file %s" % aFile) if aFile.endswith('.jpg') or aFile.endswith('.jpeg') or aFile.endswith('.png'): coverFile = os_path_join(coverCache, aFile) xbmcvfs.delete(coverFile) # Now remove the actual directory xbmcvfs.rmdir(coverCache) except: log("AudioBookCoverCleanup: %s" % traceback.format_exc(), xbmc.LOGERROR) xbmcgui.Dialog().ok(ADDON.getLocalizedString(32001), ADDON.getLocalizedString(32009))
def getThemes(self): themePath = "" # Only need the theme path for videos if not WindowShowing.isMusicSection(): # Check if the files are stored in a custom path if Settings.isCustomPathEnabled(): if not WindowShowing.isMovies(): videotitle = xbmc.getInfoLabel("ListItem.TVShowTitle") else: videotitle = xbmc.getInfoLabel("ListItem.Title") videotitle = normalize_string(videotitle) themePath = os_path_join(Settings.getCustomPath(), videotitle) # Looking at the TV Show information page elif WindowShowing.isMovieInformation() and ( WindowShowing.isTvShowTitles() or WindowShowing.isTvShows()): themePath = xbmc.getInfoLabel("ListItem.FilenameAndPath") else: themePath = xbmc.getInfoLabel("ListItem.Path") # To try and reduce the amount of "noise" in the logging, where the # same check is logged again and again, we record if it has been # logged for this video, and then do not do it again until the # video changes and what we would print wound be different debug_logging_enabled = False # Only log if something is different from the last time we logged if self.lastLoggedThemePath != themePath: debug_logging_enabled = True self.lastLoggedThemePath = themePath log("TunesBackend: themePath = %s" % themePath, debug_logging_enabled) # Check if the selection is a Movie Set if WindowShowing.isMovieSet(): movieSetMap = self._getMovieSetFileList() if Settings.isCustomPathEnabled(): # Need to make the values part (the path) point to the custom path # rather than the video file for aKey in movieSetMap.keys(): videotitle = normalize_string(aKey) movieSetMap[aKey] = os_path_join(Settings.getCustomPath(), videotitle) if len(movieSetMap) < 1: themefile = ThemeFiles( "", debug_logging_enabled=debug_logging_enabled) else: themefile = ThemeFiles( themePath, movieSetMap.values(), debug_logging_enabled=debug_logging_enabled) # When the reference is into the database and not the file system # then don't return it elif themePath.startswith("videodb:"): # If in either the Tv Show List or the Movie list then # need to stop the theme is selecting the back button if WindowShowing.isMovies() or WindowShowing.isTvShowTitles(): themefile = ThemeFiles( "", debug_logging_enabled=debug_logging_enabled) else: # Load the previous theme themefile = self.newThemeFiles else: if WindowShowing.isMusicSection(): themefile = MusicThemeFiles(debug_logging_enabled) else: themefile = ThemeFiles( themePath, debug_logging_enabled=debug_logging_enabled) # Check if no themes were found for this item, there is a case if it is a # TV Show and it is nested Show-Name/Series-X/Episode-Directory/Episode.ext # Then this will not pick up themes in the root of the TV Show directory if (not themefile.hasThemes()) and ( not Settings.isCustomPathEnabled() ) and WindowShowing.isEpisodes(): tvshowTitle = xbmc.getInfoLabel("ListItem.TVShowTitle") if tvshowTitle not in [None, ""]: try: # Make a call to the database to find out the root path of this TV Show filterStr = '{"operator": "is", "field": "title", "value": "%s"}' % tvshowTitle cmd = '{"jsonrpc": "2.0", "method": "VideoLibrary.GetTVShows", "params": {"properties": ["file"], "filter": %s},"id": 1 }' % filterStr json_query = executeJSONRPC(cmd) json_query = simplejson.loads(json_query) if ("result" in json_query) and ( 'tvshows' in json_query['result']): # Get the path to the TV Show and compare it to where we were previously # looking tvshowList = json_query['result']['tvshows'] if len(tvshowList) == 1: tvshowPath = json_query['result'][ 'tvshows'][0]['file'] # Make sure we have not already checked this path # We will already have checked the parent path as well if (tvshowPath != themePath) and ( tvshowPath != os_path_split(themePath)[0]): # So we know that we haven't checked the root of this TV Show yet log( "TunesBackend: Checking root TV Show Path = %s" % tvshowPath, debug_logging_enabled) themefile = ThemeFiles( tvshowPath, debug_logging_enabled= debug_logging_enabled) except: log( "TunesBackend: Failed to check root TV Show %s" % traceback.format_exc(), debug_logging_enabled) return themefile
def download(self, name, filename, downloadURL): log("VideoScreensaverPlugin: Downloading %s" % name) tmpdestination = os_path_join(Settings.getTempFolder(), filename) destination = os_path_join(Settings.getScreensaverFolder(), filename) # Check to see if there is already a file present if xbmcvfs.exists(destination): useExisting = xbmcgui.Dialog().yesno( ADDON.getLocalizedString(32005), ADDON.getLocalizedString(32301), name, ADDON.getLocalizedString(32302)) if useExisting: # Don't want to overwrite, so nothing to do log("Download: Reusing existing video file %s" % destination) return else: log("Download: Removing existing file %s ready for fresh download" % destination) xbmcvfs.delete(destination) # Create a progress dialog for the download downloadProgressDialog = xbmcgui.DialogProgress() downloadProgressDialog.create(ADDON.getLocalizedString(32303), name, filename, destination) # Callback method to report progress def _report_hook(count, blocksize, totalsize): percent = int(float(count * blocksize * 100) / totalsize) downloadProgressDialog.update(percent, name, filename, destination) if downloadProgressDialog.iscanceled(): log("Download: Operation cancelled") raise ValueError('Download Cancelled') try: log("Download: Using server: %s" % downloadURL) # Now retrieve the actual file fp, h = urllib.urlretrieve(downloadURL, tmpdestination, _report_hook) log(h) # Check to make sure that the file created downloaded correctly st = xbmcvfs.Stat(tmpdestination) fileSize = st.st_size() log("Download: Size of file %s is %d" % (tmpdestination, fileSize)) # Check for something that has a size greater than zero (in case some OSs do not # support looking at the size), but less that 1,000,000 (As all our files are # larger than that if (fileSize > 0) and (fileSize < 1000000): log("Download: Detected that file %s did not download correctly as file size is only %d" % (downloadURL, fileSize)) xbmcgui.Dialog().ok(ADDON.getLocalizedString(32005), ADDON.getLocalizedString(32306)) else: log("Download: Copy from %s to %s" % (tmpdestination, destination)) copy = xbmcvfs.copy(tmpdestination, destination) if copy: log("Download: Copy Successful") else: log("Download: Copy Failed") xbmcvfs.delete(tmpdestination) except ValueError: # This was a cancel by the user, so remove any file that may be part downloaded if xbmcvfs.exists(tmpdestination): xbmcvfs.delete(tmpdestination) except: log("Download: Theme download Failed!!!", xbmc.LOGERROR) log("Download: %s" % traceback.format_exc(), xbmc.LOGERROR) # Make sure the progress dialog has been closed downloadProgressDialog.close() # Now reload the screen to reflect the change xbmc.executebuiltin("Container.Refresh")
def _loadFromFile(self): # Get the videos schedule that is stored in the file scheduleFileName = Settings.getScheduleFile() if scheduleFileName in [None, ""]: log("Schedule: No schedule file set") return log("Schedule: Searching for schedule file: %s" % scheduleFileName) # Return False if file does not exist if not xbmcvfs.exists(scheduleFileName): log("Schedule: No schedule file found: %s" % scheduleFileName) return # Save off the time this file was modified statFile = xbmcvfs.Stat(scheduleFileName) self.lastScheduleModified = statFile.st_mtime() log("Schedule: Reading in schedule file with modify time: %s" % str(self.lastScheduleModified)) # The file exists, so start loading it try: # Need to first load the contents of the file into # a string, this is because the XML File Parse option will # not handle formats like smb:// scheduleFile = xbmcvfs.File(scheduleFileName, 'r') scheduleFileStr = scheduleFile.read() scheduleFile.close() # Create an XML parser scheduleXml = ET.ElementTree(ET.fromstring(scheduleFileStr)) rootElement = scheduleXml.getroot() log("Schedule: Root element is = %s" % rootElement.tag) # Check which format if being used if rootElement.tag == "schedule": log("Schedule: Schedule format file detected") # <schedule> # <rule start="14:24" end="14:37" video="video3.mkv" overlay="WindowFrame1.png" /> # </schedule> # Get the directory that the schedule file is in as this might be needed # if we have local paths in the XML file directory = os_path_split(scheduleFileName)[0] # There could be multiple rule entries, so loop through all of them itemNum = self.idOffset + 1 for ruleElem in scheduleXml.findall('rule'): if ruleElem is not None: videoFile = ruleElem.get('video', None) overlayFile = ruleElem.get('overlay', None) startTime = self._convertTimeToMinutes( ruleElem.get('start', "00:00")) endTime = self._convertTimeToMinutes( ruleElem.get('end', "00:00")) day = self._convertDayFormat(ruleElem.get('day', None)) if (videoFile not in [None, ""]) and (startTime not in [ None, "" ]) and (endTime not in [None, ""]): # Make it a full path if it is not already if videoFile.startswith('..') or ( ("/" not in videoFile) and ("\\" not in videoFile)): videoFile = os_path_join(directory, videoFile) if overlayFile not in [None, ""]: if overlayFile.startswith('..') or ( ("/" not in overlayFile) and ("\\" not in overlayFile)): overlayFile = os_path_join( directory, overlayFile) log("Schedule File: Item %d (Start:%d, End:%d) contains video %s" % (itemNum, startTime, endTime, videoFile)) # Check if the video file exists if os_path_isfile(videoFile): details = { 'id': itemNum, 'start': startTime, 'end': endTime, 'day': day, 'video': videoFile, 'overlay': overlayFile } self.scheduleDetails.append(details) else: log("Schedule: File does not exist: %s" % videoFile) itemNum = itemNum + 1 else: log("Schedule: Unknown schedule file format") del scheduleXml except: log( "Schedule: Failed to process schedule file: %s" % scheduleFileName, xbmc.LOGERROR) log("Schedule: %s" % traceback.format_exc(), xbmc.LOGERROR)
def __init__(self): addonRootDir = xbmc.translatePath('special://profile/addon_data/%s' % ADDON.getAddonInfo('id')) self.collectSetsFile = os_path_join(addonRootDir, 'collectsets.xml') self.disabledVideosFile = os_path_join(addonRootDir, 'disabled.xml')
import xbmc import xbmcaddon import xbmcvfs import xbmcgui # Import the common settings from resources.lib.settings import log from resources.lib.settings import os_path_join ADDON = xbmcaddon.Addon(id="script.audiobooks") ######################### # Main ######################### if __name__ == "__main__": log("AudioBookDeleteDb: Delete audiobook database called (version %s)" % ADDON.getAddonInfo("version")) configPath = xbmc.translatePath(ADDON.getAddonInfo("profile")) databasefile = os_path_join(configPath, "audiobooks_database.db") log("AudioBookDeleteDb: Database file location = %s" % databasefile) # If the database file exists, delete it if xbmcvfs.exists(databasefile): xbmcvfs.delete(databasefile) log("AudioBookDeleteDb: Removed database: %s" % databasefile) else: log("AudioBookDeleteDb: No database exists: %s" % databasefile) xbmcgui.Dialog().ok(ADDON.getLocalizedString(32001), ADDON.getLocalizedString(32013))
def __init__(self): # special://skin - This path points to the currently active skin's root directory. skinExtrasOverlayBase = xbmc.translatePath("special://skin").decode( "utf-8") skinExtrasOverlayBase = os_path_join(skinExtrasOverlayBase, "media") # Now check to see if the user has defines a different overlay image in the # settings, as that is the main one that will be used self.skinExtrasOverlay = Settings.getCustomOverlayImage() self.skinExtrasOverlayList = Settings.getCustomListImage() # Next check the skin specific overlay if self.skinExtrasOverlay in [None, '']: self.skinExtrasOverlay = os_path_join(skinExtrasOverlayBase, "videoextras_overlay.png") if self.skinExtrasOverlayList in [None, '']: self.skinExtrasOverlayList = os_path_join( skinExtrasOverlayBase, "videoextras_overlay_list.png") log("VideoExtrasService: Looking for image overlay file: %s" % self.skinExtrasOverlay) if not xbmcvfs.exists(self.skinExtrasOverlay): log("VideoExtrasService: No custom image, using default") # Add default image setting to skinExtrasOverlay self.skinExtrasOverlay = os_path_join(RES_DIR, "skins") self.skinExtrasOverlay = os_path_join(self.skinExtrasOverlay, "icons") self.skinExtrasOverlay = os_path_join(self.skinExtrasOverlay, "overlay1.png") log("VideoExtrasService: Looking for list image overlay file: %s" % self.skinExtrasOverlayList) if not xbmcvfs.exists(self.skinExtrasOverlayList): log("VideoExtrasService: No custom wide image, using default") # Add default image setting to skinExtrasOverlay self.skinExtrasOverlayList = os_path_join(RES_DIR, "skins") self.skinExtrasOverlayList = os_path_join( self.skinExtrasOverlayList, "icons") self.skinExtrasOverlayList = os_path_join( self.skinExtrasOverlayList, "list1.png") self.forceOverlayOverwrite = False # We now know the file that we are going to use for the overlay # Check to see if this is different from the last overlay file used filename = os_path_join(PROFILE_DIR, "overlay_image_used.txt") try: previousOverlay = None if xbmcvfs.exists(filename): fileHandle = xbmcvfs.File(filename, 'r') previousOverlay = fileHandle.read() fileHandle.close() # Check if the overlay has changed if self.skinExtrasOverlay != previousOverlay: self.forceOverlayOverwrite = True # Update the record of the file we are now using if xbmcvfs.exists(filename): xbmcvfs.delete(filename) fileHandle = xbmcvfs.File(filename, 'w') fileHandle.write(self.skinExtrasOverlay.encode("UTF-8")) fileHandle.close() except: log("VideoExtrasService: Failed to write: %s" % filename, xbmc.LOGERROR) log("VideoExtrasService: %s" % traceback.format_exc(), xbmc.LOGERROR)
def _loadFromFile(self): # Get the videos schedule that is stored in the file scheduleFileName = Settings.getScheduleFile() if scheduleFileName in [None, ""]: log("Schedule: No schedule file set") return log("Schedule: Searching for schedule file: %s" % scheduleFileName) # Return False if file does not exist if not xbmcvfs.exists(scheduleFileName): log("Schedule: No schedule file found: %s" % scheduleFileName) return # Save off the time this file was modified statFile = xbmcvfs.Stat(scheduleFileName) self.lastScheduleModified = statFile.st_mtime() log("Schedule: Reading in schedule file with modify time: %s" % str(self.lastScheduleModified)) # The file exists, so start loading it try: # Need to first load the contents of the file into # a string, this is because the XML File Parse option will # not handle formats like smb:// scheduleFile = xbmcvfs.File(scheduleFileName, 'r') scheduleFileStr = scheduleFile.read() scheduleFile.close() # Create an XML parser scheduleXml = ET.ElementTree(ET.fromstring(scheduleFileStr)) rootElement = scheduleXml.getroot() log("Schedule: Root element is = %s" % rootElement.tag) # Check which format if being used if rootElement.tag == "schedule": log("Schedule: Schedule format file detected") # <schedule> # <rule start="14:24" end="14:37" video="video3.mkv" overlay="WindowFrame1.png" /> # </schedule> # Get the directory that the schedule file is in as this might be needed # if we have local paths in the XML file directory = os_path_split(scheduleFileName)[0] # There could be multiple rule entries, so loop through all of them itemNum = self.idOffset + 1 for ruleElem in scheduleXml.findall('rule'): if ruleElem is not None: videoFile = ruleElem.get('video', None) overlayFile = ruleElem.get('overlay', None) startTime = self._convertTimeToMinutes(ruleElem.get('start', "00:00")) endTime = self._convertTimeToMinutes(ruleElem.get('end', "00:00")) day = self._convertDayFormat(ruleElem.get('day', None)) if (videoFile not in [None, ""]) and (startTime not in [None, ""]) and (endTime not in [None, ""]): # Make it a full path if it is not already if videoFile.startswith('..') or (("/" not in videoFile) and ("\\" not in videoFile)): videoFile = os_path_join(directory, videoFile) if overlayFile not in [None, ""]: if overlayFile.startswith('..') or (("/" not in overlayFile) and ("\\" not in overlayFile)): overlayFile = os_path_join(directory, overlayFile) log("Schedule File: Item %d (Start:%d, End:%d) contains video %s" % (itemNum, startTime, endTime, videoFile)) # Check if the video file exists if os_path_isfile(videoFile): details = {'id': itemNum, 'start': startTime, 'end': endTime, 'day': day, 'video': videoFile, 'overlay': overlayFile} self.scheduleDetails.append(details) else: log("Schedule: File does not exist: %s" % videoFile) itemNum = itemNum + 1 else: log("Schedule: Unknown schedule file format") del scheduleXml except: log("Schedule: Failed to process schedule file: %s" % scheduleFileName, xbmc.LOGERROR) log("Schedule: %s" % traceback.format_exc(), xbmc.LOGERROR)
def _loadNfoInfo(self, directory): # Find out the name of the NFO file nfoFileName = os_path_join(directory, "tvtunes.nfo") # If this is a plugin path, then don't try and get the NFO file if "plugin://" in nfoFileName: log("NfoReader: Plugin paths do not support NFO files: %s" % nfoFileName, self.debug_logging_enabled) return log("NfoReader: Searching for NFO file: %s" % nfoFileName, self.debug_logging_enabled) # Return False if file does not exist if not xbmcvfs.exists(nfoFileName): log("NfoReader: No NFO file found: %s" % nfoFileName, self.debug_logging_enabled) return False returnValue = False checkThemeExists = False try: # Need to first load the contents of the NFO file into # a string, this is because the XML File Parse option will # not handle formats like smb:// nfoFile = xbmcvfs.File(nfoFileName, 'r') nfoFileStr = nfoFile.read() nfoFile.close() # Create an XML parser nfoXml = ET.ElementTree(ET.fromstring(nfoFileStr)) rootElement = nfoXml.getroot() log("NfoReader: Root element is = %s" % rootElement.tag, self.debug_logging_enabled) # Check which format if being used if rootElement.tag == "tvtunes": log("NfoReader: TvTunes format NFO detected", self.debug_logging_enabled) # <tvtunes> # <file>theme.mp3</file> # <directory>c:\my\themes</directory> # <playlistfile>playlist.m3u</playlistfile> # <excludeFromScreensaver/> # </tvtunes> # There could be multiple file entries, so loop through all of them for fileElem in nfoXml.findall('file'): file = None if fileElem is not None: file = fileElem.text if (file is not None) and (file != ""): if file.startswith('..') or (("/" not in file) and ("\\" not in file)): # Make it a full path if it is not already file = os_path_join(directory, file) log("NfoReader: file = %s" % file, self.debug_logging_enabled) self.themeFiles.append(file) # There could be multiple directory entries, so loop through all of them for dirElem in nfoXml.findall('directory'): dir = None if dirElem is not None: dir = dirElem.text if (dir is not None) and (dir != ""): if dir.startswith('..') or (("/" not in dir) and ("\\" not in dir)): # Make it a full path if it is not already dir = os_path_join(directory, dir) log("NfoReader: directory = %s" % dir, self.debug_logging_enabled) self.themeDirs.append(dir) # Check for the playlist files for playlistFileElem in nfoXml.findall('playlistfile'): playlistFile = None if playlistFileElem is not None: playlistFile = playlistFileElem.text self._addFilesFromPlaylist(playlistFile, directory) # Check if this directory should be excluded from the screensaver for playlistFileElem in nfoXml.findall('excludeFromScreensaver'): self.excludeFromScreensaver = True # Check if there may be theme paths that do not exist and we should # check each theme to see if they they can be accessed for playlistFileElem in nfoXml.findall('checkThemeExists'): checkThemeExists = True returnValue = True else: self.displayName = None self.orderKey = None log("NfoReader: Unknown NFO format", self.debug_logging_enabled) del nfoXml except: log("NfoReader: Failed to process NFO: %s" % nfoFileName, True, LOGERROR) log("NfoReader: %s" % traceback.format_exc(), True, LOGERROR) returnValue = False # Not that the entire NFO file has been read, see if we need to verify # that each of the themes exists if checkThemeExists: # Check the theme files to make sure they all exist existingThemeFiles = [] for nfoThemeFile in self.themeFiles: if xbmcvfs.exists(nfoThemeFile): existingThemeFiles.append(nfoThemeFile) else: log("NfoReader: File does not exists, removing %s" % nfoThemeFile, self.debug_logging_enabled) self.themeFiles = existingThemeFiles # Check the theme directories to make sure they all exist existingThemeDir = [] for nfoThemeDir in self.themeDirs: if dir_exists(nfoThemeDir): existingThemeDir.append(nfoThemeDir) else: log("NfoReader: Directory does not exists, removing %s" % nfoThemeDir, self.debug_logging_enabled) self.themeDirs = existingThemeDir return returnValue