[r21]: Rhythmbox_AWN / Mac4Lin_Rhythmbox-AWN / artdisplay-awn / CoverArtDatabase.py Maximize Restore History

Download this file

CoverArtDatabase.py    141 lines (115 with data), 4.9 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# -*- Mode: python; coding: utf-8; tab-width: 8; indent-tabs-mode: t; -*-
#
# Copyright (C) 2006 - Gareth Murphy, Martin Szulecki
#
# This program 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, or (at your option)
# any later version.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
import rhythmdb
import os
import gtk
from AmazonCoverArtSearch import AmazonCoverArtSearch
from Loader import Loader
ART_FOLDER = '~/.gnome2/rhythmbox/covers'
class CoverArtDatabase (object):
def __init__ (self):
self.loader = 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
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)