Hello community,

here is the log from the commit of package lollypop for openSUSE:Factory 
checked in at 2019-02-01 11:45:51
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/lollypop (Old)
 and      /work/SRC/openSUSE:Factory/.lollypop.new.28833 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "lollypop"

Fri Feb  1 11:45:51 2019 rev:66 rq:669975 version:0.9.916

Changes:
--------
--- /work/SRC/openSUSE:Factory/lollypop/lollypop.changes        2019-01-25 
22:45:14.135089864 +0100
+++ /work/SRC/openSUSE:Factory/.lollypop.new.28833/lollypop.changes     
2019-02-01 11:45:51.632526904 +0100
@@ -1,0 +2,16 @@
+Tue Jan 29 19:57:41 UTC 2019 - antoine.belv...@opensuse.org
+
+- Update to version 0.9.916:
+  * Fix inotify code.
+  * Faster collection scanner.
+
+-------------------------------------------------------------------
+Sat Jan 26 13:14:00 UTC 2019 - antoine.belv...@opensuse.org
+
+- Update to version 0.9.915:
+  * Fix an issue with artist playback (glgo#World/lollypop#1611).
+  * Fix an issue with lyrics (glgo#World/lollypop#1606).
+  * Fix an issue in collection scanner.
+  * Fix an issue with collection history.
+
+-------------------------------------------------------------------

Old:
----
  lollypop-0.9.914.tar.xz

New:
----
  lollypop-0.9.916.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ lollypop.spec ++++++
--- /var/tmp/diff_new_pack.nStfcX/_old  2019-02-01 11:45:52.164526357 +0100
+++ /var/tmp/diff_new_pack.nStfcX/_new  2019-02-01 11:45:52.164526357 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           lollypop
-Version:        0.9.914
+Version:        0.9.916
 Release:        0
 Summary:        GNOME music playing application
 License:        GPL-3.0-or-later

++++++ _service ++++++
--- /var/tmp/diff_new_pack.nStfcX/_old  2019-02-01 11:45:52.192526329 +0100
+++ /var/tmp/diff_new_pack.nStfcX/_new  2019-02-01 11:45:52.192526329 +0100
@@ -1,7 +1,7 @@
 <services>
   <service mode="disabled" name="tar_scm">
     <param name="changesgenerate">enable</param>
-    <param name="revision">0.9.914</param>
+    <param name="revision">0.9.916</param>
     <param name="scm">git</param>
     <param name="url">https://gitlab.gnome.org/World/lollypop.git</param>
     <param name="versionformat">@PARENT_TAG@</param>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.nStfcX/_old  2019-02-01 11:45:52.204526316 +0100
+++ /var/tmp/diff_new_pack.nStfcX/_new  2019-02-01 11:45:52.208526312 +0100
@@ -1,4 +1,4 @@
 <servicedata>
 <service name="tar_scm">
                 <param 
name="url">https://gitlab.gnome.org/World/lollypop.git</param>
-              <param 
name="changesrevision">ddb232d9eb8d91917e3eb12192f1006d1f498990</param></service></servicedata>
\ No newline at end of file
+              <param 
name="changesrevision">8a6b84f0bd565d1d764aadc29de3fa61a78df335</param></service></servicedata>
\ No newline at end of file

++++++ lollypop-0.9.914.tar.xz -> lollypop-0.9.916.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-0.9.914/data/application.css 
new/lollypop-0.9.916/data/application.css
--- old/lollypop-0.9.914/data/application.css   2019-01-23 19:00:51.000000000 
+0100
+++ new/lollypop-0.9.916/data/application.css   2019-01-29 07:05:19.000000000 
+0100
@@ -57,6 +57,7 @@
 
 .progress-bottom {
     border: none;
+    border-radius: 0px;
     background-color: transparent;
     background-image: none;
     padding-top: 0px;
@@ -69,11 +70,13 @@
     background-color: @theme_selected_bg_color;
     background-image: none;
     border: none;
+    border-radius: 0px;
     min-height: 6px;
 }
 
 .progress-bottom trough {
     border: none;
+    border-radius: 0px;
     background-color: transparent;
     background-image: none;
     min-height: 6px;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lollypop-0.9.914/data/org.gnome.Lollypop.appdata.xml.in 
new/lollypop-0.9.916/data/org.gnome.Lollypop.appdata.xml.in
--- old/lollypop-0.9.914/data/org.gnome.Lollypop.appdata.xml.in 2019-01-23 
19:00:51.000000000 +0100
+++ new/lollypop-0.9.916/data/org.gnome.Lollypop.appdata.xml.in 2019-01-29 
07:05:19.000000000 +0100
@@ -27,9 +27,10 @@
     </ul>
   </description>
   <releases>
-    <release version="0.9.913" date="2019-01-23">
+    <release version="0.9.916" date="2019-01-28">
       <description>
-        <ul>Fix issues in collection scanner</ul>
+        <ul>Fix inotify code</ul>
+        <ul>Faster collection scanner</ul>
       </description>
     </release>
   </releases>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-0.9.914/lollypop/application.py 
new/lollypop-0.9.916/lollypop/application.py
--- old/lollypop-0.9.914/lollypop/application.py        2019-01-23 
19:00:51.000000000 +0100
+++ new/lollypop-0.9.916/lollypop/application.py        2019-01-29 
07:05:19.000000000 +0100
@@ -38,7 +38,7 @@
 from lollypop.utils import set_proxy_from_gnome
 from lollypop.application_actions import ApplicationActions
 from lollypop.utils import is_audio, is_pls
-from lollypop.define import Type, LOLLYPOP_DATA_PATH
+from lollypop.define import Type, LOLLYPOP_DATA_PATH, ScanType
 from lollypop.window import Window
 from lollypop.database import Database
 from lollypop.player import Player
@@ -472,7 +472,7 @@
         """
         def scanner_update():
             self.__scanner_timeout_id = None
-            self.scanner.update(self.__scanner_uris, False)
+            self.scanner.update(ScanType.EPHEMERAL, self.__scanner_uris)
             self.__scanner_uris = []
 
         if self.__scanner_timeout_id is not None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-0.9.914/lollypop/application_actions.py 
new/lollypop-0.9.916/lollypop/application_actions.py
--- old/lollypop-0.9.914/lollypop/application_actions.py        2019-01-23 
19:00:51.000000000 +0100
+++ new/lollypop-0.9.916/lollypop/application_actions.py        2019-01-29 
07:05:19.000000000 +0100
@@ -12,7 +12,7 @@
 
 from gi.repository import Gio, GLib, Gtk
 
-from lollypop.define import App
+from lollypop.define import App, ScanType
 from lollypop.settings import SettingsDialog
 
 
@@ -72,7 +72,7 @@
         """
         if App().window:
             App().task_helper.run(App().art.clean_all_cache)
-            App().scanner.update()
+            App().scanner.update(ScanType.FULL)
 
     def __on_about_activate_response(self, dialog, response_id):
         """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-0.9.914/lollypop/collectionscanner.py 
new/lollypop-0.9.916/lollypop/collectionscanner.py
--- old/lollypop-0.9.914/lollypop/collectionscanner.py  2019-01-23 
19:00:51.000000000 +0100
+++ new/lollypop-0.9.916/lollypop/collectionscanner.py  2019-01-29 
07:05:19.000000000 +0100
@@ -24,7 +24,7 @@
 from time import time
 
 from lollypop.inotify import Inotify
-from lollypop.define import App, Type
+from lollypop.define import App, Type, ScanType
 from lollypop.objects import Track, Album
 from lollypop.sqlcursor import SqlCursor
 from lollypop.tagreader import TagReader
@@ -67,30 +67,31 @@
             self.__inotify = None
         App().albums.update_max_count()
 
-    def update(self, uris=[], saved=True):
+    def update(self, scan_type, uris=[]):
         """
             Update database
+            @param scan_type as ScanType
             @param uris as [str]
-            @param saved as bool
         """
+        App().lookup_action("update_db").set_enabled(False)
         # Stop previous scan
-        if self.is_locked():
+        if self.is_locked() and scan_type != ScanType.EPHEMERAL:
             self.stop()
-            GLib.timeout_add(250, self.update, uris, saved)
+            GLib.timeout_add(250, self.update, scan_type, uris)
         else:
             self.__disable_compilations = not App().settings.get_value(
                 "show-compilations")
 
-            if not uris:
+            if scan_type == ScanType.FULL:
                 uris = App().settings.get_music_uris()
-                if not uris:
-                    return
-
+            if not uris:
+                return
             # Register to progressbar
-            App().window.container.progress.add(self)
-            App().window.container.progress.set_fraction(0, self)
+            if scan_type != ScanType.EPHEMERAL:
+                App().window.container.progress.add(self)
+                App().window.container.progress.set_fraction(0, self)
             # Launch scan in a separate thread
-            self.__thread = Thread(target=self.__scan, args=(uris, saved))
+            self.__thread = Thread(target=self.__scan, args=(scan_type, uris))
             self.__thread.daemon = True
             self.__thread.start()
 
@@ -114,13 +115,16 @@
             Update progress bar status
             @param scanned items as int, total items as int
         """
-        App().window.container.progress.set_fraction(current / total, self)
+        GLib.idle_add(App().window.container.progress.set_fraction,
+                      current / total,
+                      self)
 
     def __finish(self, modifications):
         """
             Notify from main thread when scan finished
             @param modifications as bool
         """
+        App().lookup_action("update_db").set_enabled(True)
         App().window.container.progress.set_fraction(1.0, self)
         self.stop()
         self.emit("scan-finished", modifications)
@@ -145,11 +149,12 @@
                 self.__inotify.add_monitor(d)
 
     @profile
-    def __get_objects_for_uris(self, uris):
+    def __get_objects_for_uris(self, scan_type, uris):
         """
             Get all tracks and dirs in uris
+            @param scan_type as ScanType
             @param uris as string
-            @return (tracks as [mtime: int, uri: str], dirs as [uri: str])
+            @return (tracks [mtimes: int, uri: str], dirs as [uri: str])
         """
         files = []
         dirs = []
@@ -178,6 +183,7 @@
                         else:
                             mtime = get_mtime(info)
                             files.append((mtime, child_uri))
+                # Only happens if files passed as args
                 else:
                     mtime = get_mtime(info)
                     files.append((mtime, uri))
@@ -188,36 +194,43 @@
         return (files, dirs)
 
     @profile
-    def __scan(self, uris, saved):
+    def __scan(self, scan_type, uris):
         """
             Scan music collection for music files
+            @param scan_type as ScanType
             @param uris as [str]
-            @param saved as bool
             @thread safe
         """
-        if self.__history is None:
+        if scan_type != ScanType.EPHEMERAL and self.__history is None:
             self.__history = History()
 
-        (files, dirs) = self.__get_objects_for_uris(uris)
+        (files, dirs) = self.__get_objects_for_uris(scan_type, uris)
 
-        new_tracks = self.__scan_files(files, saved)
-        self.__add_monitor(dirs)
+        if scan_type == ScanType.NEW_FILES:
+            db_uris = App().tracks.get_uris(uris)
+        else:
+            db_uris = App().tracks.get_uris()
+        new_tracks = self.__scan_files(files, db_uris, scan_type)
 
-        GLib.idle_add(self.__finish, new_tracks and saved)
+        if scan_type != ScanType.EPHEMERAL:
+            self.__add_monitor(dirs)
+            GLib.idle_add(self.__finish, new_tracks)
 
-        if not saved and self.__thread is not None:
+        if scan_type == ScanType.EPHEMERAL:
             self.__play_new_tracks(new_tracks)
 
-        del self.__history
-        self.__history = None
+        if scan_type != ScanType.EPHEMERAL:
+            del self.__history
+            self.__history = None
 
-    def __scan_to_handle(self, f):
+    def __scan_to_handle(self, uri):
         """
             Check if file has to be handle by scanner
             @param f as Gio.File
             @return bool
         """
         try:
+            f = Gio.File.new_for_uri(uri)
             # Scan file
             if is_pls(f):
                 # Handle playlist
@@ -230,77 +243,57 @@
             Logger.error("CollectionScanner::__scan_to_handle(): %s" % e)
         return False
 
-    def __scan_add(self, uri, mtime):
-        """
-            Add audio file to database
-            @param uri as str
-            @param mtime as float
-        """
-        try:
-            Logger.debug("Adding file: %s" % uri)
-            self.__add2db(uri, mtime)
-            SqlCursor.allow_thread_execution(App().db)
-        except Exception as e:
-            Logger.error("CollectionScanner::__scan_add(add): "
-                         "%s, %s" % (e, uri))
-
-    def __scan_del(self, uri):
-        """
-            Delete file from DB
-            @param uri as str
-        """
-        try:
-            self.__del_from_db(uri)
-            SqlCursor.allow_thread_execution(App().db)
-        except Exception as e:
-            Logger.error("CollectionScanner::__scan_del: %s" % e)
-
     @profile
-    def __scan_files(self, files, saved):
+    def __scan_files(self, files, db_uris, scan_type):
         """
             Scan music collection for new audio files
-            @param files as [(int, str)]
+            @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
-        mtimes = App().tracks.get_mtimes()
-        # Get uris of all tracks to detect which has to be deleted
-        to_delete = App().tracks.get_uris()
-        SqlCursor.add(App().db)
+        db_mtimes = App().tracks.get_mtimes()
+        count = len(files) + 1
         try:
-            count = len(files)
-            i = 0
-            while files:
+            # Scan new files
+            for (mtime, uri) in files:
                 # Handle a stop request
-                if self.__thread is None:
-                    raise Exception("Scan cancelled")
+                if self.__thread is None and scan_type != ScanType.EPHEMERAL:
+                    raise Exception("Scan add cancelled")
                 try:
-                    (mtime, uri) = files.pop(0)
-                    f = Gio.File.new_for_uri(uri)
-                    already_in_db = uri in to_delete
-                    if already_in_db:
-                        to_delete.remove(uri)
-                    if mtime > mtimes.get(uri, 0):
-                        handled = self.__scan_to_handle(f)
-                        if handled:
-                            # On first scan, we want file mtime
-                            mtime = int(time()) if mtimes else mtime
-                            # If not saved, use 0 as mtime, easy delete on quit
-                            if already_in_db:
-                                self.__scan_del(uri)
-                            self.__scan_add(uri, mtime if saved else 0)
-                            new_tracks.append(uri)
+                    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_files: % s" % e)
+                               "CollectionScanner:: __scan_add_files: % s" % e)
                 i += 1
-                GLib.idle_add(self.__update_progress, i, count)
-            # This files are not in collection anymore
-            if saved:
-                for uri in to_delete:
-                    self.__scan_del(uri)
+                self.__update_progress(i, count)
+            if scan_type != ScanType.EPHEMERAL and self.__thread is not None:
+                for uri in db_uris:
+                    # Handle a stop request
+                    if self.__thread is None:
+                        raise Exception("Scan del cancelled")
+                    f = Gio.File.new_for_uri(uri)
+                    if not f.query_exists():
+                        self.__del_from_db(uri)
+                        SqlCursor.allow_thread_execution(App().db)
         except Exception as e:
             Logger.warning("CollectionScanner:: __scan_files: % s" % e)
         SqlCursor.commit(App().db)
@@ -358,9 +351,25 @@
 
         Logger.debug("CollectionScanner::add2db(): Restore stats")
         # Restore stats
-        (track_pop, track_rate, track_ltime, album_mtime,
-         track_loved, album_loved, album_pop, album_rate) = self.__history.get(
-            name, duration)
+        track_id = App().tracks.get_id_by_uri(uri)
+        if track_id is None:
+            basename = f.get_basename()
+            track_id = App().tracks.get_id_by_basename_duration(basename,
+                                                                duration)
+        # Restore from history
+        if self.__history is None:
+            (track_pop, track_rate, track_ltime,
+             album_mtime, track_loved, album_loved,
+             album_pop, album_rate) = (0, 0, 0, 0, False, False, 0, 0)
+        elif track_id is None:
+            (track_pop, track_rate, track_ltime,
+             album_mtime, track_loved, album_loved,
+             album_pop, album_rate) = self.__history.get(name, duration)
+        # Delete track and restore from it
+        else:
+            (track_pop, track_rate, track_ltime,
+             album_mtime, track_loved, album_loved,
+             album_pop, album_rate) = self.__del_from_db(uri)
         # If nothing in stats, use track mtime
         if album_mtime == 0:
             album_mtime = mtime
@@ -414,28 +423,24 @@
         """
             Delete track from db
             @param uri as str
+            @return (popularity, ltime, mtime,
+                     loved album, album_popularity)
         """
         try:
-            f = Gio.File.new_for_uri(uri)
-            name = f.get_basename()
             track_id = App().tracks.get_id_by_uri(uri)
             album_id = App().tracks.get_album_id(track_id)
             genre_ids = App().tracks.get_genre_ids(track_id)
             album_artist_ids = App().albums.get_artist_ids(album_id)
             artist_ids = App().tracks.get_artist_ids(track_id)
-            popularity = App().tracks.get_popularity(track_id)
-            rate = App().tracks.get_rate(track_id)
-            ltime = App().tracks.get_ltime(track_id)
-            mtime = App().tracks.get_mtime(track_id)
-            loved_track = App().tracks.get_loved(track_id)
-            duration = App().tracks.get_duration(track_id)
-            album_popularity = App().albums.get_popularity(album_id)
+            track_pop = App().tracks.get_popularity(track_id)
+            track_rate = App().tracks.get_rate(track_id)
+            track_ltime = App().tracks.get_ltime(track_id)
+            album_mtime = App().tracks.get_mtime(track_id)
+            track_loved = App().tracks.get_loved(track_id)
+            album_pop = App().albums.get_popularity(album_id)
             album_rate = App().albums.get_rate(album_id)
-            loved_album = App().albums.get_loved(album_id)
+            album_loved = App().albums.get_loved(album_id)
             uri = App().tracks.get_uri(track_id)
-            self.__history.add(name, duration, popularity, rate,
-                               ltime, mtime, loved_track, loved_album,
-                               album_popularity, album_rate)
             App().tracks.remove(track_id)
             App().tracks.clean(track_id)
             cleaned = App().albums.clean(album_id)
@@ -445,16 +450,17 @@
                               album_id, True)
             for artist_id in album_artist_ids + artist_ids:
                 cleaned = App().artists.clean(artist_id)
-                # Force update even if not cleaned as artist may
-                # have been removed from a selected genre
-                GLib.idle_add(self.emit, "artist-updated",
-                              artist_id, False)
+                if cleaned:
+                    GLib.idle_add(self.emit, "artist-updated",
+                                  artist_id, False)
             for genre_id in genre_ids:
                 cleaned = App().genres.clean(genre_id)
                 if cleaned:
                     SqlCursor.commit(App().db)
                     GLib.idle_add(self.emit, "genre-updated",
                                   genre_id, False)
+            return (track_pop, track_rate, track_ltime, album_mtime,
+                    track_loved, album_loved, album_pop, album_rate)
         except Exception as e:
             Logger.error("CollectionScanner::__del_from_db: %s" % e)
 
@@ -485,8 +491,9 @@
                     album_artist_ids = new_artist_ids
                 App().albums.set_artist_ids(album_id, new_artist_ids)
         # Update UI based on previous artist calculation
-        for artist_id in album_artist_ids:
-            GLib.idle_add(self.emit, "artist-updated", artist_id, add)
+        if App().albums.get_tracks_count(album_id) > 1:
+            for artist_id in album_artist_ids:
+                GLib.idle_add(self.emit, "artist-updated", artist_id, add)
         # Update album genres
         for genre_id in genre_ids:
             App().albums.add_genre(album_id, genre_id)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-0.9.914/lollypop/database_tracks.py 
new/lollypop-0.9.916/lollypop/database_tracks.py
--- old/lollypop-0.9.914/lollypop/database_tracks.py    2019-01-23 
19:00:51.000000000 +0100
+++ new/lollypop-0.9.916/lollypop/database_tracks.py    2019-01-29 
07:05:19.000000000 +0100
@@ -144,6 +144,22 @@
                 return v[0]
             return None
 
+    def get_id_by_basename_duration(self, basename, duration):
+        """
+            Get track id by basename
+            @param basename as str
+            @param duration as int
+            @return track_id as int
+        """
+        with SqlCursor(App().db) as sql:
+            result = sql.execute("SELECT rowid FROM tracks\
+                                  WHERE uri like ? AND duration=?",
+                                 ("%" + basename, duration))
+            v = result.fetchone()
+            if v is not None:
+                return v[0]
+            return None
+
     def get_id_by(self, name, album_id, artist_ids):
         """
             Return track id for name/album/artists
@@ -432,14 +448,24 @@
                                   WHERE mtime=0")
             return list(itertools.chain(*result))
 
-    def get_uris(self):
+    def get_uris(self, uris_concerned=None):
         """
             Get all tracks uri
+            @param uris_concerned as [uri as str]
             @return [str]
         """
         with SqlCursor(App().db) as sql:
-            result = sql.execute("SELECT uri FROM tracks")
-            return list(itertools.chain(*result))
+            uris = []
+            if uris_concerned:
+                for uri in uris_concerned:
+                    result = sql.execute("SELECT uri\
+                                          FROM tracks\
+                                          WHERE uri LIKE ?", (uri + "%",))
+                    uris += list(itertools.chain(*result))
+            else:
+                result = sql.execute("SELECT uri FROM tracks")
+                uris = list(itertools.chain(*result))
+            return uris
 
     def get_number(self, track_id):
         """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-0.9.914/lollypop/define.py 
new/lollypop-0.9.916/lollypop/define.py
--- old/lollypop-0.9.914/lollypop/define.py     2019-01-23 19:00:51.000000000 
+0100
+++ new/lollypop-0.9.916/lollypop/define.py     2019-01-29 07:05:19.000000000 
+0100
@@ -62,6 +62,12 @@
     MAX = 4000
 
 
+class ScanType:
+    EPHEMERAL = 0
+    NEW_FILES = 1
+    FULL = 2
+
+
 class SelectionListMask:
         LIST_ONE = 1 << 1
         LIST_TWO = 1 << 2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-0.9.914/lollypop/inotify.py 
new/lollypop-0.9.916/lollypop/inotify.py
--- old/lollypop-0.9.914/lollypop/inotify.py    2019-01-23 19:00:51.000000000 
+0100
+++ new/lollypop-0.9.916/lollypop/inotify.py    2019-01-29 07:05:19.000000000 
+0100
@@ -12,7 +12,7 @@
 
 from gi.repository import Gio, GLib
 
-from lollypop.define import App
+from lollypop.define import App, ScanType
 from lollypop.utils import is_audio
 from lollypop.logger import Logger
 
@@ -21,15 +21,15 @@
     """
         Inotify support
     """
-    # 10 second before updating database
-    __TIMEOUT = 10000
+    # 2 seconds before updating database
+    __TIMEOUT = 2000
 
     def __init__(self):
         """
             Init inode notification
         """
         self.__monitors = {}
-        self.__timeout = None
+        self.__timeout_id = None
 
     def add_monitor(self, uri):
         """
@@ -61,7 +61,18 @@
             @param other_file as Gio.File/None
             @param event as Gio.FileMonitorEvent
         """
-        update = False
+        changed_uri = changed_file.get_uri()
+        # Do not monitor our self
+        if changed_uri in self.__monitors.keys() and\
+                self.__monitors[changed_uri] == monitor:
+            return
+        # Ignore non audio/dir
+        if changed_file.query_exists() and\
+                not is_audio(changed_file) and\
+                changed_file.query_file_type(Gio.FileQueryInfoFlags.NONE,
+                                             None) != Gio.FileType.DIRECTORY:
+            return
+
         # Stop collection scanner and wait
         if App().scanner.is_locked():
             App().scanner.stop()
@@ -73,40 +84,20 @@
                              event)
         # Run update delayed
         else:
-            uri = changed_file.get_uri()
-            d = Gio.File.new_for_uri(uri)
-            is_dir = False
-            if d.query_exists():
-                # If a directory, monitor it
-                if changed_file.query_file_type(
-                        Gio.FileQueryInfoFlags.NONE,
-                        None) == Gio.FileType.DIRECTORY:
-                    self.add_monitor(uri)
-                    is_dir = True
-                # If not an audio file, exit
-                elif is_audio(changed_file):
-                    update = True
+            if self.__timeout_id is not None:
+                GLib.source_remove(self.__timeout_id)
+            if changed_file.has_parent():
+                uris = [changed_file.get_parent().get_uri()]
             else:
-                update = True
-            if update:
-                if self.__timeout is not None:
-                    GLib.source_remove(self.__timeout)
-                    self.__timeout = None
-                # Launch collection update from this directory
-                # (and not the entire collection)
-                uris = None
-                if is_dir:
-                    uris = [uri]
-                elif changed_file.has_parent():
-                    uris = [changed_file.get_parent().get_uri()]
-                self.__timeout = GLib.timeout_add(self.__TIMEOUT,
-                                                  self.__run_collection_update,
-                                                  uris)
+                uris = [changed_uri]
+            self.__timeout_id = GLib.timeout_add(self.__TIMEOUT,
+                                                 self.__run_collection_update,
+                                                 uris)
 
-    def __run_collection_update(self, uris=None):
+    def __run_collection_update(self, uris=[]):
         """
             Run a collection update
             @param uris as [str]
         """
-        self.__timeout = None
-        App().scanner.update(uris)
+        self.__timeout_id = None
+        App().scanner.update(ScanType.NEW_FILES, uris)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-0.9.914/lollypop/mpris.py 
new/lollypop-0.9.916/lollypop/mpris.py
--- old/lollypop-0.9.914/lollypop/mpris.py      2019-01-23 19:00:51.000000000 
+0100
+++ new/lollypop-0.9.916/lollypop/mpris.py      2019-01-29 07:05:19.000000000 
+0100
@@ -54,7 +54,7 @@
 
         args = list(parameters.unpack())
         for i, sig in enumerate(self.method_inargs[method_name]):
-            if sig is "h":
+            if sig == "h":
                 msg = invocation.get_message()
                 fd_list = msg.get_unix_fd_list()
                 args[i] = fd_list.get(args[i])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-0.9.914/lollypop/objects.py 
new/lollypop-0.9.916/lollypop/objects.py
--- old/lollypop-0.9.914/lollypop/objects.py    2019-01-23 19:00:51.000000000 
+0100
+++ new/lollypop-0.9.916/lollypop/objects.py    2019-01-29 07:05:19.000000000 
+0100
@@ -326,12 +326,12 @@
         """
             Get track
             @param track_id as int
-            @return Track/None
+            @return Track
         """
         for track in self.tracks:
             if track.id == track_id:
                 return track
-        return None
+        return Track()
 
     @property
     def title(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-0.9.914/lollypop/player.py 
new/lollypop-0.9.916/lollypop/player.py
--- old/lollypop-0.9.914/lollypop/player.py     2019-01-23 19:00:51.000000000 
+0100
+++ new/lollypop-0.9.916/lollypop/player.py     2019-01-29 07:05:19.000000000 
+0100
@@ -257,37 +257,25 @@
             else:
                 album_ids += App().albums.get_ids([], filter1_ids, True)
 
-        shuffle_setting = App().settings.get_enum("shuffle")
         if not album_ids:
             return
-        elif shuffle_setting == Shuffle.ALBUMS:
-            if album_id is None:
-                shuffle(album_ids)
-                album = Album(album_id, filter1_ids, filter2_ids, True)
-            else:
-                album = Album(album_id, filter1_ids, filter2_ids, True)
-                shuffle(album_ids)
-        else:
-            album = Album(album_id, filter1_ids, filter2_ids, True)
-        # Select a track and start playback
-        track = None
-        if shuffle_setting == Shuffle.ALBUMS:
-            self._albums = [album]
-            album_ids.remove(album_id)
-        if shuffle_setting == Shuffle.TRACKS:
-            track = choice(album.tracks)
-        elif shuffle_setting == Shuffle.ALBUMS:
-            if self._albums and self._albums[0].tracks:
-                track = self._albums[0].tracks[0]
-        elif album.tracks:
-            track = album.tracks[0]
 
         # Create album objects
+        albums = []
+        album = None
         for _album_id in album_ids:
-            album = Album(_album_id, filter1_ids, filter2_ids, True)
-            self._albums.append(album)
-        if track is not None:
-            self.load(track)
+            _album = Album(_album_id, filter1_ids, filter2_ids, True)
+            if album_id == _album_id:
+                album = _album
+            albums.append(_album)
+
+        shuffle_setting = App().settings.get_enum("shuffle")
+        if shuffle_setting == Shuffle.ALBUMS:
+            self.__play_shuffle_albums(album, albums)
+        elif shuffle_setting == Shuffle.TRACKS:
+            self.__play_shuffle_tracks(album, albums)
+        else:
+            self.__play_albums(album, albums)
         self.emit("playlist-changed")
 
     def clear_albums(self):
@@ -539,6 +527,57 @@
 #######################
 # PRIVATE             #
 #######################
+    def __play_shuffle_albums(self, album, albums):
+        """
+            Start shuffle albums playback. Prepend album if not None
+            @param album as Album
+            @param albums as [albums]
+        """
+        track = None
+        if album is None:
+            album = choice(albums)
+        else:
+            self._albums = [album]
+            albums.remove(album)
+        shuffle(albums)
+        self._albums += albums
+        if album.tracks:
+            track = album.tracks[0]
+        if track is not None:
+            self.load(track)
+
+    def __play_shuffle_tracks(self, album, albums):
+        """
+            Start shuffle tracks playback.
+            @param album as Album
+            @param albums as [albums]
+        """
+        if album is None:
+            album = choice(albums)
+        if album.tracks:
+            track = choice(album.tracks)
+        else:
+            track = None
+        self._albums = albums
+        if track is not None:
+            self.load(track)
+
+    def __play_albums(self, album, albums):
+        """
+            Start albums playback.
+            @param album as Album
+            @param albums as [albums]
+        """
+        if album is None:
+            album = albums[0]
+        if album.tracks:
+            track = album.tracks[0]
+        else:
+            track = None
+        self._albums = albums
+        if track is not None:
+            self.load(track)
+
     def __on_playback_changed(self, settings, value):
         """
             reset next/prev
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-0.9.914/lollypop/progressbar.py 
new/lollypop-0.9.916/lollypop/progressbar.py
--- old/lollypop-0.9.914/lollypop/progressbar.py        2019-01-23 
19:00:51.000000000 +0100
+++ new/lollypop-0.9.916/lollypop/progressbar.py        2019-01-29 
07:05:19.000000000 +0100
@@ -51,7 +51,9 @@
         if caller == self.__callers[0]:
             self.show()
             self.__fraction = fraction
-            if not self.__progress_running:
+            if fraction == 0:
+                Gtk.ProgressBar.set_fraction(self, 0.0)
+            elif not self.__progress_running:
                 self.__progress_running = True
                 self.__progress_update(caller)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-0.9.914/lollypop/settings.py 
new/lollypop-0.9.916/lollypop/settings.py
--- old/lollypop-0.9.914/lollypop/settings.py   2019-01-23 19:00:51.000000000 
+0100
+++ new/lollypop-0.9.916/lollypop/settings.py   2019-01-29 07:05:19.000000000 
+0100
@@ -15,7 +15,7 @@
 from gettext import gettext as _
 from gettext import ngettext as ngettext
 
-from lollypop.define import App
+from lollypop.define import App, ScanType
 from lollypop.logger import Logger
 from lollypop.database import Database
 from lollypop.database_history import History
@@ -668,7 +668,15 @@
         self.__settings_dialog.hide()
         self.__settings_dialog.destroy()
         if set(previous) != set(uris):
-            App().scanner.update()
+            to_delete = [uri for uri in previous if uri not in uris]
+            if to_delete:
+                # We need to do a full scan
+                App().scanner.update(ScanType.FULL)
+            else:
+                # Only scan new folders
+                to_scan = [uri for uri in uris if uri not in previous]
+                if to_scan:
+                    App().scanner.update(ScanType.NEW_FILES, to_scan)
 
     def __test_lastfm_connection(self, result, fm):
         """
@@ -806,7 +814,7 @@
             App().db = Database()
             App().window.container.show_genres(
                 App().settings.get_value("show-genres"))
-            App().scanner.update()
+            App().scanner.update(ScanType.FULL)
             self.__progress.get_toplevel().set_deletable(True)
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-0.9.914/lollypop/tagreader.py 
new/lollypop-0.9.916/lollypop/tagreader.py
--- old/lollypop-0.9.914/lollypop/tagreader.py  2019-01-23 19:00:51.000000000 
+0100
+++ new/lollypop-0.9.916/lollypop/tagreader.py  2019-01-29 07:05:19.000000000 
+0100
@@ -375,6 +375,7 @@
     def get_lyrics(self, tags):
         """
             Return lyrics for tags
+            All this code sucks
             @parma tags as Gst.TagList
             @return lyrics as str
         """
@@ -387,9 +388,11 @@
                     else:
                         return None
                 elif bytes[0:4] == b"USLT":
-                    # This code sucks, if someone know how to handle this
-                    # UTF8
-                    lyrics = bytes.split(b"\x00")[-1]
+                    # Search for lyrics (more than 10 chars)
+                    for value in bytes.split(b"\x00"):
+                        if len(value) > 10:
+                            lyrics = value
+                            break
                     # UTF-16
                     if not lyrics:
                         lyrics = bytes.split(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-0.9.914/lollypop/view_information.py 
new/lollypop-0.9.916/lollypop/view_information.py
--- old/lollypop-0.9.914/lollypop/view_information.py   2019-01-23 
19:00:51.000000000 +0100
+++ new/lollypop-0.9.916/lollypop/view_information.py   2019-01-29 
07:05:19.000000000 +0100
@@ -158,6 +158,8 @@
             albums = []
             for album_id in App().albums.get_ids([artist_id], []):
                 albums.append(Album(album_id))
+            if not albums:
+                albums = [App().player.current_track.album]
             albums_view.populate(albums)
         App().task_helper.run(InformationStore.get_bio, self.__artist_name,
                               callback=(self.__on_get_bio,))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-0.9.914/lollypop/window.py 
new/lollypop-0.9.916/lollypop/window.py
--- old/lollypop-0.9.914/lollypop/window.py     2019-01-23 19:00:51.000000000 
+0100
+++ new/lollypop-0.9.916/lollypop/window.py     2019-01-29 07:05:19.000000000 
+0100
@@ -15,7 +15,7 @@
 from gettext import gettext as _
 
 from lollypop.container import Container
-from lollypop.define import App, Sizing, Type
+from lollypop.define import App, Sizing, Type, ScanType
 from lollypop.toolbar import Toolbar
 from lollypop.logger import Logger
 from lollypop.adaptive import AdaptiveWindow
@@ -523,7 +523,7 @@
             # Delayed, make python segfault on sys.exit() otherwise
             # No idea why, maybe scanner using Gstpbutils before Gstreamer
             # initialisation is finished...
-            GLib.timeout_add(2000, App().scanner.update)
+            GLib.timeout_add(1000, App().scanner.update, ScanType.FULL)
         # Here we ignore initial configure events
         self.__toolbar.set_content_width(self.get_size()[0])
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-0.9.914/meson.build 
new/lollypop-0.9.916/meson.build
--- old/lollypop-0.9.914/meson.build    2019-01-23 19:00:51.000000000 +0100
+++ new/lollypop-0.9.916/meson.build    2019-01-29 07:05:19.000000000 +0100
@@ -1,5 +1,5 @@
 project('lollypop',
-  version: '0.9.914',
+  version: '0.9.916',
   meson_version: '>= 0.40.0'
 )
 i18n = import('i18n')


Reply via email to