Beispiel #1
0
    def _count_files(self) -> int:
        """
        Counts the number of files present in this directory
        """
        count = 0
        for file in common.walk(Gio.File.new_for_uri(self.location)):
            if self.collection:
                if self.collection._scan_stopped:
                    break
            count += 1

        return count
Beispiel #2
0
    def _count_files(self):
        """
            Counts the number of files present in this directory
        """
        count = 0
        for file in common.walk(gio.File(self.location)):
            if self.collection:
                if self.collection._scan_stopped:
                    break
            count += 1

        return count
Beispiel #3
0
    def rescan(self,
               notify_interval: Optional[int] = None,
               force_update: bool = False):  # TODO: What return type?
        """
        Rescan the associated folder and add the contained files
        to the Collection
        """
        # TODO: use gio's cancellable support

        if self.collection is None:
            return True

        if self.scanning:
            return

        logger.info("Scanning library: %s", self.location)
        self.scanning = True
        libloc = Gio.File.new_for_uri(self.location)

        count = 0
        dirtracks = deque()
        compilations = deque()
        ccheck = {}
        for fil in common.walk(libloc):
            count += 1
            type = fil.query_info("standard::type",
                                  Gio.FileQueryInfoFlags.NONE,
                                  None).get_file_type()
            if type == Gio.FileType.DIRECTORY:
                if dirtracks:
                    for tr in dirtracks:
                        self._check_compilation(ccheck, compilations, tr)
                    for (basedir, album) in compilations:
                        base = basedir.replace('"', '\\"')
                        alb = album.replace('"', '\\"')
                        items = [
                            tr for tr in dirtracks
                            if tr.get_tag_raw('__basedir') == base and
                            # FIXME: this is ugly
                            alb in "".join(tr.get_tag_raw('album')
                                           or []).lower()
                        ]
                        for item in items:
                            item.set_tag_raw('__compilation', (basedir, album))
                dirtracks = deque()
                compilations = deque()
                ccheck = {}
            elif type == Gio.FileType.REGULAR:
                tr = self.update_track(fil, force_update=force_update)
                if not tr:
                    continue

                if dirtracks is not None:
                    dirtracks.append(tr)
                    # do this so that if we have, say, a 4000-song folder
                    # we dont get bogged down trying to keep track of them
                    # for compilation detection. Most albums have far fewer
                    # than 110 tracks anyway, so it is unlikely that this
                    # restriction will affect the heuristic's accuracy.
                    # 110 was chosen to accomodate "top 100"-style
                    # compilations.
                    if len(dirtracks) > 110:
                        logger.debug(
                            "Too many files, skipping "
                            "compilation detection heuristic for %s",
                            fil.get_uri(),
                        )
                        dirtracks = None

            if self.collection and self.collection._scan_stopped:
                self.scanning = False
                logger.info("Scan canceled")
                return

            # progress update
            if notify_interval is not None and count % notify_interval == 0:
                event.log_event('tracks_scanned', self, count)

        # final progress update
        if notify_interval is not None:
            event.log_event('tracks_scanned', self, count)

        removals = deque()
        for tr in self.collection.tracks.values():
            tr = tr._track
            loc = tr.get_loc_for_io()
            if not loc:
                continue
            gloc = Gio.File.new_for_uri(loc)
            try:
                if not gloc.has_prefix(libloc):
                    continue
            except UnicodeDecodeError:
                logger.exception("Error decoding file location")
                continue

            if not gloc.query_exists(None):
                removals.append(tr)

        for tr in removals:
            logger.debug("Removing %s", tr)
            self.collection.remove(tr)

        logger.info("Scan completed: %s", self.location)
        self.scanning = False
Beispiel #4
0
    def rescan(self, notify_interval=None):
        """
            Rescan the associated folder and add the contained files
            to the Collection
        """
        # TODO: use gio's cancellable support

        if self.collection is None:
            return True

        if self.scanning:
            return

        logger.info("Scanning library: %s", self.location)
        self.scanning = True
        db = self.collection
        libloc = gio.File(self.location)

        count = 0
        dirtracks = deque()
        compilations = deque()
        ccheck = {}
        for fil in common.walk(libloc):
            count += 1
            type = fil.query_info("standard::type").get_file_type()
            if type == gio.FILE_TYPE_DIRECTORY:
                if dirtracks:
                    for tr in dirtracks:
                        self._check_compilation(ccheck, compilations, tr)
                    for (basedir, album) in compilations:
                        base = basedir.replace('"', '\\"')
                        alb = album.replace('"', '\\"')
                        items = [ tr for tr in dirtracks if \
                                tr.get_tag_raw('__basedir') == base and \
                                # FIXME: this is ugly
                                alb in "".join(
                                    tr.get_tag_raw('album') or []).lower()
                                ]
                        for item in items:
                            item.set_tag_raw('__compilation', (basedir, album))
                dirtracks = deque()
                compilations = deque()
                ccheck = {}
            elif type == gio.FILE_TYPE_REGULAR:
                tr = self.update_track(fil)
                if not tr:
                    continue

                if dirtracks is not None:
                    dirtracks.append(tr)
                    # do this so that if we have, say, a 4000-song folder
                    # we dont get bogged down trying to keep track of them
                    # for compilation detection. Most albums have far fewer
                    # than 110 tracks anyway, so it is unlikely that this
                    # restriction will affect the heuristic's accuracy.
                    # 110 was chosen to accomodate "top 100"-style
                    # compilations.
                    if len(dirtracks) > 110:
                        logger.info("Too many files, skipping "
                                "compilation detection heuristic.")
                        dirtracks = None

            if self.collection and self.collection._scan_stopped:
                self.scanning = False
                logger.info("Scan canceled")
                return

            # progress update
            if notify_interval is not None and count % notify_interval == 0:
                event.log_event('tracks_scanned', self, count)

        # final progress update
        if notify_interval is not None:
            event.log_event('tracks_scanned', self, count)



        removals = deque()
        for tr in self.collection.tracks.itervalues():
            tr = tr._track
            loc = tr.get_loc_for_io()
            if not loc:
                continue
            gloc = gio.File(loc)
            try:
                if not gloc.has_prefix(libloc):
                    continue
            except UnicodeDecodeError:
                common.log_exception(log=logger)
                continue

            if not gloc.query_exists():
                removals.append(tr)

        for tr in removals:
            logger.debug(u"Removing %s"%unicode(tr))
            self.collection.remove(tr)
            
        logger.info("Scan completed: %s", self.location)
        self.scanning = False