[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: Sat, 6 Jan 2018 00:54:52 +0000 (UTC)
commit db5ac462ffdce5f21a07accbae3a3d9eb41ec3c6
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 | 19 ++--------
7 files changed, 99 insertions(+), 93 deletions(-)
---
diff --git a/gnomemusic/albumartcache.py b/gnomemusic/albumartcache.py
index 89a1611..38ab0ca 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 bbc0474..b5b594a 100644
--- a/gnomemusic/player.py
+++ b/gnomemusic/player.py
@@ -42,7 +42,7 @@ from gi.repository import Gtk, Gdk, GLib, Gio, GObject, Gst, GstAudio, GstPbutil
from gettext import gettext as _, ngettext
from random import randint
from collections import deque
-from gnomemusic.albumartcache import AlbumArtCache, DefaultIcon, ArtSize
+from gnomemusic.albumartcache import Art, ArtSize
from gnomemusic.grilo import grilo
from gnomemusic.playlists import Playlists
import gnomemusic.utils as utils
@@ -110,11 +110,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)
@@ -604,8 +599,7 @@ class Player(GObject.GObject):
self.artistLabel.set_label(artist)
self._currentArtist = 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)
self._currentTitle = utils.get_media_title(media)
self.titleLabel.set_label(self._currentTitle)
@@ -659,7 +653,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
@@ -802,9 +796,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 3d53baf..1a687e7 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]
@@ -196,6 +189,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:
@@ -246,13 +243,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, 13],
- [str(item.get_id()), title, artist, self._loading_icon, item,
- 2, category, composer])
- self._cache.lookup(
- item, ArtSize.SMALL, self._on_lookup_ready, _iter)
+ [str(item.get_id()), title, artist, art.pixbuf, item, 2,
+ category, composer])
elif category == 'song':
# FIXME: source specific hack
if source.get_id() != 'grl-tracker-source':
@@ -261,24 +258,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, 13],
- [str(item.get_id()), title, artist, self._loading_icon, item,
- fav, category, composer])
- self._cache.lookup(
- item, ArtSize.SMALL, self._on_lookup_ready, _iter)
+ [str(item.get_id()), title, artist, art.pixbuf, item, fav,
+ category, composer])
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, 13],
- [str(item.get_id()), artist, self._loading_icon, item, 2,
+ [str(item.get_id()), artist, art.pixbuf, item, 2,
category, composer])
- 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..9289683 100644
--- a/gnomemusic/widgets/artistalbumwidget.py
+++ b/gnomemusic/widgets/artistalbumwidget.py
@@ -25,7 +25,7 @@
from gi.repository import 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
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]