def __scan(self, uris, saved):
        """
            Scan music collection for music files
            @param uris as [str]
            @param saved as bool
            @thread safe
        """
        modifications = False
        if self.__history is None:
            self.__history = History()
        mtimes = App().tracks.get_mtimes()
        (new_tracks, new_dirs) = self.__get_objects_for_uris(uris)
        orig_tracks = App().tracks.get_uris()
        was_empty = len(orig_tracks) == 0

        count = len(new_tracks) + len(orig_tracks)
        # Add monitors on dirs
        if self.__inotify is not None:
            for d in new_dirs:
                if d.startswith("file://"):
                    self.__inotify.add_monitor(d)

        i = 0
        # Look for new files/modified file
        SqlCursor.add(App().db)
        try:
            to_add = []
            for uri in new_tracks:
                if self.__thread is None:
                    SqlCursor.remove(App().db)
                    return
                try:
                    GLib.idle_add(self.__update_progress, i, count)
                    f = Gio.File.new_for_uri(uri)
                    # We do not use time::modified because many tag editors
                    # just preserve this setting
                    try:
                        info = f.query_info("time::changed",
                                            Gio.FileQueryInfoFlags.NONE, None)
                        mtime = int(
                            info.get_attribute_as_string("time::changed"))
                    except:  # Fallback for remote fs
                        info = f.query_info("time::modified",
                                            Gio.FileQueryInfoFlags.NONE, None)
                        mtime = int(
                            info.get_attribute_as_string("time::modified"))
                    # If songs exists and mtime unchanged, continue,
                    # else rescan
                    if uri in orig_tracks:
                        orig_tracks.remove(uri)
                        i += 1
                        if not saved or mtime <= mtimes.get(uri, mtime + 1):
                            i += 1
                            continue
                        else:
                            SqlCursor.allow_thread_execution(App().db)
                            self.__del_from_db(uri)
                    # If not saved, use 0 as mtime, easy delete on quit
                    if not saved:
                        mtime = 0
                    # On first scan, use modification time
                    # Else, use current time
                    elif not was_empty:
                        mtime = int(time())
                    to_add.append((uri, mtime))
                except Exception as e:
                    Logger.error("CollectionScanner::__scan(mtime): %s" % e)
            if to_add or orig_tracks:
                modifications = True
            # Clean deleted files
            # Now because we need to populate history
            # Only if we are saving
            if saved:
                for uri in orig_tracks:
                    i += 1
                    GLib.idle_add(self.__update_progress, i, count)
                    self.__del_from_db(uri)
                    SqlCursor.allow_thread_execution(App().db)
            # Add files to db
            for (uri, mtime) in to_add:
                try:
                    Logger.debug("Adding file: %s" % uri)
                    i += 1
                    GLib.idle_add(self.__update_progress, i, count)
                    self.__add2db(uri, mtime)
                    SqlCursor.allow_thread_execution(App().db)
                except Exception as e:
                    Logger.error("CollectionScanner::__scan(add): %s, %s" %
                                 (e, uri))
        except Exception as e:
            Logger.error("CollectionScanner::__scan(): %s" % e)
        SqlCursor.commit(App().db)
        SqlCursor.remove(App().db)
        GLib.idle_add(self.__finish, modifications and saved)
        if not saved:
            self.__play_new_tracks(new_tracks)
        del self.__history
        self.__history = None
Beispiel #2
0
 def __scan_files(self, files, db_uris, scan_type):
     """
         Scan music collection for new audio files
         @param files as [str]
         @param db_uris as [str]
         @param scan_type as ScanType
         @return new track uris as [str]
         @thread safe
     """
     SqlCursor.add(App().db)
     i = 0
     # New tracks present in collection
     new_tracks = []
     # Get mtime of all tracks to detect which has to be updated
     db_mtimes = App().tracks.get_mtimes()
     count = len(files) + 1
     try:
         # Scan new files
         for (mtime, uri) in files:
             # Handle a stop request
             if self.__thread is None and scan_type != ScanType.EPHEMERAL:
                 raise Exception("Scan add cancelled")
             try:
                 if not self.__scan_to_handle(uri):
                     continue
                 if mtime > db_mtimes.get(uri, 0):
                     # If not saved, use 0 as mtime, easy delete on quit
                     if scan_type == ScanType.EPHEMERAL:
                         mtime = 0
                     # Do not use mtime if not intial scan
                     elif db_mtimes:
                         mtime = int(time())
                     Logger.debug("Adding file: %s" % uri)
                     self.__add2db(uri, mtime)
                     SqlCursor.allow_thread_execution(App().db)
                     new_tracks.append(uri)
             except Exception as e:
                 Logger.error("CollectionScanner:: __scan_add_files: % s" %
                              e)
             i += 1
             self.__update_progress(i, count)
         if scan_type != ScanType.EPHEMERAL and self.__thread is not None:
             # We need to check files are always in collections
             if scan_type == ScanType.FULL:
                 collections = App().settings.get_music_uris()
             else:
                 collections = None
             for uri in db_uris:
                 # Handle a stop request
                 if self.__thread is None:
                     raise Exception("Scan del cancelled")
                 in_collection = True
                 if collections is not None:
                     in_collection = False
                     for collection in collections:
                         if collection in uri:
                             in_collection = True
                             break
                 f = Gio.File.new_for_uri(uri)
                 if not in_collection or not f.query_exists():
                     self.del_from_db(uri, True)
                     SqlCursor.allow_thread_execution(App().db)
     except Exception as e:
         Logger.warning("CollectionScanner:: __scan_files: % s" % e)
     SqlCursor.commit(App().db)
     SqlCursor.remove(App().db)
     return new_tracks