[gnome-music/wip/jfelder/untangle-mpris-playertoolbar] mpris: Untangle MPRIS and playertoolbar
- From: Jean Felder <jfelder src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-music/wip/jfelder/untangle-mpris-playertoolbar] mpris: Untangle MPRIS and playertoolbar
- Date: Sat, 1 Jun 2019 21:53:36 +0000 (UTC)
commit 61573a2dc674c5a1728959a1aa14cbec8fb77f44
Author: Jean Felder <jfelder src gnome org>
Date: Wed Apr 10 19:45:27 2019 +0200
mpris: Untangle MPRIS and playertoolbar
MPRIS is tied with PlayerToolbar because the thumbnail updating logic
takes place in the CoverStack from PlayerToolbar.
In fact, on every song change the following thing happens:
* PlayerToolbar looks up for the song's thumbnail (via its
cover_stack) and emits a "thumbnail-updated" signal once the
operation is finished.
* MPRIS sends the song's metadata without the thumbnail url (it has
not been updated yet). A bit later, once the "thumbnail-updated"
signal is received, the metadata are sent again with the correct
thumbnail url.
This can result in a glitter on some MPRIS clients: the client is
updated with an empty thumbnail, and then, very quickly, with the
correct one.
Fix that issue by factoring out the thumbnail cache lookup and
directly looking up the song thumbnail from MPRIS. The disadvantage of
this solution is that the lookup_art_file_from_cache function is
called two times on a song change. One call from PlayerToolbar and the
other one from mpris. However, this function call is less costy than
sending two times the song's metadata.
Related: #43, #172
Closes: #101
gnomemusic/albumartcache.py | 41 +++++++++++++++++++------------------
gnomemusic/mpris.py | 25 +++++++++++-----------
gnomemusic/widgets/playertoolbar.py | 9 --------
3 files changed, 34 insertions(+), 41 deletions(-)
---
diff --git a/gnomemusic/albumartcache.py b/gnomemusic/albumartcache.py
index 01561f7e..e9f60826 100644
--- a/gnomemusic/albumartcache.py
+++ b/gnomemusic/albumartcache.py
@@ -42,6 +42,25 @@ import gnomemusic.utils as utils
logger = logging.getLogger(__name__)
+@log
+def lookup_art_file_from_cache(media):
+ """Lookup MediaArt cache art of an album or song.
+
+ :param Grl.Media media: song or album
+ :returns: a cache file
+ :rtype: Gio.File
+ """
+ album = utils.get_album_title(media)
+ artist = utils.get_artist_name(media)
+
+ success, thumb_file = MediaArt.get_file(artist, album, "album")
+ if (not success
+ or not thumb_file.query_exists()):
+ return None
+
+ return thumb_file
+
+
@log
def _make_icon_frame(icon_surface, art_size=None, scale=1, default_icon=False):
border = 3
@@ -213,7 +232,6 @@ class Art(GObject.GObject):
pixbuf, self._scale, None)
surface = _make_icon_frame(surface, self._size, self._scale)
self._surface = surface
- self._set_grilo_thumbnail_path()
self.emit('finished')
@@ -284,18 +302,6 @@ class Art(GObject.GObject):
return False
- def _set_grilo_thumbnail_path(self):
- # TODO: This sets the thumbnail path for the Grilo Media object
- # to be used by MPRIS. However, calling this by default for
- # every cache hit is unnecessary.
- album = utils.get_album_title(self._media)
- artist = utils.get_artist_name(self._media)
-
- success, thumb_file = MediaArt.get_file(artist, album, "album")
- if success:
- self._media.set_thumbnail(
- GLib.filename_to_uri(thumb_file.get_path(), None))
-
@GObject.Property
def surface(self):
if self._surface is None:
@@ -339,13 +345,8 @@ class Cache(GObject.GObject):
:param Grl.Media media: The media object to search art for
"""
- album = utils.get_album_title(media)
- artist = utils.get_artist_name(media)
-
- success, thumb_file = MediaArt.get_file(artist, album, "album")
-
- if (success
- and thumb_file.query_exists()):
+ thumb_file = lookup_art_file_from_cache(media)
+ if thumb_file:
thumb_file.read_async(
GLib.PRIORITY_LOW, None, self._open_stream, None)
return
diff --git a/gnomemusic/mpris.py b/gnomemusic/mpris.py
index b74c4c53..4a8fcf15 100644
--- a/gnomemusic/mpris.py
+++ b/gnomemusic/mpris.py
@@ -23,6 +23,7 @@
# 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 gnomemusic.albumartcache import lookup_art_file_from_cache
from gnomemusic.gstplayer import Playback
from gnomemusic.player import PlayerPlaylist, RepeatMode
from gnomemusic.grilo import grilo
@@ -243,9 +244,6 @@ class MediaPlayer2Service(Server):
self.player.connect('seek-finished', self._on_seek_finished)
self.player.connect(
'playlist-changed', self._on_player_playlist_changed)
- self.player_toolbar = app.get_active_window()._player_toolbar
- self.player_toolbar.connect(
- 'thumbnail-updated', self._on_thumbnail_updated)
self._playlists = Playlists.get_default()
self._playlists.connect(
'playlist-created', self._on_playlists_count_changed)
@@ -315,8 +313,19 @@ class MediaPlayer2Service(Server):
last_played_str = last_played.format("%FT%T%:z")
metadata['xesam:lastUsed'] = GLib.Variant('s', last_played_str)
+ # If the media has already been part of an MPRIS playlist, its
+ # thumbnail is already set. Otherwise, try to look for it in the
+ # cache directory and set the media thumbnail for a future use.
+ # The search is only through the cache to prevent any delayed
+ # loading.
art_url = media.get_thumbnail()
- if art_url is not None:
+ if not art_url:
+ thumb_file = lookup_art_file_from_cache(media)
+ if thumb_file:
+ art_url = GLib.filename_to_uri(thumb_file.get_path())
+ media.set_thumbnail(art_url)
+
+ if art_url:
metadata['mpris:artUrl'] = GLib.Variant('s', art_url)
return metadata
@@ -451,14 +460,6 @@ class MediaPlayer2Service(Server):
},
[])
- @log
- def _on_thumbnail_updated(self, player, data=None):
- self.PropertiesChanged(MediaPlayer2Service.MEDIA_PLAYER2_PLAYER_IFACE,
- {
- 'Metadata': GLib.Variant('a{sv}', self._get_metadata()),
- },
- [])
-
@log
def _on_player_state_changed(self, klass, args):
playback_status = self._get_playback_status()
diff --git a/gnomemusic/widgets/playertoolbar.py b/gnomemusic/widgets/playertoolbar.py
index 311f74b4..de11eb93 100644
--- a/gnomemusic/widgets/playertoolbar.py
+++ b/gnomemusic/widgets/playertoolbar.py
@@ -42,10 +42,6 @@ class PlayerToolbar(Gtk.ActionBar):
Contains the ui of playing a song with Music.
"""
- __gsignals__ = {
- 'thumbnail-updated': (GObject.SignalFlags.RUN_FIRST, None, ()),
- }
-
__gtype_name__ = 'PlayerToolbar'
_artist_label = Gtk.Template.Child()
@@ -79,7 +75,6 @@ class PlayerToolbar(Gtk.ActionBar):
self._player = None
self._cover_stack.props.size = Art.Size.XSMALL
- self._cover_stack.connect('updated', self._on_cover_stack_updated)
self._tooltip = TwoLineTip()
@@ -121,10 +116,6 @@ class PlayerToolbar(Gtk.ActionBar):
seconds = int(progress_scale.get_value() / 60)
self._progress_time_label.set_label(utils.seconds_to_string(seconds))
- @log
- def _on_cover_stack_updated(self, klass):
- self.emit('thumbnail-updated')
-
@Gtk.Template.Callback()
@log
def _on_prev_button_clicked(self, button):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]