[gnome-music/wip/mschraal/core-thumb-property: 17/22] coresong: Add thumbnail property
- From: Marinus Schraal <mschraal src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-music/wip/mschraal/core-thumb-property: 17/22] coresong: Add thumbnail property
- Date: Thu, 2 Jul 2020 19:22:51 +0000 (UTC)
commit 42ffba1a3ca0400b9ef08bdc13b1e77e03714092
Author: Marinus Schraal <mschraal gnome org>
Date: Sun Jun 14 16:57:28 2020 +0200
coresong: Add thumbnail property
Use the same machinery as album and artist art for retrieval.
data/ui/PlayerToolbar.ui | 2 +-
gnomemusic/artcache.py | 7 ++-
gnomemusic/coregrilo.py | 8 +++
gnomemusic/coresong.py | 24 +++++++++
gnomemusic/grilowrappers/grltrackerwrapper.py | 40 +++++++++++++++
gnomemusic/songart.py | 72 +++++++++++++++++++++++++++
gnomemusic/storeart.py | 5 ++
gnomemusic/widgets/playertoolbar.py | 7 ++-
8 files changed, 158 insertions(+), 7 deletions(-)
---
diff --git a/data/ui/PlayerToolbar.ui b/data/ui/PlayerToolbar.ui
index 142a74fc..79c37bbc 100644
--- a/data/ui/PlayerToolbar.ui
+++ b/data/ui/PlayerToolbar.ui
@@ -120,7 +120,7 @@
<property name="spacing">8</property>
<signal name="query-tooltip" handler="_on_tooltip_query"/>
<child>
- <object class="CoverStack" id="_cover_stack">
+ <object class="ArtStack" id="_art_stack">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
diff --git a/gnomemusic/artcache.py b/gnomemusic/artcache.py
index 8627b938..28f29cdc 100644
--- a/gnomemusic/artcache.py
+++ b/gnomemusic/artcache.py
@@ -29,6 +29,7 @@ from gi.repository import Gdk, GdkPixbuf, Gio, Gtk, GLib, GObject
from gnomemusic.corealbum import CoreAlbum
from gnomemusic.coreartist import CoreArtist
+from gnomemusic.coresong import CoreSong
from gnomemusic.musiclogger import MusicLogger
@@ -203,7 +204,8 @@ class ArtCache(GObject.GObject):
self._default_icon = DefaultIcon().get(
DefaultIcon.Type.ARTIST, self._size, self._scale,
round_shape=True)
- elif isinstance(coreobject, CoreAlbum):
+ elif (isinstance(coreobject, CoreAlbum)
+ or isinstance(coreobject, CoreSong)):
self._loading_icon = DefaultIcon().get(
DefaultIcon.Type.LOADING, self._size, self._scale)
self._default_icon = DefaultIcon().get(
@@ -253,7 +255,8 @@ class ArtCache(GObject.GObject):
if isinstance(self._coreobject, CoreArtist):
surface = _make_icon_frame(
surface, self._size, self._scale, round_shape=True)
- elif isinstance(self._coreobject, CoreAlbum):
+ elif (isinstance(self._coreobject, CoreAlbum)
+ or isinstance(self._coreobject, CoreSong)):
surface = _make_icon_frame(surface, self._size, self._scale)
self.emit("result", surface)
diff --git a/gnomemusic/coregrilo.py b/gnomemusic/coregrilo.py
index cf78bd58..9ecc7a4d 100644
--- a/gnomemusic/coregrilo.py
+++ b/gnomemusic/coregrilo.py
@@ -204,6 +204,14 @@ class CoreGrilo(GObject.GObject):
self._wrappers["grl-tracker-source"].get_album_art_for_item(
coresong, callback)
+ def get_song_art(self, coresong):
+ """Retrieve song art for the given CoreSong
+
+ :param CoreSong coresong: CoreSong to retrieve art for
+ """
+ if "grl-tracker-source" in self._wrappers:
+ self._wrappers["grl-tracker-source"].get_song_art(coresong)
+
def get_album_art(self, corealbum):
"""Retrieve album art for the given CoreAlbum
diff --git a/gnomemusic/coresong.py b/gnomemusic/coresong.py
index eaa67fc5..76561675 100644
--- a/gnomemusic/coresong.py
+++ b/gnomemusic/coresong.py
@@ -28,6 +28,7 @@ import gi
gi.require_version('Grl', '0.3')
from gi.repository import Grl, GLib, GObject
+from gnomemusic.songart import SongArt
import gnomemusic.utils as utils
@@ -63,10 +64,12 @@ class CoreSong(GObject.GObject):
"""
super().__init__()
+ self._application = application
self._coregrilo = application.props.coregrilo
self._coreselection = application.props.coreselection
self._favorite = False
self._selected = False
+ self._thumbnail = None
self.props.grlid = media.get_source() + media.get_id()
self._is_tracker = media.get_source() == "grl-tracker-source"
@@ -116,6 +119,27 @@ class CoreSong(GObject.GObject):
self._selected = value
self._coreselection.update_selection(self, self._selected)
+ @GObject.Property(type=str, default=None)
+ def thumbnail(self):
+ """Song art thumbnail retrieval
+
+ :return: The song art location or "generic" or "loading"
+ :rtype: string
+ """
+ if self._thumbnail is None:
+ self._thumbnail = "loading"
+ SongArt(self._application, self)
+
+ return self._thumbnail
+
+ @thumbnail.setter
+ def thumbnail(self, value):
+ """Song art thumbnail setter
+
+ :param string value: path, "generic" or "loading"
+ """
+ self._thumbnail = value
+
def update(self, media):
self.props.media = media
self.props.album = utils.get_album_title(media)
diff --git a/gnomemusic/grilowrappers/grltrackerwrapper.py b/gnomemusic/grilowrappers/grltrackerwrapper.py
index 0482fde5..71ead33d 100644
--- a/gnomemusic/grilowrappers/grltrackerwrapper.py
+++ b/gnomemusic/grilowrappers/grltrackerwrapper.py
@@ -985,6 +985,46 @@ class GrlTrackerWrapper(GObject.GObject):
return query
+ def get_song_art(self, coresong):
+ """Retrieve song art for the given CoreSong
+
+ Since MediaArt does not really support per-song art this
+ uses the songs album information as base to retrieve relevant
+ art.
+
+ :param CoreSong coresong: CoreSong to get art for
+ """
+ media = coresong.props.media
+
+ def art_retrieved_cb(source, op_id, queried_media, remaining, error):
+ if error:
+ self._log.warning("Error: {}".format(error))
+ coresong.props.thumbnail = "generic"
+ return
+
+ if (remaining == 0
+ and queried_media is None):
+ coresong.props.thumbnail = "generic"
+ return
+
+ thumbnail_uri = queried_media.get_thumbnail()
+ if thumbnail_uri is None:
+ coresong.props.thumbnail = "generic"
+ else:
+ media.set_thumbnail(thumbnail_uri)
+ StoreArt(coresong)
+
+ song_id = media.get_id()
+ query = self._get_album_for_song_id(song_id)
+
+ full_options = Grl.OperationOptions()
+ full_options.set_resolution_flags(
+ Grl.ResolutionFlags.FULL | Grl.ResolutionFlags.IDLE_RELAY)
+
+ self.props.source.query(
+ query, self.METADATA_THUMBNAIL_KEYS, full_options,
+ art_retrieved_cb)
+
def get_album_art(self, corealbum):
"""Retrieve album art for the given CoreAlbum
diff --git a/gnomemusic/songart.py b/gnomemusic/songart.py
new file mode 100644
index 00000000..40c50107
--- /dev/null
+++ b/gnomemusic/songart.py
@@ -0,0 +1,72 @@
+# Copyright 2020 The GNOME Music developers
+#
+# GNOME Music is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GNOME Music is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with GNOME Music; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# The GNOME Music authors hereby grant permission for non-GPL compatible
+# GStreamer plugins to be used and distributed together with GStreamer
+# and GNOME Music. This permission is above and beyond the permissions
+# granted by the GPL license by which GNOME Music is covered. If you
+# modify this code, you may extend this exception to your version of the
+# code, but you are not obligated to do so. If you do not wish to do so,
+# delete this exception statement from your version.
+
+import gi
+gi.require_version("MediaArt", "2.0")
+from gi.repository import GObject, MediaArt
+
+from gnomemusic.embeddedart import EmbeddedArt
+
+
+class SongArt(GObject.GObject):
+ """SongArt retrieval object
+ """
+
+ def __init__(self, application, coresong):
+ """Initialize SongArt
+
+ :param Application application: The application object
+ :param CoreSong coresong: The coresong to use
+ """
+ super().__init__()
+
+ self._application = application
+ self._coresong = coresong
+ self._album = self._coresong.props.album
+ self._artist = self._coresong.props.artist
+
+ if self._in_cache():
+ return
+
+ embedded = EmbeddedArt()
+ embedded.connect("art-found", self._on_embedded_art_found)
+ embedded.query(coresong, self._album)
+
+ def _on_embedded_art_found(self, embeddedart, found):
+ if found:
+ self._in_cache()
+ else:
+ self._application.props.coregrilo.get_song_art(self._coresong)
+
+ def _in_cache(self):
+ success, thumb_file = MediaArt.get_file(
+ self._artist, self._album, "album")
+ if (not success
+ or not thumb_file.query_exists()):
+ self._coresong.props.thumbnail = "loading"
+ return False
+
+ self._coresong.props.thumbnail = thumb_file.get_path()
+
+ return True
diff --git a/gnomemusic/storeart.py b/gnomemusic/storeart.py
index 6f0f6595..c397b083 100644
--- a/gnomemusic/storeart.py
+++ b/gnomemusic/storeart.py
@@ -29,6 +29,7 @@ from gi.repository import Gio, GLib, GObject, MediaArt, Soup
from gnomemusic.musiclogger import MusicLogger
from gnomemusic.coreartist import CoreArtist
from gnomemusic.corealbum import CoreAlbum
+from gnomemusic.coresong import CoreSong
class StoreArt(GObject.Object):
@@ -127,6 +128,10 @@ class StoreArt(GObject.Object):
success, cache_path = MediaArt.get_path(
self._coreobject.props.artist, self._coreobject.props.title,
"album")
+ elif isinstance(self._coreobject, CoreSong):
+ success, cache_path = MediaArt.get_path(
+ self._coreobject.props.artist, self._coreobject.props.album,
+ "album")
else:
success = False
diff --git a/gnomemusic/widgets/playertoolbar.py b/gnomemusic/widgets/playertoolbar.py
index e060f02d..ba72f7af 100644
--- a/gnomemusic/widgets/playertoolbar.py
+++ b/gnomemusic/widgets/playertoolbar.py
@@ -28,7 +28,6 @@ from gi.repository import GObject, Gtk
from gnomemusic.albumartcache import Art
from gnomemusic.gstplayer import Playback
from gnomemusic.player import Player, RepeatMode
-from gnomemusic.widgets.coverstack import CoverStack # noqa: F401
from gnomemusic.widgets.smoothscale import SmoothScale # noqa: F401
from gnomemusic.widgets.twolinetip import TwoLineTip
import gnomemusic.utils as utils
@@ -44,7 +43,7 @@ class PlayerToolbar(Gtk.ActionBar):
__gtype_name__ = 'PlayerToolbar'
_artist_label = Gtk.Template.Child()
- _cover_stack = Gtk.Template.Child()
+ _art_stack = Gtk.Template.Child()
_duration_label = Gtk.Template.Child()
_next_button = Gtk.Template.Child()
_pause_image = Gtk.Template.Child()
@@ -69,7 +68,7 @@ class PlayerToolbar(Gtk.ActionBar):
self._player = None
- self._cover_stack.props.size = Art.Size.XSMALL
+ self._art_stack.props.size = Art.Size.XSMALL
self._tooltip = TwoLineTip()
@@ -177,7 +176,7 @@ class PlayerToolbar(Gtk.ActionBar):
self._tooltip.props.title = title
self._tooltip.props.subtitle = artist
- self._cover_stack.update(coresong)
+ self._art_stack.props.coreobject = coresong
@Gtk.Template.Callback()
def _on_tooltip_query(self, widget, x, y, kb, tooltip, data=None):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]