From 1d1d7b4b52081dc98408721dca310aabc0868d19 Mon Sep 17 00:00:00 2001 From: Ivan Frade Date: Tue, 25 Aug 2009 23:54:28 +0300 Subject: [PATCH] Async album art showing thumbnails Async retrieval of the album art. Showing thumbnails instead of full images. Show 5 images instead of 4 in the dialog --- src/aa_selection_dialog.py | 42 +++++++++++++-------- src/album_art.py | 88 +++++++++++++++++++------------------------- src/album_art_panel.py | 2 +- 3 files changed, 64 insertions(+), 68 deletions(-) diff --git a/src/aa_selection_dialog.py b/src/aa_selection_dialog.py index 47086d1..b22ecc0 100644 --- a/src/aa_selection_dialog.py +++ b/src/aa_selection_dialog.py @@ -17,6 +17,7 @@ class AlbumArtSelectionDialog (gtk.Dialog): self.artist = artist self.album = album self.size = size + self.paths = [] self.__create_view (size) if (downloader): @@ -29,6 +30,7 @@ class AlbumArtSelectionDialog (gtk.Dialog): self.selection_thumb = None hildon.hildon_gtk_window_set_progress_indicator (self, 1) + def __create_view (self, size): hbox = gtk.HBox (homogeneous=True) @@ -50,23 +52,27 @@ class AlbumArtSelectionDialog (gtk.Dialog): self.vbox.add (hbox) def __get_alternatives_async (self): - self.paths = self.downloader.get_alternatives (self.album, self.artist, 4) - self.__populate (self.paths) + counter = 0 + for (path, thumb) in self.downloader.get_alternatives (self.album, self.artist, self.size): + self.paths.insert (counter, (path, thumb)) + self.images[counter].set_from_file (thumb) + self.event_boxes [counter].set_sensitive (True) + counter += 1 + while (gtk.events_pending()): + gtk.main_iteration() + + while (counter < self.size): + self.images[counter].set_from_stock (gtk.STOCK_CDROM, gtk.ICON_SIZE_DIALOG) + counter += 1 + hildon.hildon_gtk_window_set_progress_indicator (self, 0) - def __populate (self, paths): - - for i in range (0, self.size): - if (len(paths) > i): - self.images[i].set_from_file (paths[i]) - self.event_boxes[i].set_sensitive (True) - else: - self.images[i].set_from_stock (gtk.STOCK_CDROM, gtk.ICON_SIZE_DIALOG) def click_on_img (self, widget, event, position): + img, thumb = self.paths[position] self.selection_img, self.selection_thumb = self.downloader.save_alternative (self.artist, self.album, - self.paths[position]) + img, thumb) self.response (position) def get_selection (self): @@ -79,12 +85,16 @@ if __name__ == "__main__": import time class MockDownloader: def __init__ (self): - self.alt = ["../hendrix.jpeg", "../hoover.jpeg", "../dylan.jpeg"] + self.alt = [("../hendrix.jpeg", "../hendrix-thumb.jpeg"), + ("../hoover.jpeg", "../hoover-thumb.jpeg"), + ("../backbeat.jpeg", "../backbeat-thumb.jpeg"), + ("../dylan.jpeg", "../dylan-thumb.jpeg")] def get_alternatives (self, album, artist, amount): - time.sleep (5) - return self.alt [0:amount] - def save_alternative (self, artist, album, img): - return ("/home/user/.cache/media-art/" + img, "/home/user/.thumbnails/normal/" + img) + for a in self.alt: + time.sleep (1) + yield a + def save_alternative (self, artist, album, img, thumb): + return ("/home/user/.cache/media-art/" + img, "/home/user/.thumbnails/normal/" + thumb) def clicked_button (self): diff --git a/src/album_art.py b/src/album_art.py index 72cf1db..7f81061 100755 --- a/src/album_art.py +++ b/src/album_art.py @@ -14,10 +14,9 @@ except ImportError: try: import PIL import Image - pil_available = True except ImportError: - pil_available = False - + print "Please install python-imaging package" + sys.exit (-1) # Set socket timeout import socket @@ -49,15 +48,7 @@ class MussorgskyAlbumArt: if (not os.path.exists (CACHE_LOCATION)): os.makedirs (CACHE_LOCATION) - if (pil_available): - self.thumbnailer = LocalThumbnailer () - else: - try: - self.thumbnailer = bus.get_object ('org.freedesktop.thumbnailer', - '/org/freedesktop/thumbnailer/Generic') - except dbus.exceptions.DBusException: - print "No thumbnailer available" - self.thumbnailer = None + self.thumbnailer = LocalThumbnailer () def get_album_art (self, artist, album, force=False): """ @@ -95,37 +86,41 @@ class MussorgskyAlbumArt: return (filename, thumbnail) - def get_alternatives (self, artist, album, no_alternatives): + def get_alternatives (self, artist, album, max_alternatives=4): """ return a list of paths of possible album arts """ + counter = 0 results_page = self.__msn_images (artist, album) - valid_images = [] for image_url in self.__get_url_from_msn_results_page (results_page): if (not image_url): # Some searches doesn't return anything at all! break + + if (counter >= max_alternatives): + break image = self.__get_url (image_url) if (image): - image_path = os.path.join (CACHE_LOCATION, "alternative-" + str(len(valid_images))) + image_path = os.path.join (CACHE_LOCATION, "alternative-" + str(counter)) + thumb_path = os.path.join (CACHE_LOCATION, "alternative-" + str(counter) + "thumb") self.__save_content_into_file (image, image_path) - valid_images.append (image_path) - if (len (valid_images) > no_alternatives): - return valid_images - return valid_images + self.thumbnailer.create (image_path, thumb_path) + counter += 1 + yield (image_path, thumb_path) - def save_alternative (self, artist, album, path): - if not os.path.exists (path): + + def save_alternative (self, artist, album, img_path, thumb_path): + if not os.path.exists (img_path) or not os.path.exists (thumb_path): print "**** CRITICAL **** image in path", path, "doesn't exist!" return (None, None) filename = getCoverArtFileName (album) thumbnail = getCoverArtThumbFileName (album) - os.rename (path, filename) - if (not self.__request_thumbnail (filename)): - print "Something wrong creating the thumbnail!" + os.rename (img_path, filename) + os.rename (thumb_path, thumbnail) + return (filename, thumbnail) def __last_fm (self, artist, album): @@ -162,7 +157,7 @@ class MussorgskyAlbumArt: full_try = BASE_MSN + good_album + "+" + good_artist + MSN_MEDIUM + MSN_SQUARE print "Searching (album + artist): %s" % (full_try) result = self.__get_url (full_try) - if (result.find ("no_results") == -1): + if (result and result.find ("no_results") == -1): return result if (album): @@ -173,14 +168,14 @@ class MussorgskyAlbumArt: album_try = BASE_MSN + good_album + MSN_MEDIUM + MSN_SQUARE print "Searching (album): %s" % (album_try) result = self.__get_url (album_try) - if (result.find ("no_results") == -1): + if (result and result.find ("no_results") == -1): return result if (artist): artist_try = BASE_MSN + good_artist + "+CD+music" + MSN_SMALL + MSN_SQUARE + MSN_PHOTO print "Searching (artist CD): %s" % (artist_try) result = self.__get_url (artist_try) - if (result.find ("no_results") == -1): + if (result and result.find ("no_results") == -1): return result return None @@ -206,7 +201,6 @@ class MussorgskyAlbumArt: current_option.lower().endswith (".jpeg")): yield current_option starting_at = end - yield None def __clean_string_for_search (self, text): @@ -237,12 +231,8 @@ class MussorgskyAlbumArt: return None def __request_thumbnail (self, filename): - if (not self.thumbnailer): - print "No thumbnailer available" - return - uri = "file://" + filename - handle = time.time () - return self.thumbnailer.Queue ([uri], ["image/jpeg"], dbus.UInt32 (handle)) + thumbFile = get_thumb_filename_for_path (fullCoverFileName) + return self.thumbnailer.create (filename, thumbFile) @@ -250,20 +240,16 @@ class LocalThumbnailer: def __init__ (self): self.THUMBNAIL_SIZE = (124,124) - def Queue (self, uris, mimes, handle): - for i in range (0, len(uris)): - uri = uris[i] - fullCoverFileName = uri[7:] - if (os.path.exists (fullCoverFileName)): - thumbFile = get_thumb_filename_for_path (fullCoverFileName) - try: - image = Image.open (fullCoverFileName) - image = image.resize (self.THUMBNAIL_SIZE, Image.ANTIALIAS ) - image.save( thumbFile, "JPEG" ) - print "Thumbnail: " + thumbFile - except IOError, e: - print e - return False + def create (self, fullCoverFileName, thumbFile): + if (os.path.exists (fullCoverFileName)): + try: + image = Image.open (fullCoverFileName) + image = image.resize (self.THUMBNAIL_SIZE, Image.ANTIALIAS ) + image.save (thumbFile, "JPEG") + print "Thumbnail: " + thumbFile + except IOError, e: + print e + return False return True @@ -308,6 +294,6 @@ if __name__ == "__main__": if options.multiple: maa = MussorgskyAlbumArt () - alt = maa.get_alternatives (options.artist, options.album, 5) - for a in alt: - print a + for (img, thumb) in maa.get_alternatives (options.artist, options.album, 5): + print img + print thumb diff --git a/src/album_art_panel.py b/src/album_art_panel.py index cbb7074..f98feb3 100644 --- a/src/album_art_panel.py +++ b/src/album_art_panel.py @@ -68,7 +68,7 @@ class MussorgskyAlbumArtPanel (hildon.StackableWindow): album = treeview.get_model ().get_value (it, 3) artist = treeview.get_model ().get_value (it, 2) - dialog = AlbumArtSelectionDialog (self, artist, album, 4) + dialog = AlbumArtSelectionDialog (self, artist, album, 5) dialog.show_all () response = dialog.run () -- 1.7.9.5