Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package lollypop for openSUSE:Factory 
checked in at 2021-01-18 11:28:42
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/lollypop (Old)
 and      /work/SRC/openSUSE:Factory/.lollypop.new.28504 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "lollypop"

Mon Jan 18 11:28:42 2021 rev:143 rq:863904 version:1.4.12

Changes:
--------
--- /work/SRC/openSUSE:Factory/lollypop/lollypop.changes        2021-01-11 
17:16:13.732606419 +0100
+++ /work/SRC/openSUSE:Factory/.lollypop.new.28504/lollypop.changes     
2021-01-18 11:32:30.364693559 +0100
@@ -1,0 +2,26 @@
+Sun Jan 17 19:51:31 UTC 2021 - antoine.belv...@opensuse.org
+
+- Update to version 1.4.12:
+  * Fix a crash on init due to missing secret.
+  * Fix a crash on album widget reveal (glgo#World/lollypop#2679).
+  * Fix a playback issue (glgo#World/lollypop#2683).
+  * Fix content not being reloaded after resizing window
+    (glgo#World/lollypop#2673).
+  * Fix album artwork removal (glgo#World/lollypop#2680).
+
+-------------------------------------------------------------------
+Sun Jan 17 12:25:41 UTC 2021 - antoine.belv...@opensuse.org
+
+- Update to version 1.4.11:
+  * Fix an issue with blacklisted songs (glgo#Wolrd/lollypop#2676).
+  * Fix an issue with loved songs (glgo#World/lollypop#2677).
+
+-------------------------------------------------------------------
+Sat Jan 16 14:26:58 UTC 2021 - antoine.belv...@opensuse.org
+
+- Update to version 1.4.10:
+  * Fix crash when clicking "Play all" button for entire library
+    (glgo#World/lollypop#2674)
+  * Rework ReplayGain defaults (glgo#World/lollypop#2564).
+
+-------------------------------------------------------------------

Old:
----
  lollypop-1.4.9.tar.xz

New:
----
  lollypop-1.4.12.tar.xz

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

Other differences:
------------------
++++++ lollypop.spec ++++++
--- /var/tmp/diff_new_pack.CFGi6G/_old  2021-01-18 11:32:31.016694201 +0100
+++ /var/tmp/diff_new_pack.CFGi6G/_new  2021-01-18 11:32:31.016694201 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           lollypop
-Version:        1.4.9
+Version:        1.4.12
 Release:        0
 Summary:        GNOME music playing application
 License:        GPL-3.0-or-later

++++++ _service ++++++
--- /var/tmp/diff_new_pack.CFGi6G/_old  2021-01-18 11:32:31.048694233 +0100
+++ /var/tmp/diff_new_pack.CFGi6G/_new  2021-01-18 11:32:31.048694233 +0100
@@ -1,7 +1,7 @@
 <services>
   <service mode="disabled" name="tar_scm">
     <param name="changesgenerate">enable</param>
-    <param name="revision">1.4.9</param>
+    <param name="revision">1.4.12</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.CFGi6G/_old  2021-01-18 11:32:31.068694253 +0100
+++ /var/tmp/diff_new_pack.CFGi6G/_new  2021-01-18 11:32:31.068694253 +0100
@@ -1,4 +1,4 @@
 <servicedata>
 <service name="tar_scm">
                 <param 
name="url">https://gitlab.gnome.org/World/lollypop.git</param>
-              <param 
name="changesrevision">99d5aaf24c8b2cfe0c0cd81d0cdc0bbb2ed77d1c</param></service></servicedata>
\ No newline at end of file
+              <param 
name="changesrevision">0b01adcdeb33ad3af86f2336dd067759cae9d4b8</param></service></servicedata>
\ No newline at end of file

++++++ lollypop-1.4.9.tar.xz -> lollypop-1.4.12.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-1.4.9/data/org.gnome.Lollypop.gschema.xml 
new/lollypop-1.4.12/data/org.gnome.Lollypop.gschema.xml
--- old/lollypop-1.4.9/data/org.gnome.Lollypop.gschema.xml      2021-01-10 
20:27:35.000000000 +0100
+++ new/lollypop-1.4.12/data/org.gnome.Lollypop.gschema.xml     2021-01-17 
20:48:13.000000000 +0100
@@ -365,17 +365,17 @@
             <description></description>
         </key>
         <key enum="org.gnome.Lollypop.ReplayGain" name="replay-gain">
-            <default>'album'</default>
+            <default>'none'</default>
             <summary>ReplayGain state</summary>
             <description></description>
         </key>
         <key type="d" name="replay-gain-db">
-            <default>3.0</default>
+            <default>0</default>
             <summary>ReplayGain value in dB</summary>
             <description>Between -15 and 15</description>
         </key>
         <key type="b" name="replay-gain-limiter">
-            <default>true</default>
+            <default>false</default>
             <summary>Applies signal compression/limiting to raw audio 
data</summary>
             <description>It performs strict hard limiting with soft-knee 
characteristics, using a threshold of -6 dB</description>
         </key>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-1.4.9/lollypop/artwork_album.py 
new/lollypop-1.4.12/lollypop/artwork_album.py
--- old/lollypop-1.4.9/lollypop/artwork_album.py        2021-01-10 
20:27:35.000000000 +0100
+++ new/lollypop-1.4.12/lollypop/artwork_album.py       2021-01-17 
20:48:13.000000000 +0100
@@ -397,7 +397,7 @@
         art_uri = "%s/%s" % (album.uri, self.__favorite)
         art_uri = self.add_extension(art_uri)
         # Save cover to tags
-        if save_to_tags:
+        if save_to_tags and data is not None:
             helper = TaskHelper()
             helper.run(self.__add_to_tags, album, data)
         # We need to remove favorite if exists
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-1.4.9/lollypop/collection_scanner.py 
new/lollypop-1.4.12/lollypop/collection_scanner.py
--- old/lollypop-1.4.9/lollypop/collection_scanner.py   2021-01-10 
20:27:35.000000000 +0100
+++ new/lollypop-1.4.12/lollypop/collection_scanner.py  2021-01-17 
20:48:13.000000000 +0100
@@ -557,6 +557,8 @@
         except Exception as e:
             Logger.warning("CollectionScanner::__scan(): %s", e)
         SqlCursor.remove(App().db)
+        App().settings.set_value("flatpak-access-migration",
+                                 GLib.Variant("b", True))
 
     def __scan_to_handle(self, uri):
         """
@@ -870,5 +872,3 @@
             assistant.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
             assistant.set_transient_for(App().window)
             GLib.timeout_add(1000, assistant.show)
-            App().settings.set_value("flatpak-access-migration",
-                                     GLib.Variant("b", True))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-1.4.9/lollypop/container.py 
new/lollypop-1.4.12/lollypop/container.py
--- old/lollypop-1.4.9/lollypop/container.py    2021-01-10 20:27:35.000000000 
+0100
+++ new/lollypop-1.4.12/lollypop/container.py   2021-01-17 20:48:13.000000000 
+0100
@@ -58,6 +58,7 @@
         """
         self.__widget = Handy.Leaflet()
         self.__widget.show()
+        self.__widget.connect("notify::folded", self.__on_folded)
         self.__sub_widget = Handy.Leaflet()
         self.__sub_widget.show()
         self.__focused_view = None
@@ -210,6 +211,13 @@
 ############
 # PRIVATE  #
 ############
+    def __on_folded(self, *ignore):
+        """
+            Reload main view if needed
+        """
+        if not App().window.folded and self.view is None:
+            self.show_view(self.sidebar.selected_ids)
+
     def __on_search_activate(self, action, variant):
         """
             @param action as Gio.SimpleAction
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-1.4.9/lollypop/database_albums.py 
new/lollypop-1.4.12/lollypop/database_albums.py
--- old/lollypop-1.4.9/lollypop/database_albums.py      2021-01-10 
20:27:35.000000000 +0100
+++ new/lollypop-1.4.12/lollypop/database_albums.py     2021-01-17 
20:48:13.000000000 +0100
@@ -940,6 +940,7 @@
             @param skipped as bool
             @return [int]
         """
+        print("::", skipped)
         genre_ids = remove_static(genre_ids)
         artist_ids = remove_static(artist_ids)
         with SqlCursor(self.__db) as sql:
@@ -1078,7 +1079,7 @@
                     request += " AND not albums.loved & ?"
                     filters += (LovedFlags.SKIPPED,)
                 request += order
-                result = sql.execute(request, (storage_type,))
+                result = sql.execute(request, filters)
             # Get albums for genres
             elif not artist_ids:
                 filters = (storage_type,)
@@ -1268,7 +1269,7 @@
             @return album ids as [int]
         """
         with SqlCursor(self.__db) as sql:
-            filters = ()
+            filters = (storage_type,)
             request = "SELECT album_id FROM tracks, albums\
                        WHERE albums.storage_type & ? AND albums.rowid=album_id"
             if not skipped:
@@ -1276,7 +1277,7 @@
                 filters += (LovedFlags.SKIPPED,)
             request += " GROUP BY album_id\
                         ORDER BY SUM(ltime)/COUNT(ltime), random() LIMIT ?"
-            filters += (storage_type, limit)
+            filters += (limit,)
             result = sql.execute(request, filters)
             return list(itertools.chain(*result))
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-1.4.9/lollypop/database_genres.py 
new/lollypop-1.4.12/lollypop/database_genres.py
--- old/lollypop-1.4.9/lollypop/database_genres.py      2021-01-10 
20:27:35.000000000 +0100
+++ new/lollypop-1.4.12/lollypop/database_genres.py     2021-01-17 
20:48:13.000000000 +0100
@@ -13,7 +13,7 @@
 import itertools
 
 from lollypop.sqlcursor import SqlCursor
-from lollypop.define import App, Type, OrderBy
+from lollypop.define import App, Type, OrderBy, LovedFlags
 from lollypop.utils import get_network_available, sql_escape
 
 
@@ -104,6 +104,7 @@
                      albums.name\
                      COLLATE NOCASE COLLATE LOCALIZED"
         with SqlCursor(self.__db) as sql:
+            filters = ()
             request = "SELECT albums.rowid\
                        FROM albums, album_genres, genres,\
                             album_artists, artists\
@@ -114,9 +115,10 @@
             if not get_network_available():
                 request += " AND albums.synced!=%s" % Type.NONE
             if ignore:
-                request += " AND albums.loved != -1"
+                request += " AND not albums.loved & ?"
+                filters += (LovedFlags.SKIPPED,)
             request += order
-            result = sql.execute(request)
+            result = sql.execute(request, filters)
             return list(itertools.chain(*result))
 
     def get(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-1.4.9/lollypop/database_tracks.py 
new/lollypop-1.4.12/lollypop/database_tracks.py
--- old/lollypop-1.4.9/lollypop/database_tracks.py      2021-01-10 
20:27:35.000000000 +0100
+++ new/lollypop-1.4.12/lollypop/database_tracks.py     2021-01-17 
20:48:13.000000000 +0100
@@ -604,10 +604,10 @@
             @return [int]
         """
         with SqlCursor(self.__db) as sql:
-            filters = (storage_type,)
+            filters = (LovedFlags.LOVED, storage_type)
             request = "SELECT tracks.rowid\
                        FROM tracks, album_artists, artists\
-                       WHERE loved=1 AND\
+                       WHERE loved=? AND\
                        artists.rowid=album_artists.artist_id AND\
                        tracks.album_id=album_artists.album_id AND\
                        storage_type & ?"
@@ -617,7 +617,7 @@
                 request += make_subrequest("album_artists.artist_id=?",
                                            "OR",
                                            len(artist_ids))
-            request += "ORDER BY artists.name"
+            request += " ORDER BY artists.name"
             result = sql.execute(request, filters)
             return list(itertools.chain(*result))
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-1.4.9/lollypop/dialog_settings.py 
new/lollypop-1.4.12/lollypop/dialog_settings.py
--- old/lollypop-1.4.9/lollypop/dialog_settings.py      2021-01-10 
20:27:35.000000000 +0100
+++ new/lollypop-1.4.12/lollypop/dialog_settings.py     2021-01-17 
20:48:13.000000000 +0100
@@ -149,6 +149,10 @@
         setting = widget.get_name()
         value = widget.get_active()
         App().settings.set_enum(setting, value)
+        if setting == "replay-gain":
+            for plugin in App().player.plugins:
+                plugin.build_audiofilter()
+            App().player.reload_track()
 
     def _on_clean_artwork_cache_clicked(self, button):
         """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-1.4.9/lollypop/helper_passwords.py 
new/lollypop-1.4.12/lollypop/helper_passwords.py
--- old/lollypop-1.4.9/lollypop/helper_passwords.py     2021-01-10 
20:27:35.000000000 +0100
+++ new/lollypop-1.4.12/lollypop/helper_passwords.py    2021-01-17 
20:48:13.000000000 +0100
@@ -28,12 +28,7 @@
         """
         # Initial password lookup, prevent a lock issue in Flatpak backend
         if GLib.file_test("/app", GLib.FileTest.EXISTS):
-            SecretSchema = {"service": Secret.SchemaAttributeType.STRING}
-            SecretAttributes = {"service": "LASTFM"}
-            schema = Secret.Schema.new("org.gnome.Lollypop",
-                                       Secret.SchemaFlags.NONE,
-                                       SecretSchema)
-            Secret.password_lookup_sync(schema, SecretAttributes)
+            self.get_token("LASTFM")
 
     def get_token(self, service):
         """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-1.4.9/lollypop/objects_album.py 
new/lollypop-1.4.12/lollypop/objects_album.py
--- old/lollypop-1.4.9/lollypop/objects_album.py        2021-01-10 
20:27:35.000000000 +0100
+++ new/lollypop-1.4.12/lollypop/objects_album.py       2021-01-17 
20:48:13.000000000 +0100
@@ -350,7 +350,8 @@
             @return album
         """
         album = Album(self.id, self.genre_ids, self.artist_ids, skipped)
-        album.set_tracks(self.tracks)
+        if skipped:
+            album.set_tracks(self.tracks)
         return album
 
     def set_storage_type(self, storage_type):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-1.4.9/lollypop/tagreader.py 
new/lollypop-1.4.12/lollypop/tagreader.py
--- old/lollypop-1.4.9/lollypop/tagreader.py    2021-01-10 20:27:35.000000000 
+0100
+++ new/lollypop-1.4.12/lollypop/tagreader.py   2021-01-17 20:48:13.000000000 
+0100
@@ -32,12 +32,7 @@
         """
             Init tag reader
         """
-        self.init_discoverer()
 
-    def init_discoverer(self):
-        """
-            Init discover
-        """
         self._discoverer = GstPbutils.Discoverer.new(10 * Gst.SECOND)
 
     def get_info(self, uri):
@@ -56,6 +51,15 @@
         Scanner tag reader
     """
 
+    __STRING = ["title", "artist", "composer", "conductor",
+                "musicbrainz-albumid", "musicbrainz-trackid",
+                "musicbrainz-artistid", "musicbrainz-albumartistid",
+                "version", "performer", "artist-sortname",
+                "album-artist-sortname", "interpreted-by", "album-artist",
+                "album", "genre", "lyrics", "publisher"]
+    __INT = ["album-disc-number", "track-number"]
+    __DOUBLE = ["beats-per-minute"]
+
     def __init__(self):
         """
             Init tag reader
@@ -71,9 +75,8 @@
         """
         if tags is None:
             return GLib.path_get_basename(filepath)
-        (exists, title) = tags.get_string_index("title", 0)
-        # We need to check tag is not just spaces
-        if not exists or not title.strip(" "):
+        title = self.__get(tags, ["title"])
+        if not title:
             title = GLib.path_get_basename(filepath)
         return title
 
@@ -85,13 +88,7 @@
         """
         if tags is None:
             return _("Unknown")
-        artists = []
-        for i in range(tags.get_tag_size("artist")):
-            (exists, read) = tags.get_string_index("artist", i)
-            # We need to check tag is not just spaces
-            if exists and read.strip(" "):
-                artists.append(read)
-        return "; ".join(artists)
+        return self.__get(tags, ["artist"])
 
     def get_composers(self, tags):
         """
@@ -101,13 +98,7 @@
         """
         if tags is None:
             return _("Unknown")
-        composers = []
-        for i in range(tags.get_tag_size("composer")):
-            (exists, read) = tags.get_string_index("composer", i)
-            # We need to check tag is not just spaces
-            if exists and read.strip(" "):
-                composers.append(read)
-        return "; ".join(composers)
+        return self.__get(tags, ["composer"])
 
     def get_conductors(self, tags):
         """
@@ -117,13 +108,7 @@
         """
         if tags is None:
             return _("Unknown")
-        conductors = []
-        for i in range(tags.get_tag_size("conductor")):
-            (exists, read) = tags.get_string_index("conductor", i)
-            # We need to check tag is not just spaces
-            if exists and read.strip(" "):
-                conductors.append(read)
-        return "; ".join(conductors)
+        return self.__get(tags, ["conductor"])
 
     def get_mb_id(self, tags, name):
         """
@@ -134,8 +119,7 @@
         """
         if tags is None or not name:
             return ""
-        (exists, mbid) = tags.get_string_index("musicbrainz-" + name, 0)
-        return mbid or ""
+        return self.__get(tags, ["musicbrainz-" + name])
 
     def get_mb_album_id(self, tags):
         """
@@ -177,8 +161,7 @@
         """
         if tags is None:
             return ""
-        (exists, version) = tags.get_string_index("version", 0)
-        return version or ""
+        return self.__get(tags, ["version"])
 
     def get_performers(self, tags):
         """
@@ -188,13 +171,7 @@
         """
         if tags is None:
             return _("Unknown")
-        performers = []
-        for i in range(tags.get_tag_size("performer")):
-            (exists, read) = tags.get_string_index("performer", i)
-            # We need to check tag is not just spaces
-            if exists and read.strip(" "):
-                performers.append(read)
-        return "; ".join(performers)
+        return self.__get(tags, ["performer"])
 
     def get_artist_sortnames(self, tags):
         """
@@ -204,13 +181,7 @@
         """
         if tags is None:
             return ""
-        sortnames = []
-        for i in range(tags.get_tag_size("artist-sortname")):
-            (exists, read) = tags.get_string_index("artist-sortname", i)
-            # We need to check tag is not just spaces
-            if exists and read.strip(" "):
-                sortnames.append(read)
-        return "; ".join(sortnames)
+        return self.__get(tags, ["artist-sortname"])
 
     def get_album_artist_sortnames(self, tags):
         """
@@ -220,13 +191,7 @@
         """
         if tags is None:
             return ""
-        sortnames = []
-        for i in range(tags.get_tag_size("album-artist-sortname")):
-            (exists, read) = tags.get_string_index("album-artist-sortname", i)
-            # We need to check tag is not just spaces
-            if exists and read.strip(" "):
-                sortnames.append(read)
-        return "; ".join(sortnames)
+        return self.__get(tags, ["album-artist-sortname"])
 
     def get_remixers(self, tags):
         """
@@ -236,19 +201,10 @@
         """
         if tags is None:
             return _("Unknown")
-        remixers = []
-        for i in range(tags.get_tag_size("interpreted-by")):
-            (exists, read) = tags.get_string_index("interpreted-by", i)
-            # We need to check tag is not just spaces
-            if exists and read.strip(" "):
-                remixers.append(read)
+        remixers = self.__get(tags, ["interpreted-by"])
         if not remixers:
-            for i in range(tags.get_tag_size("extended-comment")):
-                (exists, read) = tags.get_string_index("extended-comment", i)
-                if exists and read.startswith("REMIXER="):
-                    remixer = read[8:]
-                    remixers.append(remixer)
-        return "; ".join(remixers)
+            remixers = self.__get_extended(tags, ["REMIXER"])
+        return remixers
 
     def get_album_artists(self, tags):
         """
@@ -258,13 +214,7 @@
         """
         if tags is None:
             return _("Unknown")
-        artists = []
-        for i in range(tags.get_tag_size("album-artist")):
-            (exists, read) = tags.get_string_index("album-artist", i)
-            # We need to check tag is not just spaces
-            if exists and read.strip(" "):
-                artists.append(read)
-        return "; ".join(artists)
+        return self.__get(tags, ["album-artist"])
 
     def get_album_name(self, tags):
         """
@@ -274,11 +224,10 @@
         """
         if tags is None:
             return _("Unknown")
-        (exists, album_name) = tags.get_string_index("album", 0)
-        # We need to check tag is not just spaces
-        if not exists or not album_name.strip(" "):
-            album_name = _("Unknown")
-        return album_name
+        album = self.__get(tags, ["album"])
+        if not album:
+            album = _("Unknown")
+        return album
 
     def get_genres(self, tags):
         """
@@ -288,15 +237,10 @@
         """
         if tags is None:
             return _("Unknown")
-        genres = []
-        for i in range(tags.get_tag_size("genre")):
-            (exists, read) = tags.get_string_index("genre", i)
-            # We need to check tag is not just spaces
-            if exists and read.strip(" "):
-                genres.append(read)
+        genres = self.__get(tags, ["genre"])
         if not genres:
-            return _("Unknown")
-        return "; ".join(genres)
+            genres = _("Unknown")
+        return genres
 
     def get_discname(self, tags):
         """
@@ -304,18 +248,7 @@
             @param tags as Gst.TagList
             @return disc name as str
         """
-        if tags is None:
-            return ""
-        discname = ""
-        for i in range(tags.get_tag_size("extended-comment")):
-            (exists, read) = tags.get_string_index("extended-comment", i)
-            if exists and read.startswith("PART"):
-                discname = "=".join(read.split("=")[1:])
-                break
-            if exists and read.startswith("DISCSUBTITLE"):
-                discname = "=".join(read.split("=")[1:])
-                break
-        return discname
+        return self.__get_extended(tags, ['PART', 'DISCSUBTITLE'])
 
     def get_discnumber(self, tags):
         """
@@ -325,8 +258,8 @@
         """
         if tags is None:
             return 0
-        (exists, discnumber) = tags.get_uint_index("album-disc-number", 0)
-        if not exists:
+        discnumber = self.__get(tags, ["album-disc-number"])
+        if not discnumber:
             discnumber = 0
         return discnumber
 
@@ -338,35 +271,14 @@
         """
         if tags is None:
             return False
-        size = tags.get_tag_size("private-id3v2-frame")
-        for i in range(0, size):
-            (exists, sample) = tags.get_sample_index(
-                "private-id3v2-frame",
-                i)
-            if not exists:
-                continue
-            (exists, m) = sample.get_buffer().map(Gst.MapFlags.READ)
-            if not exists:
-                continue
-            # Gstreamer 1.18 API breakage
-            try:
-                bytes = m.data.tobytes()
-            except:
-                bytes = m.data
-            frame = FrameTextTag(bytes)
-            if frame.key == "TCMP":
-                string = frame.string
-                if not string:
-                    Logger.debug(tags.to_string())
-                return string and string[-1] == "1"
-        size = tags.get_tag_size("extended-comment")
-        for i in range(0, size):
-            (exists, sample) = tags.get_string_index(
-                "extended-comment",
-                i)
-            if not exists or not sample.startswith("COMPILATION="):
-                continue
-            return sample[12]
+        try:
+            compilation = self.__get_private_string(tags, "TCMP", False)
+            if not compilation:
+                compilation = self.__get_extended(tags, ["COMPILATION"])
+            if compilation:
+                return bool(compilation)
+        except Exception as e:
+            Logger.error("TagReader::get_compilation(): %s" % e)
         return False
 
     def get_tracknumber(self, tags, filename):
@@ -377,10 +289,10 @@
             @return track number as int
         """
         if tags is not None:
-            (exists, tracknumber) = tags.get_uint_index("track-number", 0)
+            tracknumber = self.__get(tags, ["track-number"])
         else:
-            (exists, tracknumber) = (False, 0)
-        if not exists:
+            tracknumber = None
+        if not tracknumber:
             # Guess from filename
             m = match("^([0-9]*)[ ]*-", filename)
             if m:
@@ -436,45 +348,21 @@
             @return year and timestamp (int, int)
         """
         def get_id3():
+            date_string = self.__get_private_string(tags, "TDOR", False)
             try:
-                size = tags.get_tag_size("private-id3v2-frame")
-                for i in range(0, size):
-                    (exists, sample) = tags.get_sample_index(
-                        "private-id3v2-frame",
-                        i)
-                    if not exists:
-                        continue
-                    (exists, m) = sample.get_buffer().map(Gst.MapFlags.READ)
-                    if not exists:
-                        continue
-                    # Gstreamer 1.18 API breakage
-                    try:
-                        bytes = m.data.tobytes()
-                    except:
-                        bytes = m.data
-                    frame = FrameTextTag(bytes)
-                    if frame.key == "TDOR":
-                        if not frame.string:
-                            Logger.debug(tags.to_string())
-                        date = get_iso_date_from_string(frame.string)
-                        datetime = GLib.DateTime.new_from_iso8601(date, None)
-                        return (datetime.get_year(), datetime.to_unix())
+                date = get_iso_date_from_string(date_string)
+                datetime = GLib.DateTime.new_from_iso8601(date, None)
+                return (datetime.get_year(), datetime.to_unix())
             except:
                 pass
             return (None, None)
 
         def get_ogg():
             try:
-                size = tags.get_tag_size("extended-comment")
-                for i in range(0, size):
-                    (exists, sample) = tags.get_string_index(
-                        "extended-comment",
-                        i)
-                    if not exists or not sample.startswith("ORIGINALDATE="):
-                        continue
-                    date = get_iso_date_from_string(sample[13:])
-                    datetime = GLib.DateTime.new_from_iso8601(date, None)
-                    return (datetime.get_year(), datetime.to_unix())
+                date_string = self.__get_extended(tags, ['ORIGINALDATE'])
+                date = get_iso_date_from_string(date_string)
+                datetime = GLib.DateTime.new_from_iso8601(date, None)
+                return (datetime.get_year(), datetime.to_unix())
             except:
                 pass
             return (None, None)
@@ -492,14 +380,10 @@
             @param tags as Gst.TagList
             @return int/None
         """
-        try:
-            if tags is not None:
-                (exists, bpm) = tags.get_double_index("beats-per-minute", 0)
-                if exists:
-                    return bpm
-        except:
-            pass
-        return None
+        bpm = self.__get(tags, ["beats-per-minute"])
+        if not bpm:
+            bpm = None
+        return bpm
 
     def get_popm(self, tags):
         """
@@ -524,8 +408,12 @@
                     bytes = m.data.tobytes()
                 except:
                     bytes = m.data
-                if bytes[0:4] == b"POPM":
-                    popm = bytes.split(b"\x00")[6][0]
+
+                if len(bytes) > 4 and bytes[0:4] == b"POPM":
+                    try:
+                        popm = bytes.split(b"\x00")[6][0]
+                    except:
+                        popm = 0
                     if popm == 0:
                         value = 0
                     elif popm >= 1 and popm < 64:
@@ -551,61 +439,14 @@
             @parma tags as Gst.TagList
             @return lyrics as str
         """
-        def decode_lyrics(bytes):
-            try:
-                frame = FrameLangTag(bytes)
-                if frame.key == "USLT":
-                    return frame.string
-            except Exception as e:
-                Logger.warning("TagReader::get_lyrics(): %s", e)
-            return None
-
         def get_mp4():
-            try:
-                (exists, sample) = tags.get_string_index("lyrics", 0)
-                if exists:
-                    return sample
-            except Exception as e:
-                Logger.error("TagReader::get_mp4(): %s" % e)
-            return ""
+            return self.__get(tags, ["lyrics"])
 
         def get_id3():
-            try:
-                size = tags.get_tag_size("private-id3v2-frame")
-                for i in range(0, size):
-                    (exists, sample) = tags.get_sample_index(
-                        "private-id3v2-frame",
-                        i)
-                    if not exists:
-                        continue
-                    (exists, m) = sample.get_buffer().map(Gst.MapFlags.READ)
-                    if not exists:
-                        continue
-                    # Gstreamer 1.18 API breakage
-                    try:
-                        bytes = m.data.tobytes()
-                    except:
-                        bytes = m.data
-                    string = decode_lyrics(bytes)
-                    if string is not None:
-                        return string
-            except Exception as e:
-                Logger.error("TagReader::get_id3(): %s" % e)
-            return ""
+            return self.__get_private_string(tags, "USLT", True)
 
         def get_ogg():
-            try:
-                size = tags.get_tag_size("extended-comment")
-                for i in range(0, size):
-                    (exists, sample) = tags.get_string_index(
-                        "extended-comment",
-                        i)
-                    if not exists or not sample.startswith("LYRICS="):
-                        continue
-                    return sample[7:]
-            except Exception as e:
-                Logger.error("TagReader::get_ogg(): %s" % e)
-            return ""
+            return self.__get_extended(tags, ["LYRICS"])
 
         if tags is None:
             return ""
@@ -631,36 +472,21 @@
                         lyrics.append((decodeUnicode(l, encoding),
                                        int.from_bytes(t[1:4], "big")))
             except Exception as e:
-                Logger.warning("TagReader::get_synced_lyrics1(): %s", e)
+                Logger.warning(
+                        "TagReader::get_synced_lyrics.decode_lyrics(): %s", e)
             return lyrics
 
         def get_id3():
             try:
-                size = tags.get_tag_size("private-id3v2-frame")
-                for i in range(0, size):
-                    (exists, sample) = tags.get_sample_index(
-                        "private-id3v2-frame",
-                        i)
-                    if not exists:
-                        continue
-                    (exists, m) = sample.get_buffer().map(Gst.MapFlags.READ)
-                    if not exists:
-                        continue
-                    # Gstreamer 1.18 API breakage
-                    try:
-                        bytes = m.data.tobytes()
-                    except:
-                        bytes = m.data
-                    prefix = (bytes[0:4])
-                    if prefix not in [b"SYLT"]:
-                        continue
-                    frame = bytes[10:]
+                b = self.__get_private_bytes(tags, "SYLT")
+                if b:
+                    frame = b[10:]
                     encoding = frame[0:1]
                     string = decode_lyrics(frame.split(b"\n"), encoding)
                     if string is not None:
                         return string
             except Exception as e:
-                Logger.error("TagReader::get_synced_lyrics2(): %s" % e)
+                Logger.warning("TagReader::get_synced_lyrics.get_id3(): %s", e)
             return ""
 
         if tags is None:
@@ -784,3 +610,106 @@
 #######################
 # PRIVATE             #
 #######################
+    def __get_extended(self, tags, keys):
+        """
+            Return tag from tags following keys
+            @param tags as Gst.TagList
+            @param keys as [str]
+            @return Tag as str
+        """
+        if tags is None:
+            return ""
+        items = []
+        try:
+            for i in range(tags.get_tag_size("extended-comment")):
+                (exists, read) = tags.get_string_index("extended-comment", i)
+                for key in keys:
+                    if exists and read.startswith(key + "="):
+                        items.append("".join(read.split("=")[1:]))
+        except Exception as e:
+            Logger.error("TagReader::__get_extended(): %s", e)
+        return ";".join(items)
+
+    def __get(self, tags, keys):
+        """
+            Return tag from tags following keys
+            Only handles string/uint/double
+            @param tags as Gst.TagList
+            @param keys as [str]
+            @return Tag as str/int/double. Empty string if does not exist
+        """
+        if tags is None:
+            return ""
+        items = []
+        try:
+            for key in keys:
+                for i in range(tags.get_tag_size(key)):
+                    if key in self.__STRING:
+                        (exists, read) = tags.get_string_index(key, i)
+                        if exists and read.strip(" "):
+                            items.append(read)
+                    elif key in self.__INT:
+                        (exists, read) = tags.get_uint_index(key, i)
+                        if exists:
+                            return read
+                    elif key in self.__DOUBLE:
+                        (exists, read) = tags.get_double_index(key, i)
+                        if exists:
+                            return read
+                    else:
+                        Logger.error("Missing key" % key)
+        except Exception as e:
+            Logger.error("TagReader::__get(): %s", e)
+        return ";".join(items)
+
+    def __get_private_bytes(self, tags, key):
+        """
+            Get key from private frame
+            @param tags as Gst.TagList
+            @param key as str
+            @return frame as bytes
+        """
+        try:
+            size = tags.get_tag_size("private-id3v2-frame")
+            encoded_key = key.encode("utf-8")
+            for i in range(0, size):
+                (exists, sample) = tags.get_sample_index(
+                    "private-id3v2-frame",
+                    i)
+                if not exists:
+                    continue
+                (exists, m) = sample.get_buffer().map(Gst.MapFlags.READ)
+                if not exists:
+                    continue
+                # Gstreamer 1.18 API breakage
+                try:
+                    b = m.data.tobytes()
+                except:
+                    b = m.data
+
+                if b[0:len(encoded_key)] != encoded_key:
+                    continue
+                return b
+        except Exception as e:
+            Logger.error("TagReader::__get_private_bytes(): %s" % e)
+        return b""
+
+    def __get_private_string(self, tags, key, lang):
+        """
+            Get key from private frame
+            @param tags as Gst.TagList
+            @param key as str
+            @param lang as bool
+            @return Tag as str
+        """
+        try:
+            b = self.__get_private_bytes(tags, key)
+            if lang:
+                frame = FrameLangTag(b)
+            else:
+                frame = FrameTextTag(b)
+            if frame.key == key:
+                return frame.string
+        except Exception as e:
+            Logger.error("TagReader::__get_private(): %s" % e)
+        return ""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-1.4.9/lollypop/view_albums_box.py 
new/lollypop-1.4.12/lollypop/view_albums_box.py
--- old/lollypop-1.4.9/lollypop/view_albums_box.py      2021-01-10 
20:27:35.000000000 +0100
+++ new/lollypop-1.4.12/lollypop/view_albums_box.py     2021-01-17 
20:48:13.000000000 +0100
@@ -263,11 +263,10 @@
 
         def play_album(status, child):
             child.artwork.get_style_context().remove_class("load-animation")
-            child.data.reset_tracks()
-            App().player.play_album(child.data.clone(True))
+            App().player.play_album(child.data.clone(False))
 
         if child.data.storage_type & StorageType.COLLECTION:
-            App().player.play_album(child.data.clone(True))
+            App().player.play_album(child.data.clone(False))
         else:
             child.artwork.get_style_context().add_class("load-animation")
             cancellable = Gio.Cancellable.new()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-1.4.9/lollypop/view_current_albums.py 
new/lollypop-1.4.12/lollypop/view_current_albums.py
--- old/lollypop-1.4.9/lollypop/view_current_albums.py  2021-01-10 
20:27:35.000000000 +0100
+++ new/lollypop-1.4.12/lollypop/view_current_albums.py 2021-01-17 
20:48:13.000000000 +0100
@@ -194,6 +194,7 @@
             if App().player.next_track.id != track.id:
                 App().player.next()
         row.album.remove_track(track)
+        App().player.update_next_prev()
         emit_signal(App().player, "playback-updated", row.album)
         if not row.children:
             row.destroy()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-1.4.9/lollypop/view_lazyloading.py 
new/lollypop-1.4.12/lollypop/view_lazyloading.py
--- old/lollypop-1.4.9/lollypop/view_lazyloading.py     2021-01-10 
20:27:35.000000000 +0100
+++ new/lollypop-1.4.12/lollypop/view_lazyloading.py    2021-01-17 
20:48:13.000000000 +0100
@@ -13,7 +13,6 @@
 from gi.repository import GLib, GObject
 
 from time import time
-import gc
 
 from lollypop.define import LoadingState, App
 from lollypop.logger import Logger
@@ -180,7 +179,6 @@
                 else:
                     GLib.idle_add(
                         App().window.container.type_ahead.entry.grab_focus)
-            gc.collect()
             Logger.debug("LazyLoadingView::lazy_loading(): %s",
                          time() - self.__start_time)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-1.4.9/lollypop/view_tracks_album.py 
new/lollypop-1.4.12/lollypop/view_tracks_album.py
--- old/lollypop-1.4.9/lollypop/view_tracks_album.py    2021-01-10 
20:27:35.000000000 +0100
+++ new/lollypop-1.4.12/lollypop/view_tracks_album.py   2021-01-17 
20:48:13.000000000 +0100
@@ -18,7 +18,7 @@
 from lollypop.widgets_label import LabelWidget
 from lollypop.objects_album import Album
 from lollypop.utils import emit_signal
-from lollypop.define import App, ViewType
+from lollypop.define import App, ViewType, LovedFlags
 from lollypop.view_tracks import TracksView
 
 
@@ -256,7 +256,8 @@
         if self.view_type & (ViewType.ALBUM | ViewType.ARTIST):
             tracks = []
             for child in self.children:
-                if child.track.loved != -1 or track.id == child.track.id:
+                if not child.track.loved & LovedFlags.SKIPPED or\
+                        track.id == child.track.id:
                     tracks.append(child.track)
                 child.set_state_flags(Gtk.StateFlags.NORMAL, True)
             # Do not update album list if in party or album already available
@@ -365,6 +366,6 @@
             @param label as LabelWidget
             @param disc_number as int
         """
-        album = Album(self.__album.id)
+        album = self.__album.clone(False)
         album.set_disc_number(disc_number)
         App().player.play_album(album)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-1.4.9/lollypop/widgets_album.py 
new/lollypop-1.4.12/lollypop/widgets_album.py
--- old/lollypop-1.4.9/lollypop/widgets_album.py        2021-01-10 
20:27:35.000000000 +0100
+++ new/lollypop-1.4.12/lollypop/widgets_album.py       2021-01-17 
20:48:13.000000000 +0100
@@ -38,6 +38,7 @@
         Gtk.Grid.__init__(self)
         self.set_orientation(Gtk.Orientation.VERTICAL)
         self.__tracks_view = None
+        self.__revealer = None
         self.__view_type = view_type
         self.__storage_type = storage_type
         self.__album = album
@@ -50,23 +51,25 @@
         """
             Populate widget
         """
-        self.__revealer = Gtk.Revealer.new()
-        self.__revealer.show()
-        self.__banner = AlbumBannerWidget(self.__album, self.__storage_type,
-                                          self.__view_type)
-        self.__banner.show()
-        self.__banner.connect("populated", self.__on_banner_populated)
-        self.__banner.populate()
-        self.add(self.__banner)
-        self.add(self.__revealer)
-        self.__gesture = GesturesHelper(self.__banner,
-                                        primary_press_callback=self._on_press)
-        self.get_style_context().add_class("album-banner")
-        if App().settings.get_value("show-artist-tracks"):
-            self.__revealer.set_transition_type(
-                Gtk.RevealerTransitionType.NONE)
-            self.__populate()
-        self.set_selection()
+        if self.__revealer is None:
+            self.__revealer = Gtk.Revealer.new()
+            self.__revealer.show()
+            self.__banner = AlbumBannerWidget(self.__album,
+                                              self.__storage_type,
+                                              self.__view_type)
+            self.__banner.show()
+            self.__banner.connect("populated", self.__on_banner_populated)
+            self.__banner.populate()
+            self.add(self.__banner)
+            self.add(self.__revealer)
+            self.__gesture = GesturesHelper(
+                self.__banner,  primary_press_callback=self._on_press)
+            self.get_style_context().add_class("album-banner")
+            if App().settings.get_value("show-artist-tracks"):
+                self.__revealer.set_transition_type(
+                    Gtk.RevealerTransitionType.NONE)
+                self.__populate()
+            self.set_selection()
 
     def reveal_child(self):
         """
@@ -103,6 +106,8 @@
             Get banner
             @return BannerWidget
         """
+        if self.__revealer is None:
+            self.populate()
         return self.__banner
 
     @property
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-1.4.9/lollypop/widgets_banner_album.py 
new/lollypop-1.4.12/lollypop/widgets_banner_album.py
--- old/lollypop-1.4.9/lollypop/widgets_banner_album.py 2021-01-10 
20:27:35.000000000 +0100
+++ new/lollypop-1.4.12/lollypop/widgets_banner_album.py        2021-01-17 
20:48:13.000000000 +0100
@@ -369,13 +369,15 @@
             Play album
            @param button as Gtk.Button
         """
-        App().player.play_album(self.__album.clone(False))
+        selected = button.get_state_flags() & Gtk.StateFlags.SELECTED
+        App().player.play_album(self.__album.clone(selected))
 
     def __on_add_button_clicked(self, button):
         """
             Add/Remove album
            @param button as Gtk.Button
         """
+        selected = button.get_state_flags() & Gtk.StateFlags.SELECTED
         add = self.__add_button.get_image().get_icon_name()[0] ==\
             "list-add-symbolic"
         albums = App().player.get_albums_for_id(self.__album.id)
@@ -393,7 +395,7 @@
                             break
                 emit_signal(App().player, "playback-updated", album)
         else:
-            App().player.add_album(self.__album.clone(False))
+            App().player.add_album(self.__album.clone(selected))
 
     def __on_year_clicked(self, label):
         """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lollypop-1.4.9/meson.build 
new/lollypop-1.4.12/meson.build
--- old/lollypop-1.4.9/meson.build      2021-01-10 20:27:35.000000000 +0100
+++ new/lollypop-1.4.12/meson.build     2021-01-17 20:48:13.000000000 +0100
@@ -1,5 +1,5 @@
 project('lollypop',
-  version: '1.4.9',
+  version: '1.4.12',
   meson_version: '>= 0.46.0'
 )
 revision = run_command('bin/revision.sh').stdout().strip()

Reply via email to