[gnome-music/wip/mschraal/artrework: 1/3] albumartcache: Rework art retrieval
- From: Marinus Schraal <mschraal src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-music/wip/mschraal/artrework: 1/3] albumartcache: Rework art retrieval
- Date: Sun, 14 Jan 2018 14:48:56 +0000 (UTC)
commit ccf6a087293a9b6ae91f2bc8f88a718a8e2576a4
Author: Marinus Schraal <mschraal gnome org>
Date: Fri Jan 5 13:54:49 2018 +0100
albumartcache: Rework art retrieval
The basic idea is to pass the image to the art class with the media
info, so it can update the contents at will.
This works fine for GtkImage, but treeviews require an alternate
approach with a signal because it only accepts GdkPixbuf and
cellrenderers do not update by themselves.
cleans art logic from views/widgets
FIXME: does trigger too many open files crashes on large sets
gnomemusic/albumartcache.py | 61 +++++++++++++++++++++++++++++++++
gnomemusic/player.py | 16 +++------
gnomemusic/views/albumsview.py | 14 ++------
gnomemusic/views/baseview.py | 24 +++++++------
gnomemusic/views/searchview.py | 36 ++++++++-----------
gnomemusic/widgets/albumwidget.py | 22 ++----------
gnomemusic/widgets/artistalbumwidget.py | 21 ++----------
7 files changed, 100 insertions(+), 94 deletions(-)
---
diff --git a/gnomemusic/albumartcache.py b/gnomemusic/albumartcache.py
index f9954ca..2758b20 100644
--- a/gnomemusic/albumartcache.py
+++ b/gnomemusic/albumartcache.py
@@ -218,6 +218,67 @@ class DefaultIcon(GObject.GObject):
return self._cache[(icon_type, art_size)]
+class Art(GObject.GObject):
+
+ __gsignals__ = {
+ 'finished': (GObject.SignalFlags.RUN_FIRST, None, ())
+ }
+
+ @log
+ def __init__(self, image, size, media):
+ super().__init__()
+
+ self._iter = None
+
+ # FIXME: A pixbuf instead of an image means this art is
+ # requested by a treeview.
+ if isinstance(image, GdkPixbuf.Pixbuf):
+ self._pixbuf = image
+ self._image = Gtk.Image()
+ else:
+ self._image = image
+
+ self._size = size
+ self._media = media
+
+ self._image.set_property("width-request", size.width)
+ self._image.set_property("height-request", size.height)
+
+ scale = self._image.get_scale_factor()
+
+ self._surface = DefaultIcon(scale).get(DefaultIcon.Type.loading, size)
+
+ self._image.set_from_surface(self._surface)
+
+ cache = AlbumArtCache(scale)
+
+ iter_ = None
+ cache.lookup(self._media, self._size, self._callback, iter_)
+
+ @GObject.Property
+ @log
+ def pixbuf(self):
+ return Gdk.pixbuf_get_from_surface(
+ self._surface, 0, 0, self._surface.get_width(),
+ self._surface.get_height())
+
+ @GObject.Property(type=Gtk.TreeIter)
+ @log
+ def iter(self):
+ return self._iter
+
+ @iter.setter
+ @log
+ def iter(self, iter_):
+ self._iter = iter_
+
+ @log
+ def _callback(self, surface, __):
+ self._surface = surface
+ self._image.set_from_surface(self._surface)
+
+ self.emit('finished')
+
class AlbumArtCache(GObject.GObject):
"""Album art retrieval class
diff --git a/gnomemusic/player.py b/gnomemusic/player.py
index d8798d2..c755850 100644
--- a/gnomemusic/player.py
+++ b/gnomemusic/player.py
@@ -46,7 +46,7 @@ from gi.repository import Gtk, Gdk, GLib, Gio, GObject, Gst, GstAudio, GstPbutil
from gettext import gettext as _, ngettext
from gnomemusic import log
-from gnomemusic.albumartcache import AlbumArtCache, DefaultIcon, ArtSize
+from gnomemusic.albumartcache import Art, ArtSize
from gnomemusic.grilo import grilo
from gnomemusic.playlists import Playlists
from gnomemusic.scrobbler import LastFmScrobbler
@@ -109,11 +109,6 @@ class Player(GObject.GObject):
self.playlistField = None
self.currentTrack = None
self.currentTrackUri = None
- scale = parent_window.get_scale_factor()
- self.cache = AlbumArtCache(scale)
- self._loading_icon_surface = DefaultIcon(scale).get(
- DefaultIcon.Type.loading,
- ArtSize.XSMALL)
self._missingPluginMessages = []
Gst.init(None)
@@ -584,8 +579,7 @@ class Player(GObject.GObject):
artist = utils.get_artist_name(media)
self.artistLabel.set_label(artist)
- self.coverImg.set_from_surface(self._loading_icon_surface)
- self.cache.lookup(media, ArtSize.XSMALL, self._on_cache_lookup, None)
+ Art(self._image, ArtSize.XSMALL, media)
title = utils.get_media_title(media)
self.titleLabel.set_label(title)
@@ -639,7 +633,7 @@ class Player(GObject.GObject):
@log
def _on_cache_lookup(self, surface, data=None):
- self.coverImg.set_from_surface(surface)
+ # FIXME: Need this for mpris
self.emit('thumbnail-updated')
@log
@@ -780,9 +774,7 @@ class Player(GObject.GObject):
self.songTotalTimeLabel = self._ui.get_object('duration')
self.titleLabel = self._ui.get_object('title')
self.artistLabel = self._ui.get_object('artist')
- self.coverImg = self._ui.get_object('cover')
- self.coverImg.set_property("width-request", ArtSize.XSMALL.width)
- self.coverImg.set_property("height-request", ArtSize.XSMALL.height)
+ self._image = self._ui.get_object('cover')
self.duration = self._ui.get_object('duration')
self.repeatBtnImage = self._ui.get_object('playlistRepeat')
diff --git a/gnomemusic/views/albumsview.py b/gnomemusic/views/albumsview.py
index bdd83a7..b20b316 100644
--- a/gnomemusic/views/albumsview.py
+++ b/gnomemusic/views/albumsview.py
@@ -26,7 +26,7 @@ from gettext import gettext as _
from gi.repository import GLib, GObject, Gtk, Gdk
from gnomemusic import log
-from gnomemusic.albumartcache import ArtSize
+from gnomemusic.albumartcache import Art, ArtSize
from gnomemusic.grilo import grilo
from gnomemusic.toolbar import ToolbarState
from gnomemusic.views.baseview import BaseView
@@ -166,13 +166,6 @@ class AlbumsView(BaseView):
child.title.set_label(title)
child.subtitle.set_label(artist)
- child.image.set_from_surface(self._loading_icon_surface)
- # In the case of off-sized icons (eg. provided in the soundfile)
- # keep the size request equal to all other icons to get proper
- # alignment with GtkFlowBox.
- child.image.set_property("width-request", ArtSize.MEDIUM.width)
- child.image.set_property("height-request", ArtSize.MEDIUM.height)
-
child.events.add_events(Gdk.EventMask.TOUCH_MASK)
child.events.connect('button-release-event',
@@ -189,7 +182,7 @@ class AlbumsView(BaseView):
child.add(builder.get_object('main_box'))
child.show()
- self._cache.lookup(item, ArtSize.MEDIUM, self._on_lookup_ready, child)
+ Art(child.image, ArtSize.MEDIUM, item)
return child
@@ -200,9 +193,6 @@ class AlbumsView(BaseView):
if self.selection_mode:
child.check.set_active(True)
- def _on_lookup_ready(self, icon, child):
- child.image.set_from_surface(icon)
-
@log
def _on_child_toggled(self, check, pspec, child):
if (check.get_active()
diff --git a/gnomemusic/views/baseview.py b/gnomemusic/views/baseview.py
index 7f5489c..1a6583b 100644
--- a/gnomemusic/views/baseview.py
+++ b/gnomemusic/views/baseview.py
@@ -26,7 +26,7 @@ from gettext import gettext as _, ngettext
from gi.repository import Gd, Gdk, GdkPixbuf, GObject, Gtk
from gnomemusic import log
-from gnomemusic.albumartcache import AlbumArtCache, DefaultIcon, ArtSize
+from gnomemusic.albumartcache import Art, ArtSize
from gnomemusic.grilo import grilo
from gnomemusic.widgets.starhandlerwidget import StarHandlerWidget
import gnomemusic.utils as utils
@@ -107,11 +107,6 @@ class BaseView(Gtk.Stack):
self.show_all()
self._view.hide()
- scale = self.get_scale_factor()
- self._cache = AlbumArtCache(scale)
- self._loading_icon_surface = DefaultIcon(scale).get(
- DefaultIcon.Type.loading, ArtSize.MEDIUM)
-
self._init = False
grilo.connect('ready', self._on_grilo_ready)
self._header_bar.connect('selection-mode-changed',
@@ -213,8 +208,13 @@ class BaseView(Gtk.Stack):
def populate(self):
pass
+ @log
+ def _retrieval_finished(self, klass):
+ self.model[klass.iter][4] = klass.pixbuf
+
@log
def _add_item(self, source, param, item, remaining=0, data=None):
+ print("add item")
if not item:
if remaining == 0:
self._view.set_model(self.model)
@@ -226,22 +226,24 @@ class BaseView(Gtk.Stack):
title = utils.get_media_title(item)
itr = self.model.append(None)
- loading_icon = Gdk.pixbuf_get_from_surface(
- self._loadin_icon_surface, 0, 0,
- self._loading_icon_surface.get_width(),
- self._loading_icon_surface.get_height())
+
+ pixbuf = GdkPixbuf.Pixbuf()
+ art = Art(pixbuf, ArtSize.MEDIUM, item)
self.model[itr][0, 1, 2, 3, 4, 5, 7, 9] = [
str(item.get_id()),
'',
title,
artist,
- loading_icon,
+ art,
item,
0,
False
]
+ art.iter = itr
+ art.connect('finished', self._retrieval_finished)
+
@log
def _on_lookup_ready(self, surface, itr):
if surface:
diff --git a/gnomemusic/views/searchview.py b/gnomemusic/views/searchview.py
index 592ed06..b3a9f7b 100644
--- a/gnomemusic/views/searchview.py
+++ b/gnomemusic/views/searchview.py
@@ -23,9 +23,9 @@
# delete this exception statement from your version.
from gettext import gettext as _
-from gi.repository import Gd, Gdk, GdkPixbuf, GObject, Grl, Gtk, Pango
+from gi.repository import Gd, GdkPixbuf, GObject, Grl, Gtk, Pango
-from gnomemusic.albumartcache import DefaultIcon, ArtSize
+from gnomemusic.albumartcache import Art, ArtSize
from gnomemusic.grilo import grilo
from gnomemusic import log
from gnomemusic.player import DiscoveryStatus
@@ -54,13 +54,6 @@ class SearchView(BaseView):
def __init__(self, window, player):
super().__init__('search', None, window, Gd.MainViewType.LIST)
- scale = self.get_scale_factor()
- loading_icon_surface = DefaultIcon(scale).get(
- DefaultIcon.Type.loading, ArtSize.SMALL)
- self._loading_icon = Gdk.pixbuf_get_from_surface(
- loading_icon_surface, 0, 0, loading_icon_surface.get_width(),
- loading_icon_surface.get_height())
-
self._add_list_renderers()
self.player = player
self._head_iters = [None, None, None, None]
@@ -194,6 +187,10 @@ class SearchView(BaseView):
self._albums[key].songs.append(item)
self._add_item(source, None, item, 0, [self.model, 'song'])
+ @log
+ def _retrieval_finished(self, klass):
+ self.model[klass.iter][4] = klass.pixbuf
+
@log
def _add_item(self, source, param, item, remaining=0, data=None):
if data is None:
@@ -242,13 +239,13 @@ class SearchView(BaseView):
# scaled by GdkPixbuf, so it results in a * scale factor sized
# icon for the search view.
_iter = None
+ image = GdkPixbuf.Pixbuf()
+ art = Art(image, ArtSize.SMALL, item)
if category == 'album':
_iter = self.model.insert_with_values(
self._head_iters[group], -1, [0, 2, 3, 4, 5, 9, 11],
- [str(item.get_id()), title, artist, self._loading_icon, item,
- 2, category])
- self._cache.lookup(
- item, ArtSize.SMALL, self._on_lookup_ready, _iter)
+ [str(item.get_id()), title, artist, art.pixbuf, item, 2,
+ category])
elif category == 'song':
# FIXME: source specific hack
if source.get_id() != 'grl-tracker-source':
@@ -257,24 +254,21 @@ class SearchView(BaseView):
fav = item.get_favourite()
_iter = self.model.insert_with_values(
self._head_iters[group], -1, [0, 2, 3, 4, 5, 9, 11],
- [str(item.get_id()), title, artist, self._loading_icon, item,
- fav, category])
- self._cache.lookup(
- item, ArtSize.SMALL, self._on_lookup_ready, _iter)
+ [str(item.get_id()), title, artist, art.pixbuf, item, fav,
+ category])
else:
if not artist.casefold() in self._artists:
_iter = self.model.insert_with_values(
self._head_iters[group], -1, [0, 2, 4, 5, 9, 11],
- [str(item.get_id()), artist, self._loading_icon, item, 2,
+ [str(item.get_id()), artist, art.pixbuf, item, 2,
category])
- self._cache.lookup(
- item, ArtSize.SMALL, self._on_lookup_ready, _iter)
self._artists[artist.casefold()] = {
'iter': _iter,
'albums': []
}
-
self._artists[artist.casefold()]['albums'].append(item)
+ art.iter = _iter
+ art.connect('finished', self._retrieval_finished)
if self.model.iter_n_children(self._head_iters[group]) == 1:
path = self.model.get_path(self._head_iters[group])
diff --git a/gnomemusic/widgets/albumwidget.py b/gnomemusic/widgets/albumwidget.py
index 5f6841c..0167867 100644
--- a/gnomemusic/widgets/albumwidget.py
+++ b/gnomemusic/widgets/albumwidget.py
@@ -26,7 +26,7 @@ from gettext import gettext as _, ngettext
from gi.repository import GdkPixbuf, GLib, GObject, Gtk
from gnomemusic import log
-from gnomemusic.albumartcache import AlbumArtCache, DefaultIcon, ArtSize
+from gnomemusic.albumartcache import Art, ArtSize
from gnomemusic.grilo import grilo
from gnomemusic.widgets.disclistboxwidget import DiscBox, DiscListBox
import gnomemusic.utils as utils
@@ -55,12 +55,6 @@ class AlbumWidget(Gtk.EventBox):
self._songs = []
- scale = self.get_scale_factor()
- self._cache = AlbumArtCache(scale)
- self._loading_icon_surface = DefaultIcon(scale).get(
- DefaultIcon.Type.loading,
- ArtSize.LARGE)
-
self._player = player
self._iter_to_clean = None
@@ -143,10 +137,8 @@ class AlbumWidget(Gtk.EventBox):
self.selection_toolbar = selection_toolbar
self._header_bar = header_bar
self._album = album
- self._builder.get_object('cover').set_from_surface(
- self._loading_icon_surface)
- self._cache.lookup(item, ArtSize.LARGE, self._on_lookup, None)
self._duration = 0
+ Art(self._builder.get_object('cover'), ArtSize.LARGE, item)
GLib.idle_add(grilo.populate_album_songs, item, self.add_item)
header_bar._select_button.connect(
@@ -289,16 +281,6 @@ class AlbumWidget(Gtk.EventBox):
self.show_all()
- @log
- def _on_lookup(self, surface, data=None):
- """Albumart retrieved callback.
-
- :param surface: The Cairo surface retrieved
- :param path: The filesystem location the pixbuf
- :param data: User data
- """
- self._builder.get_object('cover').set_from_surface(surface)
-
@log
def _update_model(self, player, playlist, current_iter):
"""Player changed callback.
diff --git a/gnomemusic/widgets/artistalbumwidget.py b/gnomemusic/widgets/artistalbumwidget.py
index 71bc01b..86fa72b 100644
--- a/gnomemusic/widgets/artistalbumwidget.py
+++ b/gnomemusic/widgets/artistalbumwidget.py
@@ -22,10 +22,10 @@
# code, but you are not obligated to do so. If you do not wish to do so,
# delete this exception statement from your version.
-from gi.repository import GLib, GObject, Gtk
+from gi.repository import GObject, Gtk
from gnomemusic import log
-from gnomemusic.albumartcache import AlbumArtCache, DefaultIcon, ArtSize
+from gnomemusic.albumartcache import Art, ArtSize
from gnomemusic.grilo import grilo
from gnomemusic.widgets.disclistboxwidget import DiscBox
import gnomemusic.utils as utils
@@ -48,11 +48,6 @@ class ArtistAlbumWidget(Gtk.Box):
self._size_group = size_group
self._cover_size_group = cover_size_group
- scale = self.get_scale_factor()
- self._cache = AlbumArtCache(scale)
- self._loading_icon_surface = DefaultIcon(scale).get(
- DefaultIcon.Type.loading,
- ArtSize.MEDIUM)
self._media = media
self._player = player
@@ -72,7 +67,7 @@ class ArtistAlbumWidget(Gtk.Box):
ui.add_from_resource('/org/gnome/Music/ArtistAlbumWidget.ui')
self.cover = ui.get_object('cover')
- self.cover.set_from_surface(self._loading_icon_surface)
+ Art(self.cover, ArtSize.MEDIUM, self._media)
self._disc_listbox = ui.get_object('disclistbox')
self._disc_listbox.set_selection_mode_allowed(
@@ -93,7 +88,6 @@ class ArtistAlbumWidget(Gtk.Box):
self.pack_start(ui.get_object('ArtistAlbumWidget'), True, True, 0)
- GLib.idle_add(self._update_album_art)
grilo.populate_album_songs(self._media, self._add_item)
def create_disc_box(self, disc_nr, disc_songs):
@@ -159,15 +153,6 @@ class ArtistAlbumWidget(Gtk.Box):
if remaining == 0:
self.emit("songs-loaded")
- @log
- def _update_album_art(self):
- self._cache.lookup(self._media, ArtSize.MEDIUM, self._get_album_cover,
- None)
-
- @log
- def _get_album_cover(self, surface, data=None):
- self.cover.set_from_surface(surface)
-
@log
def _song_activated(self, widget, song_widget):
if (not song_widget.can_be_played
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]