From e5275c7149e6f138488f60cf1114bc58c2c8b5f6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kristoffer=20Gr=C3=B6nlund?= Date: Sun, 3 Jan 2010 01:09:42 +0100 Subject: [PATCH] Potentially broken commit - messing with maemo.org while trying to add background image downloading --- README | 7 ++++- jamaendo/__init__.py | 25 ++++++++++++---- jamaendo/api.py | 78 +++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 89 insertions(+), 21 deletions(-) diff --git a/README b/README index cfe925d..fdded53 100644 --- a/README +++ b/README @@ -7,7 +7,7 @@ A media player for the Nokia N900 and other Maemo 5 (Fremantle) phones. JAMENDO is an online platform that distributes musical works under Creative Commons licenses. -Jamaendo was written by Kristoffer Grönlund. +Jamaendo is written by Kristoffer Grönlund. ## Panucci @@ -37,3 +37,8 @@ the build process produces is not entirely optified. It is compatible with the `maemo-optify` tool, however. All you need to do is run `maemo-optify-deb` on the generated .deb file. +## License + +The backend code that speaks to jamendo.com is in the jamaendo module. This module is licensed under a modified New BSD License (modified to remove attribution clauses). See `jamaendo/api.py` for details. + +The code that implements the UI and the rest of the application is licensed under a GPL v3 license. diff --git a/jamaendo/__init__.py b/jamaendo/__init__.py index e4d99e1..e0b69b0 100644 --- a/jamaendo/__init__.py +++ b/jamaendo/__init__.py @@ -27,10 +27,23 @@ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from api import set_cache_dir, \ - Artist, Album, Track, Radio, \ - get_album_cover, get_album_cover_async, \ JamendoAPIException, \ - get_artist, get_albums, get_album, get_tracks, \ - get_track, get_radio_tracks, search_artists, search_albums, \ - search_tracks, albums_of_the_week, new_releases, \ - tracks_of_the_week, get_radio, starred_radios, favorite_albums + Artist, Album, Track, Radio, \ + get_album_cover, \ + get_album_cover_async, \ + get_images_async, \ + get_artist, \ + get_albums, \ + get_album, \ + get_tracks, \ + get_track, \ + get_radio_tracks, \ + search_artists, \ + search_albums, \ + search_tracks, \ + albums_of_the_week, \ + new_releases, \ + tracks_of_the_week, \ + get_radio, \ + starred_radios, \ + favorite_albums diff --git a/jamaendo/api.py b/jamaendo/api.py index cd3d454..0d293bc 100644 --- a/jamaendo/api.py +++ b/jamaendo/api.py @@ -8,12 +8,6 @@ # modification, are permitted provided that the following conditions are met: # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of Jamaendo nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -29,7 +23,7 @@ # An improved, structured jamendo API wrapper for the N900 with cacheing # Image / cover downloads.. and more? import urllib, threading, os, time, simplejson, re -import logging +import logging, hashlib _CACHEDIR = None _COVERDIR = None @@ -249,12 +243,30 @@ class CoverFetcher(threading.Thread): except Exception, e: return None + def _fetch_image(self, url): + try: + h = hashlib.md5(url).hexdigest() + coverdir = _COVERDIR if _COVERDIR else '/tmp' + to = os.path.join(coverdir, h+'.jpg') + if not os.path.isfile(to): + urllib.urlretrieve(url, to) + return to + except Exception, e: + return None + def request_cover(self, albumid, size, cb): self.cond.acquire() self.work.insert(0, (albumid, size, cb)) self.cond.notify() self.cond.release() + def request_images(self, urls, cb): + """cb([(url, image)])""" + self.cond.acquire() + self.work.insert(0, ('images', urls, cb)) + self.cond.notify() + self.cond.release() + def run(self): while True: work = [] @@ -268,12 +280,24 @@ class CoverFetcher(threading.Thread): self.cond.release() multi = len(work) > 1 - for albumid, size, cb in work: - cover = self._fetch_cover(albumid, size) - if cover: - cb(albumid, size, cover) - if multi: - time.sleep(1.0) + for job in work: + if job[0] == 'images': + self.process_images(job[1], job[2]) + else: + self.process_cover(*job) + if multi: + time.sleep(1.0) + + def process_cover(self, albumid, size, cb): + albumid, size, cb = job + cover = self._fetch_cover(albumid, size) + if cover: + cb(albumid, size, cover) + + def process_images(self, urls, cb): + results = [(url, image) for url, image in ((url, self._fetch_image(url)) for url in urls) if image is not None] + if results: + cb(results) class CoverCache(object): """ @@ -284,6 +308,7 @@ class CoverCache(object): """ def __init__(self): self._covers = {} # (albumid, size) -> file + self._images = {} self._fetcher = CoverFetcher() self._fetcher.start() if _COVERDIR and os.path.isdir(_COVERDIR): @@ -336,7 +361,29 @@ class CoverCache(object): if cover: cb(albumid, size, cover) else: - self._fetcher.request_cover(albumid, size, cb) + def cb2(albumid, size, cover): + self._covers[(albumid, size)] = cover + cb(albumid, size, cover) + self._fetcher.request_cover(albumid, size, cb2) + + def get_images_async(self, url_list, cb): + found = [] + lookup = [] + for url in url_list: + image = self._images.get(url, None) + if image: + found.append((url, image)) + else: + lookup.append(url) + if found: + cb(found) + + if lookup: + def cb2(results): + for url, image in results: + self._images[url] = image + cb(results) + self._fetcher.request_images(lookup, cb2) _cover_cache = CoverCache() @@ -364,6 +411,9 @@ def get_album_cover(albumid, size=100): def get_album_cover_async(cb, albumid, size=100): _cover_cache.get_async(albumid, size, cb) +def get_images_async(cb, url_list): + _cover_cache.get_images_async(url_list, cb) + class CustomQuery(Query): def __init__(self, url): Query.__init__(self) -- 1.7.9.5