Beispiel #1
0
    def _doesThemeExist(self, directory):
        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 if the directory exists before searching
        if dir_exists(directory):
            # Generate the regex
            themeFileRegEx = Settings.getThemeFileRegEx(audioOnly=True)

            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
        return False
Beispiel #2
0
    def __init__(self, extrasParent, videoType=None, title=None):
        log("VideoExtrasBase: Finding extras for %s" % extrasParent)
        self.videoType = videoType
        self.baseDirectory = extrasParent
        if self.baseDirectory.startswith("stack://"):
            self.baseDirectory = self.baseDirectory.split(" , ")[0]
            self.baseDirectory = self.baseDirectory.replace("stack://", "")
        # There is a problem if some-one is using windows shares with
        # \\SERVER\Name as when the addon gets called the first \ gets
        # removed, making an invalid path, so we add it back here
        elif self.baseDirectory.startswith("\\"):
            self.baseDirectory = "\\" + self.baseDirectory

        # 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
        # (A bit of a shame - but that's the way it is)
        fileExt = os.path.splitext(self.baseDirectory)[1]
        # If this is a file, then get it's parent directory
        if fileExt is not None and fileExt != "":
            self.baseDirectory = (os_path_split(self.baseDirectory))[0]
            self.filename = (os_path_split(extrasParent))[1]
        else:
            self.filename = None
        self.title = title
        log("VideoExtrasBase: Root directory: %s" % self.baseDirectory)
Beispiel #3
0
    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))
Beispiel #4
0
    def __init__(self, extrasParent, videoType=None, title=None):
        log("VideoExtrasBase: Finding extras for %s" % extrasParent)
        self.videoType = videoType
        self.baseDirectory = extrasParent
        if self.baseDirectory.startswith("stack://"):
            self.baseDirectory = self.baseDirectory.split(" , ")[0]
            self.baseDirectory = self.baseDirectory.replace("stack://", "")
        # There is a problem if some-one is using windows shares with
        # \\SERVER\Name as when the addon gets called the first \ gets
        # removed, making an invalid path, so we add it back here
        elif self.baseDirectory.startswith("\\"):
            self.baseDirectory = "\\" + self.baseDirectory

        # 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
        # (A bit of a shame - but that's the way it is)
        fileExt = os.path.splitext(self.baseDirectory)[1]
        # If this is a file, then get it's parent directory
        if fileExt is not None and fileExt != "":
            self.baseDirectory = (os_path_split(self.baseDirectory))[0]
            self.filename = (os_path_split(extrasParent))[1]
        else:
            self.filename = None
        self.title = title
        log("VideoExtrasBase: Root directory: %s" % self.baseDirectory)
Beispiel #5
0
    def _doesThemeExist(self, directory):
        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 if the directory exists before searching
        if dir_exists(directory):
            # Generate the regex
            themeFileRegEx = Settings.getThemeFileRegEx(audioOnly=True)

            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
        return False
    def _generateThemeFilelist(self, rawPath):
        # Get the full path with any network alterations
        workingPath = self._getUsablePath(rawPath)

        themeList = self._getThemeFiles(workingPath)

        # If no themes have been found
        if len(themeList) < 1:
            # TV shows stored as ripped disc folders
            if ('VIDEO_TS' in workingPath) or ('BDMV' in workingPath):
                log("ThemeFiles: Found VIDEO_TS or BDMV in path: Correcting the path for DVDR tv shows", self.debug_logging_enabled)
                workingPath = os_path_split(workingPath)[0]
                themeList = self._getThemeFiles(workingPath)
                if len(themeList) < 1:
                    workingPath = os_path_split(workingPath)[0]
                    themeList = self._getThemeFiles(workingPath)
            else:
                # If no theme files were found in this path, look at the parent directory
                workingPath = os_path_split(workingPath)[0]

                # Check for the case where there is the theme forlder settings, we want to
                # check the parent folders themes directory
                if Settings.isThemeDirEnabled():
                    themeDir = os_path_join(workingPath, Settings.getThemeDirectory())
                    themeList = self._getThemeFiles(themeDir)

                # If there are still no themes, just check the parent directory
                if len(themeList) < 1:
                    themeList = self._getThemeFiles(workingPath)

        log("ThemeFiles: Playlist size = %d" % len(themeList), self.debug_logging_enabled)
        log("ThemeFiles: Working Path = %s" % workingPath, self.debug_logging_enabled)

        return themeList
    def _generateThemeFilelist(self, rawPath):
        # Get the full path with any network alterations
        workingPath = self._getUsablePath(rawPath)

        themeList = self._getThemeFiles(workingPath)

        # If no themes have been found
        if len(themeList) < 1:
            # TV shows stored as ripped disc folders
            if ('VIDEO_TS' in workingPath) or ('BDMV' in workingPath):
                log("ThemeFiles: Found VIDEO_TS or BDMV in path: Correcting the path for DVDR tv shows", self.debug_logging_enabled)
                workingPath = os_path_split(workingPath)[0]
                themeList = self._getThemeFiles(workingPath)
                if len(themeList) < 1:
                    workingPath = os_path_split(workingPath)[0]
                    themeList = self._getThemeFiles(workingPath)
            else:
                # If no theme files were found in this path, look at the parent directory
                workingPath = os_path_split(workingPath)[0]

                # Check for the case where there is the theme forlder settings, we want to
                # check the parent folders themes directory
                if Settings.isThemeDirEnabled():
                    themeDir = os_path_join(workingPath, Settings.getThemeDirectory())
                    themeList = self._getThemeFiles(themeDir)

                # If there are still no themes, just check the parent directory
                if len(themeList) < 1:
                    themeList = self._getThemeFiles(workingPath)

        log("ThemeFiles: Playlist size = %d" % len(themeList), self.debug_logging_enabled)
        log("ThemeFiles: Working Path = %s" % workingPath, self.debug_logging_enabled)

        return themeList
Beispiel #8
0
    def findExtras(self,
                   path,
                   filename,
                   exitOnFirst=False,
                   noExtrasDirNeeded=False):
        # Make sure that the path and filename are OK
        try:
            path = path.encode('utf-8')
        except:
            pass
        try:
            filename = filename.encode('utf-8')
        except:
            pass

        # Get the extras that are stored in the extras directory i.e. /Extras/
        files = self._getExtrasDirFiles(path, exitOnFirst, noExtrasDirNeeded)

        # Check if we only want the first entry, in which case exit after
        # we find the first
        if files and (exitOnFirst is True):
            return files

        # Then add the files that have the extras tag in the name i.e. -extras-
        files.extend(self._getExtrasFiles(path, filename, exitOnFirst))

        # Check if we only want the first entry, in which case exit after
        # we find the first
        if files and (exitOnFirst is True):
            return files

        if Settings.isSearchNested():
            # Nested search always needs the extras directory directory
            files.extend(
                self._getNestedExtrasFiles(path, filename, exitOnFirst))
        files.sort()

        # Check if we have found any extras at this point
        if not files:
            # Check if we have a DVD image directory or Bluray image directory
            if (os_path_split(path)[1]
                    == 'VIDEO_TS') or (os_path_split(path)[1] == 'BDMV'):
                log("VideoExtrasFinder: DVD image directory detected, checking = %s"
                    % os_path_split(path)[0])
                # If nesting extras inside a Disc image - always needs an Extras directory
                files = self.findExtras(
                    os_path_split(path)[0], filename, exitOnFirst)
        return files
Beispiel #9
0
    def getCoverImage(filePath, eBookFileName):
        # Check if there is a cached version
        coverTargetName = None
        fullpathLocalImage, bookExt = os.path.splitext(filePath)
        fullpathLocalImage = "%s.jpg" % fullpathLocalImage

        if xbmcvfs.exists(fullpathLocalImage):
            log("EBookBase: Found local cached image %s" % fullpathLocalImage)
            return fullpathLocalImage

        # Check for a cached cover
        coverTargetName = EBookBase.getCachedCover(eBookFileName)

        # If we reach here, then there was no cached cover image, so we need to extract one
        if coverTargetName in [None, ""]:
            ebook = EBookBase.createEBookObject(filePath)
            coverTargetName = ebook.extractCoverImage()
            ebook.tidyUp()
            del ebook

        # If there is still no cover image, check for folder.jpg in the same directory
        if coverTargetName in [None, ""]:
            baseDirectory = (os_path_split(filePath))[0]
            subdirs, filesInDir = xbmcvfs.listdir(baseDirectory)
            for fileInDir in filesInDir:
                if fileInDir.lower() in ['folder.jpg', 'cover.jpg', 'folder.png', 'cover.png']:
                    coverTargetName = os_path_join(baseDirectory, fileInDir)

        return coverTargetName
    def _getExistingCoverImage(self):
        # Check if there is a cached version, or a local one on the drive
        fullpathLocalImage, bookExt = os.path.splitext(self.filePath)

        # Store the directory that the file is in, default the the current path
        parentPath = self.filePath

        # Check to see if this is actually a file with an extension
        if (bookExt not in [None, ""]) and (len(bookExt) < 5):
            fullpathLocalImage1 = "%s.jpg" % fullpathLocalImage
            fullpathLocalImage2 = "%s.JPG" % fullpathLocalImage

            if xbmcvfs.exists(fullpathLocalImage1):
                log("AudioBookHandler: Found local cached image %s" % fullpathLocalImage1)
                return fullpathLocalImage1
            if xbmcvfs.exists(fullpathLocalImage2):
                log("AudioBookHandler: Found local cached image %s" % fullpathLocalImage2)
                return fullpathLocalImage2

            # If we reach here, then we were a file, so get the directory part
            parentPath = (os_path_split(self.filePath))[0]

        # Check for a file in the same directory but with the name
        # "cover.jpg" or "folder.jpg
        dirs, files = xbmcvfs.listdir(parentPath)
        for file in files:
            if file.lower() in ['folder.jpg', 'cover.jpg']:
                fullpathLocalImage = os_path_join(parentPath, file)
                log("AudioBookHandler: Found local directory cover %s" % fullpathLocalImage)
                return fullpathLocalImage

        # Check for a cached cover
        return self._getCachedCover(self.fileName)
Beispiel #11
0
    def _getCustomPathDir(self, path):
        # Get the last element of the path
        pathLastDir = os_path_split(path)[1]

        # Create the path with this added
        custPath = Settings.getCustomPath(self.videoType)
        custPath = os_path_join(custPath, pathLastDir)
        log("VideoExtrasFinder: Checking existence of custom path %s" % custPath)

        # Check if this path exists
        if not dir_exists(custPath):
            # If it doesn't exist, check the path before that, this covers the
            # case where there is a TV Show with each season in it's own directory

            # Make sure we have enough elements to actually navigate back up the path
            if len(os_path_split((os_path_split(path)[0]))) < 2:
                log("VideoExtrasFinder: No parent directories to check %s" % path)
            else:
                path2ndLastDir = os_path_split((os_path_split(path)[0]))[1]
                custPath = Settings.getCustomPath(self.videoType)
                custPath = os_path_join(custPath, path2ndLastDir)
                custPath = os_path_join(custPath, pathLastDir)
                log("VideoExtrasFinder: Checking existence of custom path %s" % custPath)
                if not dir_exists(custPath):
                    # If it still does not exist then check just the 2nd to last path
                    custPath = Settings.getCustomPath(self.videoType)
                    custPath = os_path_join(custPath, path2ndLastDir)
                    log("VideoExtrasFinder: Checking existence of custom path %s" % custPath)

            if not dir_exists(custPath):
                # Some systems will store extras in the custom pass using the name
                # of the TV Show of Movie, so try that
                videoName = self.title
                if self.title in [None, ""]:
                    if self.videoType == Settings.TVSHOWS:
                        videoName = xbmc.getInfoLabel("ListItem.TVShowTitle")
                    else:
                        videoName = xbmc.getInfoLabel("ListItem.Title")
                videoName = normalize_string(videoName)
                # Now construct the path using the movie or TV show title
                custPath = Settings.getCustomPath(self.videoType)
                custPath = os_path_join(custPath, videoName)
                log("VideoExtrasFinder: Checking existence of custom path using title %s" % custPath)
                if not dir_exists(custPath):
                    custPath = None

        return custPath
Beispiel #12
0
    def _getCustomPathDir(self, path):
        # Get the last element of the path
        pathLastDir = os_path_split(path)[1]

        # Create the path with this added
        custPath = Settings.getCustomPath(self.videoType)
        custPath = os_path_join(custPath, pathLastDir)
        log("VideoExtrasFinder: Checking existence of custom path %s" % custPath)

        # Check if this path exists
        if not dir_exists(custPath):
            # If it doesn't exist, check the path before that, this covers the
            # case where there is a TV Show with each season in it's own directory

            # Make sure we have enough elements to actually navigate back up the path
            if len(os_path_split((os_path_split(path)[0]))) < 2:
                log("VideoExtrasFinder: No parent directories to check %s" % path)
            else:
                path2ndLastDir = os_path_split((os_path_split(path)[0]))[1]
                custPath = Settings.getCustomPath(self.videoType)
                custPath = os_path_join(custPath, path2ndLastDir)
                custPath = os_path_join(custPath, pathLastDir)
                log("VideoExtrasFinder: Checking existence of custom path %s" % custPath)
                if not dir_exists(custPath):
                    # If it still does not exist then check just the 2nd to last path
                    custPath = Settings.getCustomPath(self.videoType)
                    custPath = os_path_join(custPath, path2ndLastDir)
                    log("VideoExtrasFinder: Checking existence of custom path %s" % custPath)

            if not dir_exists(custPath):
                # Some systems will store extras in the custom pass using the name
                # of the TV Show of Movie, so try that
                videoName = self.title
                if self.title in [None, ""]:
                    if self.videoType == Settings.TVSHOWS:
                        videoName = xbmc.getInfoLabel("ListItem.TVShowTitle")
                    else:
                        videoName = xbmc.getInfoLabel("ListItem.Title")
                videoName = normalize_string(videoName)
                # Now construct the path using the movie or TV show title
                custPath = Settings.getCustomPath(self.videoType)
                custPath = os_path_join(custPath, videoName)
                log("VideoExtrasFinder: Checking existence of custom path using title %s" % custPath)
                if not dir_exists(custPath):
                    custPath = None

        return custPath
Beispiel #13
0
    def __init__(self, eBookFilePath, removeFileWhenComplete=False):
        log("EBookBase: Loading book %s" % eBookFilePath)
        self.filePath = eBookFilePath
        self.fileName = os_path_split(eBookFilePath)[-1]
        self.isTempBookFile = removeFileWhenComplete

        try:
            self.filePath = self.filePath.decode("utf-8")
        except:
            pass
Beispiel #14
0
    def __init__(self, eBookFilePath, removeFileWhenComplete=False):
        log("EBookBase: Loading book %s" % eBookFilePath)
        self.filePath = eBookFilePath
        self.fileName = os_path_split(eBookFilePath)[-1]
        self.isTempBookFile = removeFileWhenComplete

        try:
            self.filePath = self.filePath.decode("utf-8")
        except:
            pass
Beispiel #15
0
 def __init__(self, audioBookFilePath):
     self.filePath = audioBookFilePath
     self.fileName = os_path_split(audioBookFilePath)[-1]
     self.coverImage = None
     self.title = None
     self.chapters = []
     self.numChapters = 0
     self.position = -1
     self.chapterPosition = -1
     self.totalDuration = -1
     self.isComplete = None
 def __init__(self, audioBookFilePath):
     self.filePath = audioBookFilePath
     self.fileName = os_path_split(audioBookFilePath)[-1]
     self.coverImage = None
     self.title = None
     self.chapters = []
     self.numChapters = 0
     self.position = -1
     self.chapterPosition = -1
     self.totalDuration = -1
     self.isComplete = None
     self.hasArtwork = -1
Beispiel #17
0
    def findExtras(self, path, filename, exitOnFirst=False, noExtrasDirNeeded=False):
        # Make sure that the path and filename are OK
        try:
            path = path.encode('utf-8')
        except:
            pass
        try:
            filename = filename.encode('utf-8')
        except:
            pass

        # Get the extras that are stored in the extras directory i.e. /Extras/
        files = self._getExtrasDirFiles(path, exitOnFirst, noExtrasDirNeeded)

        # Check if we only want the first entry, in which case exit after
        # we find the first
        if files and (exitOnFirst is True):
            return files

        # Then add the files that have the extras tag in the name i.e. -extras-
        files.extend(self._getExtrasFiles(path, filename, exitOnFirst))

        # Check if we only want the first entry, in which case exit after
        # we find the first
        if files and (exitOnFirst is True):
            return files

        if Settings.isSearchNested():
            # Nested search always needs the extras directory directory
            files.extend(self._getNestedExtrasFiles(path, filename, exitOnFirst))
        files.sort()

        # Check if we have found any extras at this point
        if not files:
            # Check if we have a DVD image directory or Bluray image directory
            if (os_path_split(path)[1] == 'VIDEO_TS') or (os_path_split(path)[1] == 'BDMV'):
                log("VideoExtrasFinder: DVD image directory detected, checking = %s" % os_path_split(path)[0])
                # If nesting extras inside a Disc image - always needs an Extras directory
                files = self.findExtras(os_path_split(path)[0], filename, exitOnFirst)
        return files
Beispiel #18
0
    def __init__(self):
        self.baseurl = None
        self.libraryContentsFile = None

        self.tvShowList = []
        self.movieList = []

        # Check if a local theme library is being used
        localThemeLibrary = Settings.getLocalThemeLibrary()
        if localThemeLibrary not in [None, ""]:
            self.libraryContentsFile = localThemeLibrary
            # Set the base of the library to the directory the contents file is in
            self.baseurl = os_path_split(localThemeLibrary)[0]
            # Make sure the last character is a slash
            self.baseurl = os_path_join(self.baseurl, "")
        else:
            # Read the registration file for the library details
            try:
                tvtunesRegStr = "PHR2dHVuZXNTdG9yZVJlZz4gICAgPGNvbmZpZz5odHRwOi8vc2l0ZXMuZ29vZ2xlLmNvbS9zaXRlL3JvYndlYnNldC90dnR1bmVzLXN0b3JlLWNvbmZpZy54bWw8L2NvbmZpZz48L3R2dHVuZXNTdG9yZVJlZz4="

                # Get the library configuration from the registration file
                tvtunesRegET = ET.ElementTree(
                    ET.fromstring(base64.b64decode(tvtunesRegStr)))

                configElem = tvtunesRegET.find('config')
                if configElem is not None:
                    configLocation = configElem.text
                    if configLocation not in [None, ""]:
                        # Read in all the configuration details
                        tvtunesLibraryConfig = urllib2.urlopen(configLocation)
                        tvtunesLibraryConfigStr = tvtunesLibraryConfig.read()
                        # Closes the connection after we have read the configuration
                        try:
                            tvtunesLibraryConfig.close()
                        except:
                            log(
                                "ThemeLibrary: Failed to close connection for library config",
                                xbmc.LOGERROR)

                        tvtunesLibraryET = ET.ElementTree(
                            ET.fromstring(
                                base64.b64decode(tvtunesLibraryConfigStr)))

                        baseUrlElem = tvtunesLibraryET.find('baseurl')
                        if baseUrlElem is not None:
                            self.baseurl = baseUrlElem.text
                        storeContentsElem = tvtunesLibraryET.find(
                            'storecontent')
                        if storeContentsElem is not None:
                            self.libraryContentsFile = storeContentsElem.text
            except:
                log("ThemeLibrary: %s" % traceback.format_exc(), xbmc.LOGERROR)
Beispiel #19
0
    def createEBookObject(filePath):
        localFilePath = filePath
        removeWhenComplete = False
        if filePath.startswith('smb://') or filePath.startswith('nfs://'):
            try:
                # Copy the file to the local disk
                justFileName = os_path_split(filePath)[-1]
                copiedFile = os_path_join(Settings.getTempLocation(), justFileName)
                copy = xbmcvfs.copy(filePath, copiedFile)
                if copy:
                    log("EBookBase: copy successful for %s" % copiedFile)
                    localFilePath = copiedFile
                    removeWhenComplete = True
                else:
                    log("EBookBase: copy failed from %s to %s" % (filePath, copiedFile))
            except:
                log("EBookBase: Failed to copy file %s to local directory" % filePath)

        elif filePath.startswith('http://') or filePath.startswith('https://'):
            log("EBookBase: Book source is %s" % filePath)
            try:
                justFileName = 'opds.epub'
                if '/mobi/' in filePath:
                    justFileName = 'opds.mobi'
                elif '/pdf/' in filePath:
                    justFileName = 'opds.pdf'
                copiedFile = os_path_join(Settings.getTempLocation(), justFileName)
                fp, h = urllib.urlretrieve(filePath, copiedFile)
                log(h)
                localFilePath = copiedFile
                removeWhenComplete = True
            except:
                log("EBookBase: Failed to download file %s to local directory" % filePath)

        bookType = None
        # Check which type of EBook it is
        if localFilePath.lower().endswith('.epub'):
            bookType = EPubEBook(localFilePath, removeWhenComplete)
        elif localFilePath.lower().endswith('.mobi'):
            bookType = MobiEBook(localFilePath, removeWhenComplete)
        elif localFilePath.lower().endswith('.pdf'):
            bookType = PdfEBook(localFilePath, removeWhenComplete)
        else:
            log("EBookBase: Unknown book type for %s (%s)" % (filePath, localFilePath))

        return bookType
Beispiel #20
0
    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
Beispiel #21
0
    def createEBookObject(filePath):
        localFilePath = filePath
        removeWhenComplete = False
        if filePath.startswith('smb://') or filePath.startswith('nfs://'):
            try:
                # Copy the file to the local disk
                justFileName = os_path_split(filePath)[-1]
                copiedFile = os_path_join(Settings.getTempLocation(), justFileName)
                copy = xbmcvfs.copy(filePath, copiedFile)
                if copy:
                    log("EBookBase: copy successful for %s" % copiedFile)
                    localFilePath = copiedFile
                    removeWhenComplete = True
                else:
                    log("EBookBase: copy failed from %s to %s" % (filePath, copiedFile))
            except:
                log("EBookBase: Failed to copy file %s to local directory" % filePath)

        elif filePath.startswith('http://') or filePath.startswith('https://'):
            log("EBookBase: Book source is %s" % filePath)
            try:
                justFileName = 'opds.epub'
                if '/mobi/' in filePath:
                    justFileName = 'opds.mobi'
                elif '/pdf/' in filePath:
                    justFileName = 'opds.pdf'
                copiedFile = os_path_join(Settings.getTempLocation(), justFileName)
                fp, h = urllib.urlretrieve(filePath, copiedFile)
                log(h)
                localFilePath = copiedFile
                removeWhenComplete = True
            except:
                log("EBookBase: Failed to download file %s to local directory" % filePath)

        bookType = None
        # Check which type of EBook it is
        if localFilePath.lower().endswith('.epub'):
            bookType = EPubEBook(localFilePath, removeWhenComplete)
        elif localFilePath.lower().endswith('.mobi'):
            bookType = MobiEBook(localFilePath, removeWhenComplete)
        elif localFilePath.lower().endswith('.pdf'):
            bookType = PdfEBook(localFilePath, removeWhenComplete)
        else:
            log("EBookBase: Unknown book type for %s (%s)" % (filePath, localFilePath))

        return bookType
Beispiel #22
0
    def loadExtras(self, path, filename, exitOnFirst=False):
        # First check to see if there is a videoextras.nfo file
        extradirs, extras = self._getNfoInfo(path)

        if (len(extradirs) > 0) or (len(extras) > 0):
            # There are some extras defined via an NFO file
            extrasList = []
            # Read the extras files from the directories
            for aDir in extradirs:
                extrasList = extrasList + self.findExtras(
                    aDir, filename, exitOnFirst, noExtrasDirNeeded=True)
                # Don't look for more than one if we are only checking for existence of an extra
                if exitOnFirst:
                    break

            # For each of the files, get the directory and filename split
            # and create the extrasItem
            for anExtraFile in extras:
                extraItem = ExtrasItem(os_path_split(anExtraFile)[0],
                                       anExtraFile,
                                       extrasDb=self.extrasDb,
                                       defaultFanArt=self.defaultFanArt)
                extrasList.append(extraItem)
                # Don't look for more than one if we are only checking for existence of an extra
                if exitOnFirst:
                    break

            # Sort the list before returning
            extrasList.sort()
            return extrasList

        # Check if the files are stored in a custom path
        if Settings.isCustomPathEnabled():
            filename = None
            path = self._getCustomPathDir(path)

            if path is None:
                return []
            else:
                log("VideoExtrasFinder: Searching in custom path %s" % path)
        return self.findExtras(
            path,
            filename,
            exitOnFirst,
            noExtrasDirNeeded=Settings.isCustomPathEnabled())
    def _getCopiedFileIfNeeded(self, fullPath):
        copiedFile = None
        if fullPath.startswith('smb://') or fullPath.startswith('nfs://'):
            try:
                # Copy the file to the local disk
                justFileName = os_path_split(fullPath)[-1]
                copiedFile = os_path_join(Settings.getTempLocation(), justFileName)
                copy = xbmcvfs.copy(fullPath, copiedFile)
                if copy:
                    log("AudioBookHandler: copy successful for %s" % copiedFile)
                else:
                    log("AudioBookHandler: copy failed from %s to %s" % (fullPath, copiedFile))
                    copiedFile = None
            except:
                log("AudioBookHandler: Failed to copy file %s to local directory" % fullPath)
                copiedFile = None

        return copiedFile
Beispiel #24
0
    def _getCopiedFileIfNeeded(self, fullPath):
        copiedFile = None
        if fullPath.startswith('smb://') or fullPath.startswith('nfs://'):
            try:
                # Copy the file to the local disk
                justFileName = os_path_split(fullPath)[-1]
                copiedFile = os_path_join(Settings.getTempLocation(), justFileName)
                copy = xbmcvfs.copy(fullPath, copiedFile)
                if copy:
                    log("AudioBookHandler: copy successful for %s" % copiedFile)
                else:
                    log("AudioBookHandler: copy failed from %s to %s" % (fullPath, copiedFile))
                    copiedFile = None
            except:
                log("AudioBookHandler: Failed to copy file %s to local directory" % fullPath)
                copiedFile = None

        return copiedFile
Beispiel #25
0
    def getFanArt(filePath):
        # Check if there is a cached version
        fullpathLocalImage, bookExt = os.path.splitext(filePath)
        fullpathLocalImage = "%s-fanart.jpg" % fullpathLocalImage

        if xbmcvfs.exists(fullpathLocalImage):
            log("EBookBase: Found book fanart image %s" % fullpathLocalImage)
            return fullpathLocalImage

        # Now check if there is a default fanart file
        fanartImage = FANART
        baseDirectory = (os_path_split(filePath))[0]
        subdirs, filesInDir = xbmcvfs.listdir(baseDirectory)
        for fileInDir in filesInDir:
            if fileInDir.lower() in ['fanart.jpg', 'fanart.png']:
                fanartImage = os_path_join(baseDirectory, fileInDir)

        return fanartImage
Beispiel #26
0
    def _getExistingCoverImage(self):
        # Check if there is a cached version, or a local one on the drive
        fullpathLocalImage, bookExt = os.path.splitext(self.filePath)

        # Store the directory that the file is in, default the the current path
        parentPath = self.filePath

        # Check to see if this is actually a file with an extension
        if (bookExt not in [None, ""]) and (len(bookExt) < 5):
            fullpathLocalImage1 = "%s.jpg" % fullpathLocalImage
            fullpathLocalImage2 = "%s.JPG" % fullpathLocalImage
            fullpathLocalImage3 = "%s.png" % fullpathLocalImage
            fullpathLocalImage4 = "%s.PNG" % fullpathLocalImage

            if xbmcvfs.exists(fullpathLocalImage1):
                log("AudioBookHandler: Found local cached image %s" % fullpathLocalImage1)
                return fullpathLocalImage1
            if xbmcvfs.exists(fullpathLocalImage2):
                log("AudioBookHandler: Found local cached image %s" % fullpathLocalImage2)
                return fullpathLocalImage2
            if xbmcvfs.exists(fullpathLocalImage3):
                log("AudioBookHandler: Found local cached image %s" % fullpathLocalImage3)
                return fullpathLocalImage3
            if xbmcvfs.exists(fullpathLocalImage4):
                log("AudioBookHandler: Found local cached image %s" % fullpathLocalImage4)
                return fullpathLocalImage4

            # If we reach here, then we were a file, so get the directory part
            parentPath = (os_path_split(self.filePath))[0]

        # Check for a file in the same directory but with the name
        # "cover.jpg" or "folder.jpg
        dirs, files = xbmcvfs.listdir(parentPath)
        for file in files:
            if file.lower() in ['folder.jpg', 'cover.jpg', 'folder.png', 'cover.png']:
                fullpathLocalImage = os_path_join(parentPath, file)
                log("AudioBookHandler: Found local directory cover %s" % fullpathLocalImage)
                return fullpathLocalImage

        # Check for a cached cover
        return self._getCachedCover(self.fileName)
Beispiel #27
0
    def _getUsablePath(self, rawPath):
        workingPath = rawPath

        # Start by removing the stack details
        if workingPath.startswith("stack://"):
            workingPath = workingPath.replace("stack://", "").split(" , ",
                                                                    1)[0]

        if Settings.isSmbEnabled() and not ('@' in workingPath):
            if workingPath.startswith("smb://"):
                log("### Try authentication share")
                workingPath = workingPath.replace(
                    "smb://", "smb://%s:%s@" %
                    (Settings.getSmbUser(), Settings.getSmbPassword()))
                log("### %s" % workingPath)
            # Also handle the apple format
            elif workingPath.startswith("afp://"):
                log("### Try authentication share")
                workingPath = workingPath.replace(
                    "afp://", "afp://%s:%s@" %
                    (Settings.getSmbUser(), Settings.getSmbPassword()))
                log("### %s" % workingPath)

        # handle episodes stored as rar files
        if workingPath.startswith("rar://"):
            workingPath = workingPath.replace("rar://", "")

        fileExt = None
        if os_path_isfile(workingPath):
            fileExt = os.path.splitext(workingPath)[1]
        # If this is a file, then get it's parent directory
        # Also limit file extensions to a maximum of 4 characters
        if fileExt is not None and fileExt != "" and len(fileExt) < 5:
            workingPath = os_path_split(workingPath)[0]

        # 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]

        return workingPath
    def _generateOrderAndDisplay(self, filename):
        # First thing is to trim the display name from the filename
        # Get just the filename, don't need the full path
        displayName = os_path_split(filename)[1]
        # Remove the file extension (e.g .avi)
        displayName = os.path.splitext(displayName)[0]
        # Remove anything before the -extras- tag (if it exists)
        extrasTag = Settings.getExtrasFileTag()
        if (extrasTag != "") and (extrasTag in displayName):
            justDescription = displayName.split(extrasTag, 1)[1]
            if len(justDescription) > 0:
                displayName = justDescription

        result = (displayName, displayName)
        # Search for the order which will be written as [n]
        # Followed by the display name
        match = re.search("^\[(?P<order>.+)\](?P<Display>.*)", displayName)
        if match:
            orderKey = match.group('order')
            if orderKey != "":
                result = (orderKey, match.group('Display'))
        return result
    def _generateThemeFilelistWithDirs(self, rawPath):
        themeFiles = []
        # Check the theme directory if it is set up
        if Settings.isThemeDirEnabled():
            themeDir = self._getUsablePath(rawPath)
            themeDir = os_path_join(themeDir, Settings.getThemeDirectory())
            themeFiles = self._generateThemeFilelist(themeDir)

        # Check for the case where there is a DVD directory and the themes
        # directory is above it
        if len(themeFiles) < 1:
            if ('VIDEO_TS' in rawPath) or ('BDMV' in rawPath):
                log("ThemeFiles: Found VIDEO_TS in path: Correcting the path for DVDR tv shows", self.debug_logging_enabled)
                themeDir = self._getUsablePath(rawPath)
                themeDir = os_path_split(themeDir)[0]
                themeDir = os_path_join(themeDir, Settings.getThemeDirectory())
                themeFiles = self._generateThemeFilelist(themeDir)

        # If no themes were found in the directory then search the normal location
        if len(themeFiles) < 1:
            themeFiles = self._generateThemeFilelist(rawPath)
        return themeFiles
Beispiel #30
0
    def _generateThemeFilelistWithDirs(self, rawPath):
        themeFiles = []
        # Check the theme directory if it is set up
        if Settings.isThemeDirEnabled():
            themeDir = self._getUsablePath(rawPath)
            themeDir = os_path_join(themeDir, Settings.getThemeDirectory())
            themeFiles = self._generateThemeFilelist(themeDir)

        # Check for the case where there is a DVD directory and the themes
        # directory is above it
        if len(themeFiles) < 1:
            if ('VIDEO_TS' in rawPath) or ('BDMV' in rawPath):
                log("ThemeFiles: Found VIDEO_TS in path: Correcting the path for DVDR tv shows", self.debug_logging_enabled)
                themeDir = self._getUsablePath(rawPath)
                themeDir = os_path_split(themeDir)[0]
                themeDir = os_path_join(themeDir, Settings.getThemeDirectory())
                themeFiles = self._generateThemeFilelist(themeDir)

        # If no themes were found in the directory then search the normal location
        if len(themeFiles) < 1:
            themeFiles = self._generateThemeFilelist(rawPath)
        return themeFiles
Beispiel #31
0
    def _generateOrderAndDisplay(self, filename):
        # First thing is to trim the display name from the filename
        # Get just the filename, don't need the full path
        displayName = os_path_split(filename)[1]
        # Remove the file extension (e.g .avi)
        displayName = os.path.splitext(displayName)[0]
        # Remove anything before the -extras- tag (if it exists)
        extrasTag = Settings.getExtrasFileTag()
        if (extrasTag != "") and (extrasTag in displayName):
            justDescription = displayName.split(extrasTag, 1)[1]
            if len(justDescription) > 0:
                displayName = justDescription

        result = (displayName, displayName)
        # Search for the order which will be written as [n]
        # Followed by the display name
        match = re.search("^\[(?P<order>.+)\](?P<Display>.*)", displayName)
        if match:
            orderKey = match.group('order')
            if orderKey != "":
                result = (orderKey, match.group('Display'))
        return result
Beispiel #32
0
    def _getUsablePath(self, rawPath):
        workingPath = rawPath

        # Start by removing the stack details
        if workingPath.startswith("stack://"):
            workingPath = workingPath.replace("stack://", "").split(" , ", 1)[0]

        if Settings.isSmbEnabled() and not ('@' in workingPath):
            if workingPath.startswith("smb://"):
                log("### Try authentication share")
                workingPath = workingPath.replace("smb://", "smb://%s:%s@" % (Settings.getSmbUser(), Settings.getSmbPassword()))
                log("### %s" % workingPath)
            # Also handle the apple format
            elif workingPath.startswith("afp://"):
                log("### Try authentication share")
                workingPath = workingPath.replace("afp://", "afp://%s:%s@" % (Settings.getSmbUser(), Settings.getSmbPassword()))
                log("### %s" % workingPath)

        # handle episodes stored as rar files
        if workingPath.startswith("rar://"):
            workingPath = workingPath.replace("rar://", "")

        # 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
        # (A bit of a shame - but that's the way it is)
        fileExt = None
        if workingPath.startswith("smb://") or workingPath.startswith("afp://") or os.path.isfile(workingPath):
            fileExt = os.path.splitext(workingPath)[1]
        # If this is a file, then get it's parent directory
        # Also limit file extensions to a maximum of 4 characters
        if fileExt is not None and fileExt != "" and len(fileExt) < 5:
            workingPath = os_path_split(workingPath)[0]

        # 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]

        return workingPath
Beispiel #33
0
    def getFanArt(self):
        baseDirectory = self.filePath
        if self.filePath.lower().endswith('.m4b'):
            # Check if there is a file just for this audiobook
            fullpathLocalImage, bookExt = os.path.splitext(self.filePath)
            fullpathLocalImage = "%s-fanart.jpg" % fullpathLocalImage

            if xbmcvfs.exists(fullpathLocalImage):
                log("AudioBookHandler: Found book fanart image %s" % fullpathLocalImage)
                return fullpathLocalImage

            # Get the name of the directory this file is in
            baseDirectory = (os_path_split(self.filePath))[0]

        # Now check if there is a default fanart file
        fanartImage = FANART
        subdirs, filesInDir = xbmcvfs.listdir(baseDirectory)
        for fileInDir in filesInDir:
            if fileInDir.lower() in ['fanart.jpg', 'fanart.png']:
                fanartImage = os_path_join(baseDirectory, fileInDir)
                break

        return fanartImage
Beispiel #34
0
    def loadExtras(self, path, filename, exitOnFirst=False):
        # First check to see if there is a videoextras.nfo file
        extradirs, extras = self._getNfoInfo(path)

        if (len(extradirs) > 0) or (len(extras) > 0):
            # There are some extras defined via an NFO file
            extrasList = []
            # Read the extras files from the directories
            for aDir in extradirs:
                extrasList = extrasList + self.findExtras(aDir, filename, exitOnFirst, noExtrasDirNeeded=True)
                # Don't look for more than one if we are only checking for existence of an extra
                if exitOnFirst:
                    break

            # For each of the files, get the directory and filename split
            # and create the extrasItem
            for anExtraFile in extras:
                extraItem = ExtrasItem(os_path_split(anExtraFile)[0], anExtraFile, extrasDb=self.extrasDb, defaultFanArt=self.defaultFanArt)
                extrasList.append(extraItem)
                # Don't look for more than one if we are only checking for existence of an extra
                if exitOnFirst:
                    break

            # Sort the list before returning
            extrasList.sort()
            return extrasList

        # Check if the files are stored in a custom path
        if Settings.isCustomPathEnabled():
            filename = None
            path = self._getCustomPathDir(path)

            if path is None:
                return []
            else:
                log("VideoExtrasFinder: Searching in custom path %s" % path)
        return self.findExtras(path, filename, exitOnFirst, noExtrasDirNeeded=Settings.isCustomPathEnabled())
Beispiel #35
0
    def _generateOrderAndDisplay(self, filename):
        # First thing is to trim the display name from the filename
        # Get just the filename, don't need the full path
        displayName = os_path_split(filename)[1]
        # Remove the file extension (e.g .avi)
        displayName = os.path.splitext(displayName)[0]

        # Add path
        orgString, success, tailString = self.directory.rpartition("Extras")
        if not success:
            orgString, success, tailString = self.directory.rpartition("Featurettes")

        if tailString:
            orgString, success, parentString = tailString.rpartition("/")
            if not success:
                orgString, success, parentString = tailString.rpartition("\\")

            displayName = parentString + "\\" + displayName
        else:
            displayName = "\\" + displayName

        # Remove anything before the -extras- tag (if it exists)
        extrasTag = Settings.getExtrasFileTag()
        if (extrasTag != "") and (extrasTag in displayName):
            justDescription = displayName.split(extrasTag, 1)[1]
            if len(justDescription) > 0:
                displayName = justDescription

        result = (displayName, displayName)
        # Search for the order which will be written as [n]
        # Followed by the display name
        match = re.search("^\[(?P<order>.+)\](?P<Display>.*)", displayName)
        if match:
            orderKey = match.group('order')
            if orderKey != "":
                result = (orderKey, match.group('Display'))
        return result
Beispiel #36
0
    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"))

                    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))

                        # 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
                        # (A bit of a shame - but that's the way it is)
                        if videoFile.startswith("smb://") or os_path_isfile(
                                videoFile):
                            details = {
                                'id': itemNum,
                                'start': startTime,
                                'end': endTime,
                                '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)
Beispiel #37
0
    def _runFFmpegCommand(self, inputFileName, coverTargetName=None):
        # Check to see if ffmpeg is enabled
        ffmpeg = Settings.getFFmpegLocation()

        if ffmpeg in [None, ""]:
            log("AudioBookHandler: ffmpeg not enabled")
            return None

        log("AudioBookHandler: ffmpeg location %s" % ffmpeg)
        log("AudioBookHandler: Running ffmpeg for %s" % inputFileName)

        # FFmpeg will not recognise paths that start with smb:// or nfs://
        # These paths are specific to Kodi, so we need to copy the file locally
        # before we can run the FFmpeg command
        copiedFile = None
        fullFileName = inputFileName
        if fullFileName.startswith('smb://') or fullFileName.startswith(
                'nfs://'):
            try:
                # Copy the file to the local disk
                justFileName = os_path_split(fullFileName)[-1]
                copiedFile = os_path_join(Settings.getTempLocation(),
                                          justFileName)
                copy = xbmcvfs.copy(fullFileName, copiedFile)
                if copy:
                    log("AudioBookHandler: copy successful for %s" %
                        copiedFile)
                    fullFileName = copiedFile
                else:
                    log("AudioBookHandler: copy failed from %s to %s" %
                        (fullFileName, copiedFile))
            except:
                log("AudioBookHandler: Failed to copy file %s to local directory"
                    % fullFileName)

        info = None

        # Use ffmpeg to read the audio book and extract all of the details
        startupinfo = None
        if sys.platform.lower() == 'win32':
            # Need to stop the dialog appearing on windows
            startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW

        # Check if we need the image
        coverTempName = None
        if coverTargetName not in [None, '']:
            coverTempName = os_path_join(Settings.getTempLocation(),
                                         'maincover.jpg')
            # Remove the temporary name if it is already there
            if xbmcvfs.exists(coverTempName):
                xbmcvfs.delete(coverTempName)

        try:
            # Generate the ffmpeg command
            ffmpegCmd = [ffmpeg, '-hide_banner', '-y', '-i', fullFileName]

            # Handle non ascii characters in the file name path
            try:
                ffmpegCmd[4] = ffmpegCmd[4].decode('utf-8').encode(
                    locale.getpreferredencoding())
            except:
                log("AudioBookHandler: Failed file system encoding ffmpeg command 1, using default"
                    )
                try:
                    ffmpegCmd[4] = ffmpegCmd[4].encode(
                        locale.getpreferredencoding())
                except:
                    log("AudioBookHandler: Failed file system encoding ffmpeg command 2, using default"
                        )
                    try:
                        ffmpegCmd[4] = ffmpegCmd[4].decode().encode(
                            locale.getpreferredencoding())
                    except:
                        log("AudioBookHandler: Failed file system encoding ffmpeg command 3, using default"
                            )

            # Add the output image to the command line if it is needed
            if coverTempName is not None:
                try:
                    coverTempName = coverTempName.decode('utf-8').encode(
                        locale.getpreferredencoding())
                except:
                    log("AudioBookHandler: Failed file system encoding coverTempName ffmpeg command 1, using default"
                        )
                    try:
                        coverTempName = coverTempName.encode(
                            locale.getpreferredencoding())
                    except:
                        log("AudioBookHandler: Failed file system encoding coverTempName ffmpeg command 2, using default"
                            )
                ffmpegCmd.append(coverTempName)

            # Make the ffmpeg call
            try:
                info = subprocess.check_output(ffmpegCmd,
                                               shell=False,
                                               startupinfo=startupinfo,
                                               stderr=subprocess.STDOUT)
            except subprocess.CalledProcessError as error:
                # This exception will be thrown if ffmpeg prints to STDERR, which it will do if
                # you try and run the command without an output (i.e. image file), but in most
                # cases it does actually have the information we need
                log("AudioBookHandler: CalledProcessError received, processing remaining output"
                    )
                info = error.output
            except:
                # Unfortunately there are still systems that use Python 2.6 which does not
                # have check_output, so it that fails, we just use Popen
                proc = subprocess.Popen(ffmpegCmd,
                                        stdout=subprocess.PIPE,
                                        stderr=subprocess.PIPE,
                                        shell=True)
                info = ""
                for outStr in proc.communicate():
                    if outStr not in [None, ""]:
                        info = "%s%s\n" % (info, outStr)
        except:
            log(
                "AudioBookHandler: Failed to get data using ffmpeg for file %s with error %s"
                % (self.filePath, traceback.format_exc()), xbmc.LOGERROR)

        # If we had to copy the file locally, make sure we delete it
        if copiedFile not in [None, ""]:
            if xbmcvfs.exists(copiedFile):
                xbmcvfs.delete(copiedFile)

        # Check if there is an image in the temporary location
        if coverTempName not in [None, ""]:
            if xbmcvfs.exists(coverTempName):
                # Now move the file to the covers cache directory
                copy = xbmcvfs.copy(coverTempName, coverTargetName)
                if copy:
                    log("AudioBookHandler: copy successful for %s" %
                        coverTargetName)
                else:
                    log("AudioBookHandler: copy failed from %s to %s" %
                        (coverTempName, coverTargetName))

                # Tidy up the image that we actually do not need
                xbmcvfs.delete(coverTempName)

        # Now the command has been run
        ffmpegOutput = None
        if info not in [None, ""]:
            ffmpegOutput = self._processFFmpegOutput(info)

        return ffmpegOutput
    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
Beispiel #39
0
    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 = xbmc.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 _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"))

                    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))

                        # 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
                        # (A bit of a shame - but that's the way it is)
                        if videoFile.startswith("smb://") or os_path_isfile(videoFile):
                            details = {'id': itemNum, 'start': startTime, 'end': endTime, '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 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