''' 8tracks XBMC Plugin Copyright (C) 2011 t0mm0 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 3 of the License, 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, see <http://www.gnu.org/licenses/>. ''' import Addon import os.path import re import simplejson as json import urllib, urllib2 import xbmc class EightTracks: _BASE_URL = 'http://8tracks.com' _API_KEY = '04e89b30c1ae4f38e9f7a2fc3a6c55153ba7b98f' SORT_RECENT = 'recent' SORT_HOT = 'hot' SORT_POPULAR = 'popular' SORT_RANDOM = 'random' def __init__(self): set_path = xbmc.translatePath(os.path.join(Addon.profile_path, 'set')) try: os.makedirs(os.path.dirname(set_path)) except OSError: pass try: Addon.log('loading set number') f = open(set_path) self._set = f.readline().strip() f.close() except IOError: Addon.log('getting set number') f = open(set_path, 'w') self._set = self.new_set() f.write(self._set) f.close() def new_set(self): return self._get_json('sets/new')['play_token'] def mixes(self, sort='hot', tag='', search='', page=1): return self._get_json('mixes', {'sort': sort, 'tag': tag, 'q': search, 'page': page}) def play(self, mix_id): return self._get_json('sets/%s/play' % self._set, {'mix_id': mix_id}) def next(self, mix_id): return self._get_json('sets/%s/next' % self._set, {'mix_id': mix_id}) def next_mix(self, mix_id): return self._get_json('sets/%s/next_mix' % self._set, {'mix_id': mix_id}) def tags(self, page): return self._get_json('all/mixes/tags', {'tag_page': page}) def _build_url(self, path, queries={}): query = Addon.build_query(queries) return '%s/%s?%s' % (self._BASE_URL, path, query) def _fetch(self, url, form_data=False): if form_data: Addon.log('posting: %s %s' % (url, str(form_data))) req = urllib2.Request(url, form_data) else: Addon.log('getting: ' + url) req = url try: response = urllib2.urlopen(url) return response except urllib2.URLError, e: Addon.log(str(e), True) return False def _get_html(self, path, queries={}): html = False url = self._build_url(path, queries) response = self._fetch(url) if response: html = response.read() else: html = False return html def _get_json(self, method, queries={}): json_response = None queries['api_key'] = self._API_KEY url = self._build_url(method + '.json', queries) Addon.log('getting ' + url) try: response = urllib2.urlopen(url) try: json_response = json.loads(response.read()) except ValueError: Addon.show_error([Addon.get_string(30005)]) return False except urllib2.URLError, e: Addon.show_error([Addon.get_string(30006), str(e.reason)]) return False if json_response.get('errors', None): Addon.show_error(str(json_response['errors'][0])) return False else: return json_response class EightTracksPlayer(xbmc.Player): def __init__(self, *args, **kwargs): xbmc.Player.__init__(self) self.et = kwargs['et'] self.pl = Addon.get_playlist(xbmc.PLAYLIST_MUSIC, True) self.ended = False self.track_playing = False def onPlayBackStarted(self): Addon.log('onPlayBackStarted') self.add_next() def onPlayBackStopped(self): Addon.log('onPlayBackStopped') self.ended = True def play_mix(self, mix_id, mix_name, user, img): Addon.log('play_mix') self.mix_id = mix_id self.mix_name = mix_name self.user = user self.img = img self.add_next(True) self.play(self.pl) while not self.ended: Addon.log('player sleeping...') xbmc.sleep(1000) def add_next(self, first=False): Addon.log('add_next') if first: result = self.et.play(self.mix_id) else: result = self.et.next(self.mix_id) if result['set']['at_end']: Addon.log('moving to next mix') result = self.et.next_mix(self.mix_id) next_mix = result['next_mix'] self.mix_id = next_mix['id'] self.mix_name = next_mix['name'] self.user = next_mix['user']['login'] self.img = next_mix['cover_urls']['max200'] result = self.et.play(self.mix_id) t = result['set']['track'] comment = 'mix: %s by %s' % (self.mix_name, self.user) Addon.add_music_item(t['url'], {'title': t['name'], 'artist': t['performer'], 'comment': comment, 'album': t['release_name']}, img=self.img, playlist=self.pl) while not self.isPlaying() and not first and not self.ended: Addon.log('player sleeping (add_next)...') xbmc.sleep(1000)