[rhythmbox] artdisplay: allow search engines to return tooltip details



commit 5752eb613457e791f48eb291e4b7547d2c45f71f
Author: Jonathan Matthew <jonathan d14n org>
Date:   Sun Mar 21 15:42:33 2010 +1000

    artdisplay: allow search engines to return tooltip details
    
    This allows an album art search to return a tooltip image and text to
    display along with the album art image.  The tooltip details are written
    to a simple text file alongside the cached art image, with the extension
    .rb-meta.  None of the existing searches uses this.

 .../artdisplay/artdisplay/AmazonCoverArtSearch.py  |    3 +
 plugins/artdisplay/artdisplay/CoverArtDatabase.py  |   48 ++++++++++++++----
 .../artdisplay/EmbeddedCoverArtSearch.py           |    3 +
 .../artdisplay/artdisplay/LocalCoverArtSearch.py   |    3 +
 .../artdisplay/artdisplay/PodcastCoverArtSearch.py |    3 +
 plugins/artdisplay/artdisplay/__init__.py          |   52 ++++++++++++++------
 6 files changed, 87 insertions(+), 25 deletions(-)
---
diff --git a/plugins/artdisplay/artdisplay/AmazonCoverArtSearch.py b/plugins/artdisplay/artdisplay/AmazonCoverArtSearch.py
index 2ab904c..8bc1666 100644
--- a/plugins/artdisplay/artdisplay/AmazonCoverArtSearch.py
+++ b/plugins/artdisplay/artdisplay/AmazonCoverArtSearch.py
@@ -233,6 +233,9 @@ class AmazonCoverArtSearch (object):
 		return (hasattr (item, "LargeImage") or hasattr (item, "MediumImage")) \
 		       and hasattr (item, "ItemAttributes")
 
+	def get_result_meta (self, search_results):
+		return (None, None)
+
 	def get_result_pixbuf (self, search_results):
 		return None
 
diff --git a/plugins/artdisplay/artdisplay/CoverArtDatabase.py b/plugins/artdisplay/artdisplay/CoverArtDatabase.py
index 1d24648..a56f8ae 100644
--- a/plugins/artdisplay/artdisplay/CoverArtDatabase.py
+++ b/plugins/artdisplay/artdisplay/CoverArtDatabase.py
@@ -46,6 +46,7 @@ OLD_ART_FOLDER = '~/.gnome2/rhythmbox/covers'
 ART_FOLDER = os.path.join(rb.user_cache_dir(), 'covers')
 ART_CACHE_EXTENSION_JPG = 'jpg'
 ART_CACHE_EXTENSION_PNG = 'png'
+ART_CACHE_EXTENSION_META = 'rb-meta'
 ART_CACHE_FORMAT_JPG = 'jpeg'
 ART_CACHE_FORMAT_PNG = 'png'
 ART_CACHE_SETTINGS_JPG = {"quality": "100"}
@@ -145,6 +146,10 @@ class CoverArtDatabase (object):
 	def set_pixbuf (self, db, entry, pixbuf, callback):
 		if entry is None or pixbuf is None:
 			return
+
+		meta_location = self.build_art_cache_filename (db, entry, ART_CACHE_EXTENSION_META)
+		self.write_meta_file (meta_location, None, None)
+
 		if pixbuf.get_has_alpha():
 			art_location = self.build_art_cache_filename (db, entry, ART_CACHE_EXTENSION_PNG)
 			art_cache_format = ART_CACHE_FORMAT_PNG
@@ -155,7 +160,7 @@ class CoverArtDatabase (object):
 			art_cache_settings = ART_CACHE_SETTINGS_JPG
 		self.ticket.purge (entry)
 		pixbuf.save (art_location, art_cache_format, art_cache_settings)
-		callback (entry, pixbuf, art_location)
+		callback (entry, pixbuf, art_location, None, None)
 		for Engine in ART_SEARCHES_LOCAL:
 			try:
 				Engine ().save_pixbuf (db, entry, pixbuf)
@@ -167,7 +172,7 @@ class CoverArtDatabase (object):
   
 	def get_pixbuf (self, db, entry, is_playing, callback):
 		if entry is None:
-			callback (entry, None, None)
+			callback (entry, None, None, None, None)
 			return
             
 		st_artist = db.entry_get (entry, rhythmdb.PROP_ARTIST) or _("Unknown")
@@ -184,6 +189,7 @@ class CoverArtDatabase (object):
 	def image_search (self, plexer, db, st_album, st_artist, entry, is_playing, callback):
 		art_location_jpg = self.build_art_cache_filename (db, entry, ART_CACHE_EXTENSION_JPG)
 		art_location_png = self.build_art_cache_filename (db, entry, ART_CACHE_EXTENSION_PNG)
+		art_location_meta = self.build_art_cache_filename (db, entry, ART_CACHE_EXTENSION_META)
 		blist_location = self.build_art_cache_filename (db, entry, "rb-blist")
 
 		art_location = None
@@ -196,7 +202,8 @@ class CoverArtDatabase (object):
 		if art_location:
 			self.ticket.purge (entry)
 			pixbuf = gtk.gdk.pixbuf_new_from_file (art_location)
-			callback (entry, pixbuf, art_location)
+			(tooltip_image, tooltip_text) = self.read_meta_file (art_location_meta)
+			callback (entry, pixbuf, art_location, tooltip_image, tooltip_text)
 			return
 
 		# Check if we're already searching for art for this album
@@ -227,7 +234,7 @@ class CoverArtDatabase (object):
 				if not results:
 					break
 
-				def handle_result_pixbuf (pixbuf, engine_uri, should_save):
+				def handle_result_pixbuf (pixbuf, engine_uri, tooltip_image, tooltip_text, should_save):
 					if self.ticket.release (entry, ticket):
 						if should_save:
 							if pixbuf.get_has_alpha ():
@@ -236,23 +243,27 @@ class CoverArtDatabase (object):
 							else:
 								pixbuf.save (art_location_jpg, ART_CACHE_FORMAT_JPG, ART_CACHE_SETTINGS_JPG)
 								uri = art_location_jpg
+
+							self.write_meta_file (art_location_meta, tooltip_image, tooltip_text)
 						else:
 							uri = engine_uri
 
 						print "found image for %s" % (db.entry_get(entry, rhythmdb.PROP_LOCATION))
-						callback (entry, pixbuf, uri)
+						callback (entry, pixbuf, uri, tooltip_image, tooltip_text)
 						for m in self.same_search.pop(entry, []):
 							print "and for same search %s" % (db.entry_get(m, rhythmdb.PROP_LOCATION))
-							callback (m, pixbuf, uri)
+							callback (m, pixbuf, uri, tooltip_image, tooltip_text)
 
 					self.write_blist (blist_location, blist)
 					self.same_search.pop (entry, None)
 
+				# fetch the meta details for the engine
+				(tooltip_image, tooltip_text) = engine.get_result_meta (results)
 
 				# first check if the engine gave us a pixbuf
 				pixbuf = engine.get_result_pixbuf (results)
 				if pixbuf:
-					handle_result_pixbuf (pixbuf, None, True)
+					handle_result_pixbuf (pixbuf, None, tooltip_image, tooltip_text, True)
 					return
 
 				# then check URIs
@@ -266,7 +277,7 @@ class CoverArtDatabase (object):
 					_, (data, ) = plexer.receive ()
 					pixbuf = self.image_data_load (data)
 					if pixbuf:
-						handle_result_pixbuf (pixbuf, url, engine_remote)
+						handle_result_pixbuf (pixbuf, url, tooltip_image, tooltip_text, engine_remote)
 						return
 
 				if not engine.search_next ():
@@ -286,14 +297,31 @@ class CoverArtDatabase (object):
 
 		if self.ticket.forget (entry, ticket):
 			print "didn't find image for %s" % (db.entry_get(entry, rhythmdb.PROP_LOCATION))
-			callback (entry, None, None)
+			callback (entry, None, None, None, None)
 			for m in self.same_search.pop (entry, []):
 				print "or for same search %s" % (db.entry_get(m, rhythmdb.PROP_LOCATION))
-				callback (m, None, None)
+				callback (m, None, None, None, None)
 
 		self.write_blist (blist_location, blist)
 		self.same_search.pop (entry, None)
 
+
+	def read_meta_file (self, meta_location):
+		if os.path.exists (meta_location):
+			data = [line.strip () for line in file (meta_location)]
+			return (data[0], data[1])
+		else:
+			return (None, None)
+
+	def write_meta_file (self, meta_location, tooltip_image, tooltip_text):
+		if tooltip_text is not None:
+			meta_file = file (meta_location, 'w')
+			meta_file.writelines([tooltip_image, "\n", tooltip_text, "\n"])
+			meta_file.close()
+		elif os.path.exists (meta_location):
+			os.unlink (meta_location)
+
+
 	def read_blist (self, blist_location):
 		if os.path.exists (blist_location):
 			return [line.strip () for line in file (blist_location)]
diff --git a/plugins/artdisplay/artdisplay/EmbeddedCoverArtSearch.py b/plugins/artdisplay/artdisplay/EmbeddedCoverArtSearch.py
index 390f6e0..cffccb5 100644
--- a/plugins/artdisplay/artdisplay/EmbeddedCoverArtSearch.py
+++ b/plugins/artdisplay/artdisplay/EmbeddedCoverArtSearch.py
@@ -123,6 +123,9 @@ class EmbeddedCoverArtSearch (object):
 	def search_next (self):
 		return False
 
+	def get_result_meta (self, search_results):
+		return (None, None)
+
 	def get_result_pixbuf (self, search_results):
 		return search_results
 
diff --git a/plugins/artdisplay/artdisplay/LocalCoverArtSearch.py b/plugins/artdisplay/artdisplay/LocalCoverArtSearch.py
index 68babe0..389070d 100644
--- a/plugins/artdisplay/artdisplay/LocalCoverArtSearch.py
+++ b/plugins/artdisplay/artdisplay/LocalCoverArtSearch.py
@@ -103,6 +103,9 @@ class LocalCoverArtSearch:
 	def search_next (self):
 		return False
 
+	def get_result_meta (self, results):
+		return (None, None)
+
 	def get_result_pixbuf (self, results):
 		return None
 
diff --git a/plugins/artdisplay/artdisplay/PodcastCoverArtSearch.py b/plugins/artdisplay/artdisplay/PodcastCoverArtSearch.py
index 5fbd522..673e166 100644
--- a/plugins/artdisplay/artdisplay/PodcastCoverArtSearch.py
+++ b/plugins/artdisplay/artdisplay/PodcastCoverArtSearch.py
@@ -49,6 +49,9 @@ class PodcastCoverArtSearch (object):
 	def search_next (self):
 		return False
 
+	def get_result_meta (self, search_results):
+		return (None, None)
+
 	def get_result_pixbuf (self, search_results):
 		return None
 
diff --git a/plugins/artdisplay/artdisplay/__init__.py b/plugins/artdisplay/artdisplay/__init__.py
index 2b7fab2..13356bb 100644
--- a/plugins/artdisplay/artdisplay/__init__.py
+++ b/plugins/artdisplay/artdisplay/__init__.py
@@ -273,6 +273,8 @@ class ArtDisplayWidget (FadingImage):
 		self.set_padding (0, 5)
 		self.ddg_id = self.connect ('drag-data-get', self.drag_data_get)
 		self.ddr_id = self.connect ('drag-data-received', self.drag_data_received)
+		self.qt_id = self.connect ('query-tooltip', self.query_tooltip)
+		self.props.has_tooltip = True
 		self.current_entry, self.working = None, False
 		self.current_pixbuf, self.current_uri = None, None
 
@@ -302,21 +304,32 @@ class ArtDisplayWidget (FadingImage):
 		else:
 			self.drag_source_unset ()
 
-	def update_tooltips (self, working):
-		if not self.current_entry:
-			self.set_tooltip_text (None)
-		elif working:
-			self.set_tooltip_text (_("Searching... drop artwork here"))
+	def query_tooltip (self, widget, x, y, keyboard_mode, tooltip):
+		if (self.tooltip_image, self.tooltip_text) != (None, None):
+			tooltip.set_text(self.tooltip_text)
+			tooltip.set_icon(self.tooltip_image)
+			return True
 		else:
-			self.set_tooltip_text (_("Drop artwork here"))
+			return False
 
-	def set (self, entry, pixbuf, uri, working):
+	def set (self, entry, pixbuf, uri, tooltip_image, tooltip_text, working):
 		self.current_entry = entry
 		self.current_pixbuf = pixbuf
 		self.current_uri = uri
 		self.set_current_art (pixbuf, working)
 		self.update_dnd_targets ()
-		self.update_tooltips (working)
+
+		self.tooltip_image = None
+		if not self.current_entry:
+			self.tooltip_text = None
+		elif working:
+			self.tooltip_text = _("Searching... drop artwork here")
+		elif (tooltip_image, tooltip_text) != (None, None):
+			self.tooltip_image = tooltip_image
+			self.tooltip_text = tooltip_text
+		else:
+			self.tooltip_text = _("Drop artwork here")
+
 
 	def drag_data_get (self, widget, drag_context, selection_data, info, timestamp):
 		if self.current_pixbuf:
@@ -398,18 +411,27 @@ class ArtDisplayPlugin (rb.Plugin):
 			return
 		db = self.shell.get_property ("db")
 
-		self.art_widget.set (entry, None, None, True)
+		self.art_widget.set (entry, None, None, None, None, True)
 		self.art_container.show_all ()
 		# Intitates search in the database (which checks art cache, internet etc.)
 		self.current_entry = entry
 		self.current_pixbuf = None
 		self.art_db.get_pixbuf(db, entry, True, self.on_get_pixbuf_completed)
 
-	def on_get_pixbuf_completed(self, entry, pixbuf, uri):
+	def on_get_pixbuf_completed(self, entry, pixbuf, uri, tooltip_image, tooltip_text):
 		# Set the pixbuf for the entry returned from the art db
 		if entry == self.current_entry:
 			self.current_pixbuf = pixbuf
-			self.art_widget.set (entry, pixbuf, uri, False)
+
+			if tooltip_image is None:
+				pb = None
+			elif tooltip_image.startswith("/"):
+				pb = gtk.gdk.pixbuf_new_from_file(tooltip_image)
+			else:
+				f = self.find_file(tooltip_image)
+				pb = gtk.gdk.pixbuf_new_from_file(f)
+			self.art_widget.set (entry, pixbuf, uri, pb, tooltip_text, False)
+
 		if pixbuf:
 			db = self.shell.get_property ("db")
 			# This might be from a playing-changed signal,
@@ -421,9 +443,9 @@ class ArtDisplayPlugin (rb.Plugin):
 
 	def cover_art_request (self, db, entry):
 		a = [None]
-		def callback(entry, pixbuf, uri):
+		def callback(entry, pixbuf, uri, tooltip_image, tooltip_text):
 			a[0] = pixbuf
-			self.on_get_pixbuf_completed(entry, pixbuf, uri)
+			self.on_get_pixbuf_completed(entry, pixbuf, uri, tooltip_image, tooltip_text)
 
 		playing = (entry == self.current_entry)
 		self.art_db.get_pixbuf(db, entry, playing, callback)
@@ -439,7 +461,7 @@ class ArtDisplayPlugin (rb.Plugin):
 		self.art_db.cancel_get_pixbuf (entry)
 		if self.current_pixbuf == metadata:
 			return
-		self.art_widget.set (entry, metadata, None, False)
+		self.art_widget.set (entry, metadata, None, None, None, False)
 
 	def cover_art_uri_notify (self, db, entry, field, metadata):
 		if entry != self.current_entry:
@@ -460,7 +482,7 @@ class ArtDisplayPlugin (rb.Plugin):
 						pixbuf = pbl.get_pixbuf ()
 						if pixbuf:
 							self.art_db.cancel_get_pixbuf (entry)
-							self.on_get_pixbuf_completed (entry, pixbuf, uri)
+							self.on_get_pixbuf_completed (entry, pixbuf, uri, None, None)
 				except GError:
 					pass
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]