-# An improved, structured jamendo API for the N900 with cacheing
+#!/usr/bin/env python
+#
+# This file is part of Jamaendo.
+# Copyright (c) 2010, Kristoffer Gronlund
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# 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
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# An improved, structured jamendo API wrapper for the N900 with cacheing
# Image / cover downloads.. and more?
import urllib, threading, os, gzip, time, simplejson, re
-#import util
-#if util.platform == 'maemo':
-# _CACHEDIR = os.path.expanduser('''~/MyDocs/.jamaendo''')
-#else:
-# _CACHEDIR = os.path.expanduser('''~/.cache/jamaendo''')
-
-_CACHEDIR = None#'/tmp/jamaendo'
-_COVERDIR = None#os.path.join(_CACHEDIR, 'covers')
+
+_CACHEDIR = None
+_COVERDIR = None
_GET2 = '''http://api.jamendo.com/get2/'''
_MP3URL = _GET2+'stream/track/redirect/?id=%d&streamencoding=mp31'
_OGGURL = _GET2+'stream/track/redirect/?id=%d&streamencoding=ogg2'
# makes a query internally to get the full story
_ARTIST_FIELDS = ['id', 'name', 'image']
-_ALBUM_FIELDS = ['id', 'name', 'image', 'artist_name', 'artist_id']
+_ALBUM_FIELDS = ['id', 'name', 'image', 'artist_name', 'artist_id', 'license_url']
_TRACK_FIELDS = ['id', 'name', 'image', 'artist_name', 'album_name', 'album_id', 'numalbum', 'duration']
_RADIO_FIELDS = ['id', 'name', 'idstr', 'image']
self.image = None
self.artist_name = None
self.artist_id = None
+ self.license_url = None
self.tracks = None # None means not downloaded
if json:
self.set_from_json(json)
def _needs_load(self):
- return self._needs_load_impl('name', 'image', 'artist_name', 'artist_id', 'tracks')
+ return self._needs_load_impl('name', 'image', 'artist_name', 'artist_id', 'license_url', 'tracks')
def _set_from(self, other):
- return self._set_from_impl(other, 'name', 'image', 'artist_name', 'artist_id', 'tracks')
+ return self._set_from_impl(other, 'name', 'image', 'artist_name', 'artist_id', 'license_url', 'tracks')
class Track(LazyQuery):
def __init__(self, ID, json=None):
# TODO: cache queries?
class Query(object):
- rate_limit = 1.0 # max queries per second
+ rate_limit = 1.1 # seconds between queries
last_query = time.time() - 1.5
@classmethod
self._covers[(int(m.group(1)), int(m.group(2)))] = fl
def fetch_cover(self, albumid, size):
- Query._ratelimit() # ratelimit cover fetching too?
coverdir = _COVERDIR if _COVERDIR else '/tmp'
to = os.path.join(coverdir, '%d-%d.jpg'%(albumid, size))
if not os.path.isfile(to):
class JamendoAPIException(Exception):
def __init__(self, url):
- Exception.__init__(url)
+ Exception.__init__(self, url)
def _update_cache(cache, new_items):
if not isinstance(new_items, list):