def getDirContents(self, directory): """ Return a tuple of sorted rows (directories, playlists, mediaFiles) for the given directory """ playlists = [] mediaFiles = [] directories = [] for (file, path) in tools.listDir(unicode(directory)): # Make directory names prettier junk = ['_'] pretty_name = file for item in junk: pretty_name = pretty_name.replace(item, ' ') if isdir(path): directories.append((icons.dirMenuIcon(), tools.htmlEscape(pretty_name), TYPE_DIR, path)) elif isfile(path): if media.isSupported(file): mediaFiles.append((icons.mediaFileMenuIcon(), tools.htmlEscape(pretty_name), TYPE_FILE, path)) ##elif playlist.isSupported(file): ## playlists.append((icons.mediaFileMenuIcon(), tools.htmlEscape(unicode(file, errors='replace')), TYPE_FILE, path)) # Individually sort each type of file by name playlists.sort(key=self._filename) mediaFiles.sort(key=self._filename) directories.sort(key=self._filename) return (directories, playlists, mediaFiles)
def updateDirNodes(self, parent): """ This generator updates the directory nodes, based on whether they should be expandable """ for child in self.tree.iterChildren(parent): # Only directories need to be updated and since they all come first, # we can stop as soon as we find something else if self.tree.getItem(child, ROW_TYPE) != TYPE_DIR: break # Make sure it's readable directory = self.tree.getItem(child, ROW_FULLPATH) hasContent = False if os.access(directory, os.R_OK | os.X_OK): for (file, path) in tools.listDir(directory): supported = (media.isSupported(file) or playlist.isSupported(file)) if isdir(path) or (isfile(path) and supported): hasContent = True break # Append/remove children if needed if hasContent and self.tree.getNbChildren(child) == 0: self.tree.appendRow((icons.dirMenuIcon(), '', TYPE_NONE, ''), child) elif not hasContent and self.tree.getNbChildren(child) > 0: self.tree.removeAllChildren(child) yield True if parent is not None: self.stopLoading(parent) yield False
def updateDirNodes(self, parent): """ This generator updates the directory nodes, based on whether they should be expandable """ for child in self.tree.iterChildren(parent): # Only directories need to be updated and since they all come first, we can stop as soon as we find something else if self.tree.getItem(child, ROW_TYPE) != TYPE_DIR: break # Make sure it's readable directory = self.tree.getItem(child, ROW_FULLPATH) hasContent = False if os.access(directory, os.R_OK | os.X_OK): for (file, path) in tools.listDir(directory, self.showHiddenFiles): if isdir(path) or (isfile(path) and (media.isSupported(file) or playlist.isSupported(file))): hasContent = True break # Append/remove children if needed if hasContent and self.tree.getNbChildren(child) == 0: self.tree.appendRow((icons.dirMenuIcon(), '', TYPE_NONE, ''), child) elif not hasContent and self.tree.getNbChildren(child) > 0: self.tree.removeAllChildren(child) yield True if parent is not None: self.stopLoading(parent) yield False
def getDirContents(self, directory): """ Return a tuple of sorted rows (directories, playlists, mediaFiles) for the given directory """ playlists = [] mediaFiles = [] directories = [] for (file, path) in tools.listDir(directory, self.showHiddenFiles): if isdir(path): directories.append( (icons.dirMenuIcon(), tools.htmlEscape(unicode(file, errors='replace')), TYPE_DIR, path)) elif isfile(path): if media.isSupported(file): mediaFiles.append( (icons.mediaFileMenuIcon(), tools.htmlEscape(unicode(file, errors='replace')), TYPE_FILE, path)) elif playlist.isSupported(file): playlists.append( (icons.mediaFileMenuIcon(), tools.htmlEscape(unicode(file, errors='replace')), TYPE_FILE, path)) playlists.sort(key=self.sortKey) mediaFiles.sort(key=self.sortKey) directories.sort(key=self.sortKey) return (directories, playlists, mediaFiles)
def scanPaths(dir_info, name='', tracks=None): if tracks is None: tracks = defaultdict(list) for (subname, subpath) in dir_info: if os.path.isdir(subpath): subname = name + ' / ' + subname if name else subname tracks.update(scanPaths(tools.listDir(subpath), subname, tracks)) elif isSupported(subpath): track = getTrackFromFile(subpath) tracks[name].append(track) return tracks
def preloadTracks(paths): ''' Function for preloading tracks. It is invoked when a dnd action starts and preloads the selected tracks in reverse order, so that the tracks are loaded, when the real loading function comes to them. ''' for path in reversed(paths): if os.path.isdir(path): subpaths = [path for (name, path) in tools.listDir(path)] preloadTracks(subpaths) elif isSupported(path): getTrackFromFile(path)
def getUserCover(self, trackPath): """ Check whether a user cover (e.g., cover.jpg) exists in the given directory: * If so, return the path to that file * Otherwise, return None """ userCoverFilenames = prefs.get(__name__, 'user-cover-filenames', PREFS_DFT_USER_COVER_FILENAMES) for (file, path) in tools.listDir(trackPath, True): (name, ext) = os.path.splitext(file.lower()) if ext in ACCEPTED_FILE_FORMATS and name in userCoverFilenames: return path return None
def getTracks(filenames, sortByFilename=True): """ Same as getTracksFromFiles(), but works for any kind of filenames (files, playlists, directories) """ assert type(filenames) == list, 'filenames has to be a list' tracks = TrackDir(flat=True) for path in sorted(filenames): if os.path.isdir(path): dirname = tools.dirname(path) track_dict = scanPaths(tools.listDir(path), name=dirname) for name, track_list in sorted(track_dict.iteritems()): trackdir = TrackDir(name=name) trackdir.tracks = track_list tracks.subdirs.append(trackdir) elif isSupported(path): track = getTrackFromFile(path) tracks.tracks.append(track) return tracks
def getUserCover(self, trackPath): """ Return the path to a cover file in trackPath, None if no cover found """ # Create a dictionary with candidates candidates = {} for (file, path) in tools.listDir(trackPath, True): (name, ext) = os.path.splitext(file.lower()) if ext in ACCEPTED_FILE_FORMATS: candidates[name] = path # Check each possible name using the its index in the list as its priority for name in prefs.get(__name__, 'user-cover-filenames', PREFS_DFT_USER_COVER_FILENAMES): if name in candidates: return candidates[name] if name == '*' and len(candidates) != 0: return next(iter(candidates.values())) return None
def getTracks(filenames, sortByFilename=True): """ Same as getTracksFromFiles(), but works for any kind of filenames (files, playlists, directories) """ assert isinstance(filenames, list), 'filenames has to be a list' tracks = TrackDir(flat=True) for path in sorted(filenames): if os.path.isdir(path): dirname = tools.dirname(path) track_dict = scanPaths(tools.listDir(path), name=dirname) for name, track_list in sorted(track_dict.items()): trackdir = TrackDir(name=name) trackdir.tracks = track_list tracks.subdirs.append(trackdir) elif isSupported(path): track = getTrackFromFile(path) tracks.tracks.append(track) return tracks
def getDirContents(self, directory): """ Return a tuple of sorted rows (directories, playlists, mediaFiles) for the given directory """ playlists = [] mediaFiles = [] directories = [] for (file, path) in tools.listDir(directory, self.showHiddenFiles): if isdir(path): directories.append((icons.dirMenuIcon(), tools.htmlEscape(unicode(file, errors='replace')), TYPE_DIR, path)) elif isfile(path): if media.isSupported(file): mediaFiles.append((icons.mediaFileMenuIcon(), tools.htmlEscape(unicode(file, errors='replace')), TYPE_FILE, path)) elif playlist.isSupported(file): playlists.append((icons.mediaFileMenuIcon(), tools.htmlEscape(unicode(file, errors='replace')), TYPE_FILE, path)) playlists.sort(key=self.sortKey) mediaFiles.sort(key=self.sortKey) directories.sort(key=self.sortKey) return (directories, playlists, mediaFiles)
def refreshLibrary(self, parent, libName, path, creation=False): """ Refresh the given library, must be called through idle_add() """ # First show a progress dialog if creation: header = _('Creating library') else: header = _('Refreshing library') progress = ProgressDlg(parent, header, _('The directory is scanned for media files. This can take some time.\nPlease wait.')) yield True libPath = os.path.join(ROOT_PATH, libName) # Location of the library # If the version number has changed or does not exist, don't reuse any existing file and start from scratch if not os.path.exists(os.path.join(libPath, 'VERSION_%u' % VERSION)): self.__createEmptyLibrary(libName) db = {} # The dictionnary used to create the library queue = collections.deque((path,)) # Faster structure for appending/removing elements mediaFiles = [] # All media files found newLibrary = {} # Reflect the current file structure of the library oldLibrary = pickleLoad(os.path.join(libPath, 'files')) # Previous file structure of the same library # Make sure the root directory still exists if not os.path.exists(path): queue.pop() while len(queue) != 0: currDir = queue.pop() currDirMTime = os.stat(currDir).st_mtime # Retrieve previous information on the current directory, if any if currDir in oldLibrary: oldDirMTime, oldDirectories, oldFiles = oldLibrary[currDir] else: oldDirMTime, oldDirectories, oldFiles = -1, [], {} # If the directory has not been modified, keep old information if currDirMTime == oldDirMTime: files, directories = oldFiles, oldDirectories else: files, directories = {}, [] for (filename, fullPath) in tools.listDir(currDir): if isdir(fullPath): directories.append(fullPath) elif isfile(fullPath) and media.isSupported(filename): if filename in oldFiles: files[filename] = oldFiles[filename] else: files[filename] = [-1, FileTrack(fullPath)] # Determine which files need to be updated for filename, (oldMTime, track) in files.iteritems(): mTime = os.stat(track.getFilePath()).st_mtime if mTime != oldMTime: files[filename] = [mTime, media.getTrackFromFile(track.getFilePath())] newLibrary[currDir] = (currDirMTime, directories, files) mediaFiles.extend([track for mTime, track in files.itervalues()]) queue.extend(directories) # Update the progress dialog try: text = ngettext('Scanning directories (one track found)', 'Scanning directories (%(nbtracks)u tracks found)', len(mediaFiles)) progress.pulse(text % {'nbtracks': len(mediaFiles)}) yield True except progressDlg.CancelledException: progress.destroy() if creation: shutil.rmtree(libPath) yield False # From now on, the process should not be cancelled progress.setCancellable(False) if creation: progress.pulse(_('Creating library...')) else: progress.pulse(_('Refreshing library...')) yield True # Create the database for track in mediaFiles: album = track.getExtendedAlbum() if track.hasAlbumArtist(): artist = track.getAlbumArtist() else: artist = track.getArtist() if artist in db: allAlbums = db[artist] if album in allAlbums: allAlbums[album].append(track) else: allAlbums[album] = [track] else: db[artist] = {album: [track]} progress.pulse() yield True # If an artist name begins with a known prefix, put it at the end (e.g., Future Sound of London (The)) prefixes = prefs.get(__name__, 'prefixes', PREFS_DEFAULT_PREFIXES) for artist in db.keys(): artistLower = artist.lower() for prefix in prefixes: if artistLower.startswith(prefix): db[artist[len(prefix):] + ' (%s)' % artist[:len(prefix)-1]] = db[artist] del db[artist] progress.pulse() yield True # Re-create the library structure on the disk if isdir(libPath): shutil.rmtree(libPath) os.mkdir(libPath) # Put a version number tools.touch(os.path.join(libPath, 'VERSION_%u' % VERSION)) overallNbAlbums = 0 overallNbTracks = 0 overallNbArtists = len(db) # The 'artists' file contains all known artists with their index, the 'files' file contains the file structure of the root path allArtists = sorted([(artist, str(indexArtist), len(db[artist])) for indexArtist, artist in enumerate(db)], key = lambda a: a[0]) pickleSave(os.path.join(libPath, 'files'), newLibrary) pickleSave(os.path.join(libPath, 'artists'), allArtists) for (artist, indexArtist, nbAlbums) in allArtists: artistPath = os.path.join(libPath, indexArtist) overallNbAlbums += nbAlbums os.mkdir(artistPath) albums = [] for index, (name, tracks) in enumerate(db[artist].iteritems()): length = sum([track.getLength() for track in tracks]) overallNbTracks += len(tracks) albums.append((name, str(index), len(tracks), length)) pickleSave(os.path.join(artistPath, str(index)), sorted(tracks, key = lambda track: track.getNumber())) albums.sort(cmp = lambda a1, a2: cmp(db[artist][a1[0]][0], db[artist][a2[0]][0])) pickleSave(os.path.join(artistPath, 'albums'), albums) progress.pulse() yield True self.libraries[libName] = (path, overallNbArtists, overallNbAlbums, overallNbTracks) self.fillLibraryList() if creation: modules.postMsg(consts.MSG_CMD_EXPLORER_ADD, {'modName': MOD_L10N, 'expName': libName, 'icon': None, 'widget': self.scrolled}) progress.destroy() # If the refreshed library is currently displayed, refresh the treeview as well if self.currLib == libName: treeState = self.tree.saveState(ROW_NAME) self.loadLibrary(self.tree, self.currLib) self.tree.restoreState(treeState, ROW_NAME) yield False
def downloadRemarkable(): print(tools.listDir('', s)[0])