[gnome-music/wip/mschraal/core-thumb-property: 12/19] Restore embedded art support
- From: Jean Felder <jfelder src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-music/wip/mschraal/core-thumb-property: 12/19] Restore embedded art support
- Date: Mon, 6 Jul 2020 09:07:28 +0000 (UTC)
commit ddf5b6b43e751fa5702162c38cc33aa94e0ca67a
Author: Marinus Schraal <mschraal gnome org>
Date: Sun Jun 14 23:09:36 2020 +0200
Restore embedded art support
gnomemusic/albumart.py | 13 +++-
gnomemusic/embeddedart.py | 181 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 193 insertions(+), 1 deletion(-)
---
diff --git a/gnomemusic/albumart.py b/gnomemusic/albumart.py
index 84008a35..2d3f14eb 100644
--- a/gnomemusic/albumart.py
+++ b/gnomemusic/albumart.py
@@ -26,6 +26,8 @@ import gi
gi.require_version("MediaArt", "2.0")
from gi.repository import GObject, MediaArt
+from gnomemusic.embeddedart import EmbeddedArt
+
class AlbumArt(GObject.GObject):
"""AlbumArt retrieval object
@@ -39,6 +41,7 @@ class AlbumArt(GObject.GObject):
"""
super().__init__()
+ self._application = application
self._corealbum = corealbum
self._album = self._corealbum.props.title
self._artist = self._corealbum.props.artist
@@ -46,7 +49,15 @@ class AlbumArt(GObject.GObject):
if self._in_cache():
return
- application.props.coregrilo.get_album_art(self._corealbum)
+ embedded = EmbeddedArt()
+ embedded.connect("art-found", self._on_embedded_art_found)
+ embedded.query(corealbum, self._album)
+
+ def _on_embedded_art_found(self, embeddedart, found):
+ if found:
+ self._in_cache()
+ else:
+ self._application.props.coregrilo.get_album_art(self._corealbum)
def _in_cache(self):
success, thumb_file = MediaArt.get_file(
diff --git a/gnomemusic/embeddedart.py b/gnomemusic/embeddedart.py
new file mode 100644
index 00000000..7ef4f93d
--- /dev/null
+++ b/gnomemusic/embeddedart.py
@@ -0,0 +1,181 @@
+# 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_versions({"GstPbutils": "1.0", "GstTag": "1.0", "MediaArt": "2.0"})
+from gi.repository import GLib, GObject, MediaArt, Gst, GstTag, GstPbutils
+
+from gnomemusic.musiclogger import MusicLogger
+
+
+class EmbeddedArt(GObject.GObject):
+ """Lookup local art
+
+ 1. Embedded art using GStreamer
+ 2. Available in the directory using MediaArt
+ """
+
+ _log = MusicLogger()
+
+ __gsignals__ = {
+ "art-found": (GObject.SignalFlags.RUN_FIRST, None, (bool, ))
+ }
+
+ def __init__(self):
+ """Initialize EmbeddedArt
+ """
+ super().__init__()
+
+ try:
+ Gst.init(None)
+ GstPbutils.pb_utils_init()
+ except GLib.Error as error:
+ self._log.warning(
+ "Error: {}, {}".format(error.domain, error.message))
+ return
+
+ self._media_art = MediaArt.Process.new()
+
+ self._album = None
+ self._artist = None
+ self._coreobject = None
+ self._path = None
+
+ def query(self, coreobject, title):
+ """Start the local query
+
+ :param coreobject: The CoreAlbum or CoreSong to search art for
+ :param str title: The album title for the CoreAlbum or CoreSong
+ """
+ self._album = title
+ self._artist = coreobject.props.artist
+ self._coreobject = coreobject
+
+ try:
+ if coreobject.props.url is None:
+ self.emit("art-found", False)
+ return
+ except AttributeError:
+ self.emit("art-found", False)
+ return
+
+ try:
+ discoverer = GstPbutils.Discoverer.new(Gst.SECOND)
+ except GLib.Error as error:
+ self._log.warning(
+ "Error: {}, {}".format(error.domain, error.message))
+ self._lookup_cover_in_directory()
+ return
+
+ discoverer.connect("discovered", self._discovered)
+ discoverer.start()
+
+ success, path = MediaArt.get_path(self._artist, self._album, "album")
+
+ if not success:
+ self.emit("art-found", False)
+ discoverer.stop()
+ return
+
+ self._path = path
+
+ success = discoverer.discover_uri_async(self._coreobject.props.url)
+
+ if not success:
+ self._log.warning("Could not add url to discoverer.")
+ self.emit("art-found", False)
+ discoverer.stop()
+ return
+
+ def _discovered(self, discoverer, info, error):
+ tags = info.get_tags()
+ index = 0
+
+ if (error is not None
+ or tags is None):
+ if error:
+ self._log.warning("Discoverer error: {}, {}".format(
+ Gst.CoreError(error.code), error.message))
+ discoverer.stop()
+ self.emit("art-found", False)
+ return
+
+ while True:
+ success, sample = tags.get_sample_index(Gst.TAG_IMAGE, index)
+ if not success:
+ break
+ index += 1
+ struct = sample.get_info()
+ if struct is None:
+ break
+ success, image_type = struct.get_enum(
+ "image-type", GstTag.TagImageType)
+ if not success:
+ continue
+ if image_type != GstTag.TagImageType.FRONT_COVER:
+ continue
+
+ buf = sample.get_buffer()
+ success, map_info = buf.map(Gst.MapFlags.READ)
+ if not success:
+ continue
+
+ try:
+ mime = sample.get_caps().get_structure(0).get_name()
+ MediaArt.buffer_to_jpeg(map_info.data, mime, self._path)
+ discoverer.stop()
+ self.emit("art-found", True)
+ return
+ except GLib.Error as error:
+ self._log.warning("Error: {}, {}".format(
+ MediaArt.Error(error.code), error.message))
+
+ discoverer.stop()
+
+ self._lookup_cover_in_directory()
+
+ def _lookup_cover_in_directory(self):
+ # Find local art in cover.jpeg files.
+ self._media_art.uri_async(
+ MediaArt.Type.ALBUM, MediaArt.ProcessFlags.NONE,
+ self._coreobject.props.url, self._artist, self._album,
+ GLib.PRIORITY_LOW, None, self._uri_async_cb, None)
+
+ def _uri_async_cb(self, src, result, data):
+ try:
+ success = self._media_art.uri_finish(result)
+ if success:
+ self.emit("art-found", True)
+ return
+ except GLib.Error as error:
+ if MediaArt.Error(error.code) == MediaArt.Error.SYMLINK_FAILED:
+ # This error indicates that the coverart has already
+ # been linked by another concurrent lookup.
+ self.emit("art-found", True)
+ return
+ else:
+ self._log.warning("Error: {}, {}".format(
+ MediaArt.Error(error.code), error.message))
+
+ self.emit("art-found", False)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]