Index: plugins/artdisplay/artdisplay/CoverArtDatabase.py
===================================================================
RCS file: /cvs/gnome/rhythmbox/plugins/artdisplay/artdisplay/CoverArtDatabase.py,v
retrieving revision 1.2
diff -u -r1.2 CoverArtDatabase.py
--- plugins/artdisplay/artdisplay/CoverArtDatabase.py	12 May 2006 16:54:40 -0000	1.2
+++ plugins/artdisplay/artdisplay/CoverArtDatabase.py	23 Jun 2006 05:55:35 -0000
@@ -26,115 +26,172 @@
 ART_FOLDER = '~/.gnome2/rhythmbox/covers'
 
 class CoverArtDatabase (object):
-	def __init__ (self):
-		self.loader = Loader()
+    def __init__ (self):
+        self.loader = Loader()
 
-	def create_search (self):
-		return AmazonCoverArtSearch (self.loader)
+    def create_search (self):
+        return AmazonCoverArtSearch (self.loader)
 
-	def build_art_cache_filename (self, album, artist, extension):
-		art_folder = os.path.expanduser (ART_FOLDER)
-		if not os.path.exists (art_folder):
-			os.mkdir (art_folder)
-		if extension is None:
-			extension = "jpg"
-
-		# FIXME: the following block of code is messy and needs to be redone ASAP
-		return art_folder + '/%s - %s.%s' % (artist.replace ('/', '-'), album.replace ('/', '-'), extension)	
-
-	def get_pixbuf (self, db, entry, callback):
-		if entry is None:
-			callback (entry, None)
-			return
+    def build_art_cache_filename (self, album, artist, extension):
+        art_folder = os.path.expanduser (ART_FOLDER)
+        if not os.path.exists (art_folder):
+            os.mkdir (art_folder)
+        if extension is None:
+            extension = "jpg"
+
+        # FIXME: the following block of code is messy and needs to be redone ASAP
+        return art_folder + '/%s - %s.%s' % (artist.replace ('/', '-'), album.replace ('/', '-'), extension)    
+
+    def find_local_filename (self, location) :
+        try :
+            #TODO - What about fileshares and local networks?
+            if location[0:7] <> "file://" :
+                #Not a local file...
+                return None
+
+            #TODO - Check what happens with accents...
+            #Must "unescape" things like spaces
+            location = location[7:].replace("%20"," ")
+            track_folder = os.path.dirname(location)
+            track_filename = os.path.basename(location)
+
+            #Build a list of image files in this folder...            
+            local_files = os.listdir(track_folder)
+            for filename in local_files :
+                if filename.split(os.path.extsep)[-1] not in ["jpg", "jpeg","png"] :
+                    local_files.remove(filename)        
+
+            #First of all, look for track specific images using the track's base filename...
+            for filename in local_files :
+                if os.path.extsep.join(filename.split(os.path.extsep)[:-1]) \
+                == os.path.extsep.join(track_filename.split(os.path.extsep)[:-1]) :
+                    return os.path.join(track_folder, filename)
+
+            #That failed, so we are reduced to folder/directory specific files...
+            #Special cases include "Cover.jpg" and variants, and ".folder.png"
+            #which is used as a folder image by Gnome Nautilus
+            for filename in os.listdir(track_folder) :
+                if os.path.extsep.join(filename.split(os.path.extsep)[:-1]).lower() in ["cover",".folder"] :
+                    return os.path.join(track_folder, filename)
+
+            #Should we return ANY image in the folder? 
+            return None
+        except :
+            #Something went wrong...
+            #I want the code to carry on the the next method, so catch the exception here.
+            #TODO log it?  Error message?
+            return None
+
+    def get_pixbuf (self, db, entry, callback):
+        if entry is None:
+            callback (entry, None)
+            return
             
-		st_artist = db.entry_get (entry, rhythmdb.PROP_ARTIST)
-		st_album = db.entry_get (entry, rhythmdb.PROP_ALBUM)
-
-		# Handle special case
-		if st_album == "":
-			st_album = "Unknown"
-		if st_artist == "":
-			st_artist = "Unknown"
-
-		# If unknown artist and album there is no point continuing
-		if st_album == "Unknown" and st_artist == "Unknown":
-			callback (entry, None)
-			return
-
-		# replace quote characters
-		# don't replace single quote: could be important punctuation
-		for char in ["\""]:
-			st_artist = st_artist.replace (char, '')
-			st_album = st_album.replace (char, '')
-
-		art_location = self.build_art_cache_filename (st_album, st_artist, "jpg")
-		blist_location = self.build_art_cache_filename (st_album, st_artist, "rb-blist")
-
-		# Check local cache
-		if os.path.exists (art_location):
-			pixbuf = gtk.gdk.pixbuf_new_from_file (art_location)	
-			callback (entry, pixbuf)
-		# Check for unsuccessful previous image download to prevent overhead search
-		elif os.path.exists (blist_location):
-			callback (entry, None)
-		else:
-			# Otherwise spawn (online) search-engine search
-			se = self.create_search ()
-			se.search (db, entry, self.on_search_engine_results, callback)
-
-	def on_search_engine_results (self, search_engine, entry, results, callback):
-		if results is None:
-			self._do_blacklist_and_callback (search_engine, callback)
-			return
-
-		# Get best match from results
-		best_match = search_engine.get_best_match (results)
-
-		if best_match is None:
-			self._do_blacklist_and_callback (search_engine, callback)
-			return
-
-		# Attempt to download image for best match
-		pic_url = str (best_match.ImageUrlLarge)
-		self.loader.get_url (pic_url, self.on_image_data_received, search_engine, "large", callback, best_match)
-
-	def _do_blacklist_and_callback (self, search_engine, callback):
-		self._create_blacklist (search_engine.st_artist, search_engine.st_album)
-		callback (search_engine.entry, None)
-
-	def _create_blacklist (self, artist, album):
-		location = self.build_art_cache_filename (album, artist, "rb-blist")
-		f = file (location, 'w')
-		f.close ()
-		return location
-
-	def _create_artwork (self, artist, album, image_data):
-		location = self.build_art_cache_filename (album, artist, "jpg")
-		f = file (location, 'wb')
-		f.write (image_data)
-		f.close ()
-		return location
-
-	def on_image_data_received (self, image_data, search_engine, image_version, callback, best_match):
-		if image_data is None:
-			res = search_engine.search_next ()
-			if not res:
-				self._do_blacklist_and_callback (search_engine, callback)
-			return
-
-		if len (image_data) < 1000:
-			if image_version == "large" and best_match is not None:
-				# Fallback and try to load medium one
-				pic_url = str (best_match.ImageUrlMedium)
-				self.loader.get_url (pic_url, self.on_image_data_received, search_engine, "medium", callback, best_match)
-				return
-
-			res = search_engine.search_next ()
-			if not res:
-				# only write the blist if there are no more queries to try
-				self._do_blacklist_and_callback (search_engine, callback)
-
-		else:
-			location = self._create_artwork (search_engine.st_artist, search_engine.st_album, image_data)
-			pixbuf = gtk.gdk.pixbuf_new_from_file (location)
-			callback (search_engine.entry, pixbuf)
+        st_artist = db.entry_get (entry, rhythmdb.PROP_ARTIST)
+        st_album = db.entry_get (entry, rhythmdb.PROP_ALBUM)
+        st_location = db.entry_get (entry, rhythmdb.PROP_LOCATION)
+
+        ##########################
+        # Method One - Localfile #
+        ##########################
+        
+        # Note we do NOT make an extra copy in our cache
+        local_filename = self.find_local_filename(st_location)
+        if local_filename :
+            assert os.path.isfile(local_filename)
+            pixbuf = gtk.gdk.pixbuf_new_from_file (local_filename)    
+            callback (entry, pixbuf)
+            return
+
+        ##########################
+        # Method Two - Amazon    #
+        ##########################
+
+        # Handle special case
+        if st_album == "":
+            st_album = "Unknown"
+        if st_artist == "":
+            st_artist = "Unknown"
+
+        # If unknown artist and album there is no point continuing
+        if st_album == "Unknown" and st_artist == "Unknown":
+            callback (entry, None)
+            return
+
+        # replace quote characters
+        # don't replace single quote: could be important punctuation
+        for char in ["\""]:
+            st_artist = st_artist.replace (char, '')
+            st_album = st_album.replace (char, '')
+
+        art_location = self.build_art_cache_filename (st_album, st_artist, "jpg")
+        blist_location = self.build_art_cache_filename (st_album, st_artist, "rb-blist")
+
+        # Check local cache
+        if os.path.exists (art_location):
+            pixbuf = gtk.gdk.pixbuf_new_from_file (art_location)    
+            callback (entry, pixbuf)
+        # Check for unsuccessful previous image download to prevent overhead search
+        elif os.path.exists (blist_location):
+            callback (entry, None)
+        else:
+            # Otherwise spawn (online) search-engine search
+            se = self.create_search ()
+            se.search (db, entry, self.on_search_engine_results, callback)
+
+    def on_search_engine_results (self, search_engine, entry, results, callback):
+        if results is None:
+            self._do_blacklist_and_callback (search_engine, callback)
+            return
+
+        # Get best match from results
+        best_match = search_engine.get_best_match (results)
+
+        if best_match is None:
+            self._do_blacklist_and_callback (search_engine, callback)
+            return
+
+        # Attempt to download image for best match
+        pic_url = str (best_match.ImageUrlLarge)
+        self.loader.get_url (pic_url, self.on_image_data_received, search_engine, "large", callback, best_match)
+
+    def _do_blacklist_and_callback (self, search_engine, callback):
+        self._create_blacklist (search_engine.st_artist, search_engine.st_album)
+        callback (search_engine.entry, None)
+
+    def _create_blacklist (self, artist, album):
+        location = self.build_art_cache_filename (album, artist, "rb-blist")
+        f = file (location, 'w')
+        f.close ()
+        return location
+
+    def _create_artwork (self, artist, album, image_data):
+        location = self.build_art_cache_filename (album, artist, "jpg")
+        f = file (location, 'wb')
+        f.write (image_data)
+        f.close ()
+        return location
+
+    def on_image_data_received (self, image_data, search_engine, image_version, callback, best_match):
+        if image_data is None:
+            res = search_engine.search_next ()
+            if not res:
+                self._do_blacklist_and_callback (search_engine, callback)
+            return
+
+        if len (image_data) < 1000:
+            if image_version == "large" and best_match is not None:
+                # Fallback and try to load medium one
+                pic_url = str (best_match.ImageUrlMedium)
+                self.loader.get_url (pic_url, self.on_image_data_received, search_engine, "medium", callback, best_match)
+                return
+
+            res = search_engine.search_next ()
+            if not res:
+                # only write the blist if there are no more queries to try
+                self._do_blacklist_and_callback (search_engine, callback)
+
+        else:
+            location = self._create_artwork (search_engine.st_artist, search_engine.st_album, image_data)
+            pixbuf = gtk.gdk.pixbuf_new_from_file (location)
+            callback (search_engine.entry, pixbuf)
