Index: plugins/artdisplay/artdisplay.py
===================================================================
RCS file: /cvs/gnome/rhythmbox/plugins/artdisplay/artdisplay.py,v
retrieving revision 1.4
diff -u -r1.4 artdisplay.py
--- plugins/artdisplay/artdisplay.py	3 May 2006 12:11:09 -0000	1.4
+++ plugins/artdisplay/artdisplay.py	3 May 2006 18:06:22 -0000
@@ -36,6 +36,8 @@
 DEFAULT_LOCALE = "en_US"
 ASSOCIATE = "webservices-20"
 ART_FOLDER = '~/.gnome2/rhythmbox/covers'
+FADE_STEP = 0.1
+FADE_STEP_TIME = 100
 
 class GnomeVFSAsyncSrc(object):  
     def __init__(self):
@@ -153,6 +155,10 @@
 		# Get best match from results
 		self.best_match = self.search_engine.get_best_match (results)
 
+		if self.best_match is None:
+			self.search_engine.search_next()
+			return
+
 		# Attempt to download image for best match
 		pic_url = str(self.best_match.ImageUrlLarge)
 		self.image_version = "large";
@@ -170,7 +176,7 @@
 				pic_url = str(self.best_match.ImageUrlMedium)
 				self.image_loader.get_url (pic_url, self.on_image_data_received)
 				return
-			blist_location = self.build_art_cache_filename(self.search_engine.st_album, self.search_engine.st_artist, "rb-list")
+			blist_location = self.build_art_cache_filename(self.search_engine.st_album, self.search_engine.st_artist, "rb-blist")
 			f = file (blist_location, 'w')
 			f.close ()
 			self.search_engine.search_next()
@@ -227,10 +233,6 @@
 			st_artist = st_artist.replace (char, '')
 			st_album = st_album.replace (char, '')
 
-		# Save current search's entry properties
-		self.st_album = st_album
-		self.st_artist = st_artist
-
 		# Remove variants of Disc/CD [1-9] from album title before search
 		for exp in ["\([Dd]isc *[1-9]+\)", "\([Cc][Dd] *[1-9]+\)"]:
 			p = re.compile (exp)
@@ -241,6 +243,9 @@
 			p = re.compile (exp)
 			st_album_no_vol = p.sub ('', st_album_no_vol)
 
+		# Save current search's entry properties
+		self.st_album = st_album
+		self.st_artist = st_artist
 		self.st_album_no_vol = st_album_no_vol
 
 		# TODO: Improve to decrease wrong cover downloads, maybe add severity?
@@ -257,10 +262,11 @@
 				self.keywords.append ("%s" % (st_album_no_vol))
 			self.keywords.append ("Various %s" % (st_album))
 		else:
-			self.keywords.append ("%s %s" % (st_artist, st_album))
-			if st_album_no_vol != st_artist:
-				self.keywords.append ("%s %s" % (st_artist, st_album_no_vol))
-			self.keywords.append ("Various %s" % (st_album))
+			if st_album != st_artist:
+				self.keywords.append ("%s %s" % (st_artist, st_album))
+				if st_album_no_vol != st_artist:
+					self.keywords.append ("%s %s" % (st_artist, st_album_no_vol))
+				self.keywords.append ("%s" % (st_album))
 			self.keywords.append ("%s" % (st_artist))
 
 		# Initiate asynchronous search
@@ -346,20 +352,56 @@
 		self.on_search_completed_callback (self.db, self.entry, result)
 		self.searching = False
 
-	# TODO: Better overall matching algo - "==" is inaccurate on minor differences
+	def __tidy_up_string (self, s):
+		# Lowercase
+		s = s.lower ()
+		# Strip
+		s = s.strip ()
+
+		# TODO: Convert accented to unaccented (fixes matching Salomé vs Salome)
+		s = s.replace (" - "," ")	
+		s = s.replace (": "," ")
+
+		return s
+
 	def get_best_match (self, search_results):
-		# default to the first match as a fallback
-		best_match = search_results[0]
+		# Default to "no match", our results must match our criteria
+		best_match = None
 
 		# search within the results to find the album name match
-		for item in search_results:
-			# make album title case insensitive and strip
-			# leading and trailing space
-			if item.ProductName.lower ().strip () == self.st_album.lower ().strip ():
-				best_match = item
-				break
-
-		# TODO: Also validate <Artist/> tag if it matched search
+		if self.st_album!="Unknown":
+			album_check = self.__tidy_up_string(self.st_album)
+			for item in search_results:
+			# Check for album name in ProductName
+				product_name = self.__tidy_up_string(item.ProductName)
+				if product_name == album_check:
+					# Found exact album, can not get better than that
+					best_match = item
+					break
+				# If we already found a best_match, just keep checking for exact one
+				elif (best_match is None) and (product_name.find (album_check) != -1):
+					best_match = item
+
+		# If we still have no definite hit, use first result where artist matches
+		if (self.st_artist!="Unknown"):
+			artist_check = self.__tidy_up_string(self.st_artist)
+			if best_match is None:
+				# Check if artist appears in the Artists list
+				hit = False
+				for item in search_results:
+					if type(item.Artists.Artist) <> type([]):
+						artists = [item.Artists.Artist]
+					else:
+						artists = item.Artists.Artist
+
+					for artist in artists:
+						artist = self.__tidy_up_string(artist)
+						if artist.find(artist_check) != -1:
+							best_match = item
+							hit = True						
+							break
+					if hit:
+						break
 
 		return best_match
 
@@ -381,6 +423,7 @@
 		self.resize_id = 0
 		self.resize_in_progress = False
 		self.old_width = 0
+		self.fade_step = 0
 		entry = sp.get_playing_entry ()
 		self.playing_entry_changed (sp, entry)
 	
@@ -435,9 +478,42 @@
 		# Set the pixbuf for the entry returned from the art db
 		self.set_current_art (pixbuf)
 
-	def set_current_art (self, pixmap):
-		self.current_pixbuf = pixmap;
-		self.update_displayed_art (False);
+	def fade_art (self, old_pixbuf, new_pixbuf):
+		self.fade_step += FADE_STEP
+
+		if self.fade_step <= 0.999:
+			# get pixbuf size
+			ow = old_pixbuf.get_width ()
+			nw = new_pixbuf.get_width ()
+			oh = old_pixbuf.get_height ()
+			nh = new_pixbuf.get_height ()
+
+			# find scale, widget size and alpha
+			ww = self.art_widget.parent.allocation.width 
+			wh = oh * ww / ow
+			sw = float(ww)/nw
+			sh = float(wh)/nh
+			alpha = int (self.fade_step * 255)
+
+			self.current_pixbuf = old_pixbuf.scale_simple (ww, wh, gtk.gdk.INTERP_NEAREST)
+			new_pixbuf.composite (self.current_pixbuf, 0, 0, ow, oh, 0, 0, sw, sh, gtk.gdk.INTERP_NEAREST, alpha)
+			self.art_widget.set_from_pixbuf (self.current_pixbuf)
+			self.art_widget.show ()
+		else:
+			self.current_pixbuf = new_pixbuf
+			self.update_displayed_art (False);
+
+		return (self.fade_step <= 0.999)
+
+	def set_current_art (self, pixbuf):
+		current_pb = self.art_widget.get_pixbuf ()
+		if current_pb is not None and pixbuf is not None:
+			self.fade_step = 0.0
+			self.fade_art (current_pb, pixbuf)
+			gobject.timeout_add (FADE_STEP_TIME, self.fade_art, current_pb, pixbuf)
+		else:
+			self.current_pixbuf = pixbuf;
+			self.update_displayed_art (False);
 
 	def update_displayed_art (self, quick):
 		if self.current_pixbuf is None:
