Package elisa :: Package plugins :: Package good :: Package amazon_plugin :: Module amazon_metadata
[hide private]
[frames] | no frames]

Source Code for Module elisa.plugins.good.amazon_plugin.amazon_metadata

  1  # -*- coding: utf-8 -*- 
  2  # Elisa - Home multimedia server 
  3  # Copyright (C) 2006-2008 Fluendo Embedded S.L. (www.fluendo.com). 
  4  # All rights reserved. 
  5  # 
  6  # This file is available under one of two license agreements. 
  7  # 
  8  # This file is licensed under the GPL version 3. 
  9  # See "LICENSE.GPL" in the root of this distribution including a special 
 10  # exception to use Elisa with Fluendo's plugins. 
 11  # 
 12  # The GPL part of Elisa is also available under a commercial licensing 
 13  # agreement from Fluendo. 
 14  # See "LICENSE.Elisa" in the root directory of this distribution package 
 15  # for details on that license. 
 16   
 17  """ 
 18  Amazon Cover Loading 
 19  """ 
 20   
 21   
 22  __maintainer__ = 'Benjamin Kampmann <benjamin@fluendo.com>' 
 23   
 24  from elisa.extern.coherence.covers_by_amazon import CoverGetter, aws_server 
 25   
 26  from elisa.base_components.metadata_provider import MetadataProvider 
 27  from elisa.core.media_uri import MediaUri, quote 
 28   
 29  from elisa.core.component import InitializeFailure 
 30   
 31  import time, os 
 32  import pickle 
 33  from twisted.internet import threads, reactor 
 34   
 35  # 
 36  # 
 37  # 
 38  # IF YOU WANT TO USE THIS FILE OUTSIDE OF ELISA, YOU'LL HAVE TO REPLACE THIS 
 39  # KEY WITH YOUR ONE!!! THIS ONE IS FOR THE USE OF ELISA ONLY! 
 40  # 
 41  # 
 42  # 
 43  aws_key = '0BRN2M3KEQFQ34YKARG2' 
 44   
45 -class AmazonCovers(MetadataProvider):
46 47 config_doc = {'locale': 'set your locale amazon here, could be any ' 48 'of de,jp,ca,uk,fr'} 49 50 # FIXME: Change this to work with the local homedir 51 default_config = {'locale': ''} 52
53 - def __init__(self):
54 MetadataProvider.__init__(self) 55 56 # A dictionary containing files which point to their timestamps 57 self._expire_dict = {} 58 59 self._cache = os.path.join(os.path.expanduser("~"), ".elisa", 60 "amazon_cache") 61 self._cache_filename = os.path.join(self._cache, "cache.txt") 62 63 self._already_asked = []
64
65 - def initialize(self):
66 # setting up the locale 67 locale = self.config.get('locale' , '') 68 self._locale = None 69 70 if locale != '': 71 if locale in aws_server.keys(): 72 self._locale = locale 73 else: 74 self.warning("Locale '%s' not supported by amazon_covers", 75 locale) 76 77 if not os.path.exists(self._cache): 78 try: 79 os.makedirs(self._cache) 80 except OSError, e: 81 self.warning("Could not create the amazon caching directory" \ 82 " '%s': '%s'. This Media Provider will be" \ 83 " deactivated" % (self._cache, e)) 84 raise InitializeFailure('amazon_metadata', e) 85 86 if os.path.isfile(self._cache_filename): 87 fd = open(self._cache_filename) 88 try: 89 self._expire_dict = pickle.load(fd) 90 except EOFError: 91 # Sometimes pickle loading fails, so we drop it 92 self.expirce_dict = {} 93 fd.close() 94 95 reactor.callLater(2, self.delete_expired)
96
97 - def clean(self):
98 MetadataProvider.clean(self) 99 fd = open(self._cache_filename, 'w') 100 pickle.dump(self._expire_dict, fd) 101 fd.close()
102
103 - def get_rank(self):
104 return 200
105
106 - def able_to_handle(self, metadata):
107 if metadata.get('album', None) == None: 108 return False 109 110 if metadata.get('cover', None) != None: 111 if metadata.get('default_image' , '') != None: 112 return False 113 114 return True
115
116 - def delete_expired(self):
117 for file_name, atime in self._expire_dict.items(): 118 if atime <= time.time() + 86400: 119 os.remove(file_name) 120 del self._expire_dict[file_name] 121 if file_name in self._already_asked: 122 # FIXME: where's that remove() method defined? 123 self.remove(file_name) 124 125 # Call me again tomorrow 126 reactor.callLater(86400, self.delete_expired)
127
128 - def get_metadata(self, metadata, low_priority=False):
129 d = threads.deferToThread(self._get_cover, metadata) 130 return d
131
132 - def _get_album (self, metadata):
133 album = metadata['album'].lower().strip() 134 # FIXME: what about all other special characters?? 135 album = album.replace(unicode(u'ä'),unicode('ae')) 136 album = album.replace(unicode(u'ö'),unicode('oe')) 137 album = album.replace(unicode(u'ü'),unicode('ue')) 138 album = album.replace(unicode(u'ß'),unicode('ss')) 139 return album
140
141 - def _get_artist (self, metadata):
142 if metadata.get('artist', None) == None: 143 return None 144 artist = metadata['artist'].lower().strip() 145 # FIXME: what about all other special characters?? 146 artist = artist.replace(unicode(u'ä'),unicode('ae')) 147 artist = artist.replace(unicode(u'ö'),unicode('oe')) 148 artist = artist.replace(unicode(u'ü'),unicode('ue')) 149 artist = artist.replace(unicode(u'ß'),unicode('ss')) 150 return artist
151 152
153 - def _get_cover(self, metadata):
154 155 # we'll do it for the remote look up. So why don't do it here also? 156 album = self._get_album(metadata) 157 artist = self._get_artist(metadata) 158 if album == None or album == '': 159 return metadata 160 161 path= unicode(os.path.join(self._cache, "%s.png" % quote(album))) 162 163 self.debug("searching for file: '%s'" % path) 164 165 if os.path.exists(path): 166 self.debug("Found file %s" % path) 167 return self._set_cover(metadata, path) 168 169 170 if path in self._already_asked: 171 return metadata 172 173 if artist: 174 self._doing_album_and_artist_lookup(path, metadata, self._locale) 175 return metadata 176 177 self._doing_album_lookup(path, metadata, self._locale) 178 return metadata
179 180
181 - def _got_new_image(self, a, b, c):
182 path = a 183 metadata = c 184 # this image will expire 28 days later, like in the movie, dude 185 self._expire_dict[path] = time.time() + 2419200 186 self.debug("image found: %s for %s" % (path, metadata)) 187 self._set_cover(metadata, path)
188
189 - def _image_not_found(self, path, metadata, album=0, locale=None):
190 if album and not locale: 191 self.debug("Sorry, no amazon images found for %s" % metadata) 192 return 193 194 if locale: 195 if album: 196 self.debug("No images found for locale '%s', trying default", 197 locale) 198 self._doing_album_lookup(path, metadata, locale=None) 199 return 200 self.debug("No artist and album found for locale '%s'. "\ 201 "trying to look up for default locale") 202 203 self._doing_album_and_artist_lookup(path, metadata, locale=None) 204 205 else: 206 if not album: 207 self.debug("No artist-album combination found performing "\ 208 "a lookup of covers only") 209 self._doing_album_lookup(path, metadata, locale=self._locale) 210 return 211 self.debug("Sorry nothing found for '%s'" % metadata)
212 213
214 - def _doing_album_and_artist_lookup(self, path, metadata, locale=None):
215 self._already_asked.append(path) 216 self.debug("Doing lookup for %s" % path) 217 g = CoverGetter(path, aws_key, 218 callback=(self._got_new_image, (path, metadata)), 219 not_found_callback=(self._image_not_found, (path, 220 metadata, 221 0, locale)), 222 artist=metadata.get('artist'), 223 title=metadata.get('album'))
224
225 - def _doing_album_lookup(self, path, metadata, locale):
226 self.debug("Doing lookup for %s" % path) 227 self._already_asked.append(path) 228 g = CoverGetter(path, aws_key, 229 locale=locale, 230 callback=(self._got_new_image, (path, metadata)), 231 artist=None, 232 not_found_callback=(self._image_not_found,(path, 233 metadata,1, 234 locale)), 235 title=self._get_album(metadata))
236
237 - def _set_cover(self, metadata, cover):
238 cover_path = MediaUri("file://%s" % cover) 239 if metadata.get('cover', None) == None: 240 metadata['cover'] = cover_path 241 242 # Set globally image if not set yet: 243 if metadata.get('default_image', '') == None: 244 metadata['default_image'] = cover_path 245 246 self.debug("returning this dict: %s" % metadata) 247 return metadata
248 249 250 251 if __name__ == "__main__": 252 253 c = AmazonCovers() 254 c.config = {'cache' : '/tmp/amazon'} 255 c.initialize() 256
257 - def start_test():
258 259 def print_dict(mdict): 260 print 'got this dict:', mdict
261 262 def end_up(): 263 c.clean() 264 reactor.stop() 265 266 def power_asking(): 267 ask_it({u'artist': u'coldplay', 268 u'album' : u'Parachutes'}) 269 ask_it({u'artist': u'gorillaz', 270 u'album' : u'gorillaz'}) 271 ask_it({u'artist': u'gorillaz', 272 u'album' : u'demon days'}) 273 ask_it({u'artist': u'The Good, the Bad & the Queen', 274 u'album' : u'The Good, the Bad & the Queen'}) 275 ask_it({u'artist': u'toten hosen', 276 u'album' : u'Unplugged Im Wiener Burgtheater'}) 277 278 ask_it({u'artist': u'gorillaz', # Wrong Artist 279 u'album' : u'demon days live (At Manchester)'}) 280 281 ask_it({u'artist': u'The Good, the Bad & the Queen', 282 u'album' :'not_existing'}) # Wrong Album 283 284 # Is the same (should return one file) 285 ask_it({u'artist': u'toten hosen', 286 u'album' : u'unsterblich'}) 287 ask_it({u'artist': u'Toten Hosen', 288 u'album' : u'Unsterblich'}) 289 290 291 # Test for lstrip: bot are the same 292 ask_it({u'artist': u' coldplay ', 293 u'album' : u' x&y '}) 294 ask_it({u'artist': u' coldplay ', 295 u'album' : u' x&y '}) 296 297 298 def ask_it(dict): 299 df = c.get_metadata(dict) 300 df.addCallback(print_dict) 301 302 power_asking() 303 reactor.callLater(15,power_asking) 304 reactor.callLater(30, end_up) 305 306 307 reactor.callWhenRunning(start_test) 308 309 reactor.run() 310