class PaginateTestCase(unittest.TestCase): def setUp(self): self.fm = LastFM() self.query = 'winter' def page(self, results): new_results = self.fm.next_page(results) self.assertTrue(results != None, "No results found for this query.") self.assertTrue(new_results != None, "No results found for the second page of this query") self.assertTrue( results['results']['opensearch:startIndex'] != new_results['results']['opensearch:startIndex'], "The page did not correctly increment.") prev_results = self.fm.prev_page(new_results) self.assertDictEqual( prev_results, results, "The previous results don't match the first results provided") def test_artist_page_results(self): self.page(self.fm.artist.search(artist=self.query)) def test_album_page_results(self): self.page(self.fm.album.search(album=self.query)) def test_track_page_results(self): self.page(self.fm.track.search(track=self.query))
def __init__(self, username): super(LastFMTrackListener, self).__init__() self._lfm_user = username self._lfm = LastFM(self._lfm_user) self._last_playing_music = None self._lastfm_music_track_change() gobject.timeout_add(self.INTERVAL, self._lastfm_periodic_check)
def get_dataset(): debug_print("Obtaining dataset...") # save time by loading any existing dataset if os.path.isfile(DATASET_FILENAME): dataset = json.load(open(DATASET_FILENAME)) if len(dataset) == DATASET_SIZE: debug_print("Existing dataset found!") return dataset dataset = {} artists = set() # initialize LastFM API object and get artist list lastreq = LastFM() response = lastreq.get_artists(DATASET_SIZE) # initialize all artist tag sets for artist in response["artists"]["artist"]: dataset[artist["name"]] = set() # get tags for each artist count = 1 for artist in dataset.keys(): debug_print("Acquiring tags for artist " + str(count) + " of " + str(DATASET_SIZE)) response = lastreq.get_toptags(artist) for tag in response["toptags"]["tag"]: dataset[artist].add(tag["name"]) count += 1 # save the dataset, because it probably took a while to get debug_print("Dataset complete. Saving...") json.dump(dataset, open(DATASET_FILENAME, 'wb'), default=set_default) return dataset
def __init__(self): self.__youtube = Youtube() self.__spotify = Spotify() self.__editor = TagEditor() self.__last = LastFM() self.__apple = AppleMusic() self.__deezer = Deezer()
def __init__(self, metadatautils=None): '''Initialize - optionaly provide our base MetadataUtils class''' if not metadatautils: from metadatautils import MetadataUtils self.metadatautils = MetadataUtils else: self.metadatautils = metadatautils self.cache = self.metadatautils.cache self.lastfm = LastFM() self.mbrainz = MusicBrainz() self.audiodb = TheAudioDb()
def OnScrobble(self, event): """Scrobbles using LastFM and sets a confirmation dialog""" try: lfm = LastFM() starttime = int(time.time()) lfm.scrobble(self.artistText.GetValue(), self.titleText.GetValue(), starttime) wx.MessageBox("Scrobbled: {} - {}".format( self.artistText.GetValue(), self.titleText.GetValue()), "Done", wx.OK) self.artistText.SetValue("") self.titleText.SetValue("") except lastfm.pylast.WSError as e: wx.MessageBox(str(e), 'Uh Oh', wx.OK | wx.ICON_ERROR)
class LastFMTrackListener(gobject.GObject): __gsignals__ = { 'music-track-changed': (gobject.SIGNAL_RUN_LAST, None, (object,)), } # polling period in milliseconds INTERVAL = 60000 #LastFM.MAX_DELAY * 250 # 1/4 of LastFM's delay (in s) _instance = None @classmethod def get(cls, username): if cls._instance is None: cls._instance = cls(username) else: cls._instance._lfm.setUsername(username) return cls._instance def __init__(self, username): super(LastFMTrackListener, self).__init__() self._lfm_user = username self._lfm = LastFM(self._lfm_user) self._last_playing_music = None self._lastfm_music_track_change() gobject.timeout_add(self.INTERVAL, self._lastfm_periodic_check) def _lastfm_properties_extract(self, song_tuple): if song_tuple: info = LastFMTrackInfo() info.title = song_tuple[LastFM.NAME] info.album = song_tuple[LastFM.ALBUM] info.artist = song_tuple[LastFM.ARTIST] return info return None def _lastfm_periodic_check(self): if self._lfm.updateData(): self._lastfm_music_track_change() return True def _lastfm_music_track_change(self): info = self._lastfm_properties_extract( self._lfm.getLastRecentSong()) self._last_playing_music = info self.emit('music-track-changed', info) def get_playing_track(self): '''Return a LastFMTrackInfo for the currently playing song, or None if no song is playing''' return self._last_playing_music
class LastFMTrackListener(gobject.GObject): __gsignals__ = { 'music-track-changed': (gobject.SIGNAL_RUN_LAST, None, (object, )), } # polling period in milliseconds INTERVAL = 60000 #LastFM.MAX_DELAY * 250 # 1/4 of LastFM's delay (in s) _instance = None @classmethod def get(cls, username): if cls._instance is None: cls._instance = cls(username) else: cls._instance._lfm.setUsername(username) return cls._instance def __init__(self, username): super(LastFMTrackListener, self).__init__() self._lfm_user = username self._lfm = LastFM(self._lfm_user) self._last_playing_music = None self._lastfm_music_track_change() gobject.timeout_add(self.INTERVAL, self._lastfm_periodic_check) def _lastfm_properties_extract(self, song_tuple): if song_tuple: info = LastFMTrackInfo() info.title = song_tuple[LastFM.NAME] info.album = song_tuple[LastFM.ALBUM] info.artist = song_tuple[LastFM.ARTIST] return info return None def _lastfm_periodic_check(self): if self._lfm.updateData(): self._lastfm_music_track_change() return True def _lastfm_music_track_change(self): info = self._lastfm_properties_extract(self._lfm.getLastRecentSong()) self._last_playing_music = info self.emit('music-track-changed', info) def get_playing_track(self): '''Return a LastFMTrackInfo for the currently playing song, or None if no song is playing''' return self._last_playing_music
class API(object): def __init__(self): self.mb = MusicBrainz() self.lastfm = LastFM() def search(self, query, query_type): results = self.mb.search(query, query_type)[query_type+'s'] objects = [] for result in results: try: Artist.objects.get(mbid=result['id']) except Artist.DoesNotExist: artist_info = self.lastfm.get_artist_by_mbid(result['id']) if 'artist' in artist_info: Artist( name=artist_info['artist']['name'], description=artist_info['artist']['bio']['content'], mbid=result['id'] ).save() return objects
def OnScrobble(self, event): """Scrobbles using LastFM and sets a confirmation dialog""" try: lfm = LastFM() starttime = int(time.time()) lfm.scrobble(self.artistText.GetValue(), self.titleText.GetValue(), starttime) wx.MessageBox( "Scrobbled: {} - {}".format(self.artistText.GetValue(), self.titleText.GetValue()), "Done", wx.OK) self.artistText.SetValue("") self.titleText.SetValue("") except lastfm.pylast.WSError as e: wx.MessageBox(str(e), 'Uh Oh', wx.OK | wx.ICON_ERROR)
def setUp(self): self.fm = LastFM() self.artist_name = "Wintersleep" self.artist_mbid = 'cda8e877-fe39-4939-8b09-045d68617367' self.track_name = "Jaws of Life" self.album_name = "Untitled" self.track_mbid = 'e0b110b4-fef4-473a-9c42-207d3c92cae0'
def __init__(self): mixer.init() self._paused = False self.currentTrack = None self.last = LastFM() self.offset = 0 self.playQueue = Queue.Queue(-1) # queue of 'infinite' size self.previous = [] #using a list as a stack to hold previous plays
def search(self): self.albumBox.Clear() self.trackBox.Clear() try: lfm = LastFM() results = lfm.albumSearch( self.albumText.GetValue()).get_next_page() for result in results: self.albumBox.Append( result.get_artist().name + " - " + result.get_title() + " - " + result.get_release_date().split(',')[0], result) if len(results) == 0: wx.MessageBox( "No matches found for {}".format( self.albumText.GetValue()), 'Uh Oh', wx.OK | wx.ICON_ERROR) except lastfm.pylast.WSError as e: wx.MessageBox(str(e), 'Uh Oh', wx.OK | wx.ICON_ERROR) except last.pylast.NetworkError as e: wx.MessageBox(str(e), 'Uh Oh', wx.OK | wx.ICON_ERROR)
def onScrobbleAlbum(self, event): try: lfm = LastFM() selectedAlbum = self.albumBox.GetClientData(event.GetSelection()) starttime = int(time.time()) - 90 album = selectedAlbum.get_title() noTracks = 0 for track in selectedAlbum.get_tracks(): noTracks += 1 starttime += 10 artist = track.artist.name title = track.title lfm.scrobble(artist, title, starttime) #confirmation: wx.MessageBox( "Scrobbled: {} - {} ({} tracks).".format( artist.encode('utf-8'), album.encode('utf-8'), noTracks), "Done", wx.OK) except lastfm.pylast.WSError as e: wx.MessageBox(str(e), 'Uh Oh', wx.OK | wx.ICON_ERROR) except wx._core.PyAssertionError: wx.MessageBox("Nothing selected to scrobble", 'Uh Oh', wx.OK | wx.ICON_ERROR)
class API(object): def __init__(self): self.mb = MusicBrainz() self.lastfm = LastFM() def search(self, query, query_type): results = self.mb.search(query, query_type)[query_type + 's'] objects = [] for result in results: try: Artist.objects.get(mbid=result['id']) except Artist.DoesNotExist: artist_info = self.lastfm.get_artist_by_mbid(result['id']) if 'artist' in artist_info: Artist(name=artist_info['artist']['name'], description=artist_info['artist']['bio']['content'], mbid=result['id']).save() return objects
class MusicDownloader(object): def __init__(self): self.__youtube = Youtube() self.__spotify = Spotify() self.__editor = TagEditor() self.__last = LastFM() self.__apple = AppleMusic() self.__deezer = Deezer() def __downloadMusicFromYoutube(self, name, uri, dur): #finding song on youtube self.__youtube.get(name, dur) #downloading video from youtube if self.__youtube.download(url=self.__youtube.getResult(), path=uri, filename=uri): #converting video to mp3 file self.__youtube.convertVideoToMusic(uri=uri) return True else: return False def __getSongInfoFromSpotify(self, uri): try: return self.__spotify.getSongInfo(uri) except: return None def getNameFromYoutube(self, url): return self.__youtube.getNameFromYoutube(url) def getData(self, uri): try: return self.__spotify.getSongInfo(uri) except: return None def getLastFMTags(self, name): return self.__last.get(name) def getYoutubeMusicInfo(self, url): return self.__youtube.getNameFromYoutube(url) def downloadBySpotifyUri(self, uri, path): #get info info = self.__getSongInfoFromSpotify(uri) if info: fixed_name = f'{info["artist"][0]} - {info["name"]}' fixed_name = fixed_name.replace('.', '') fixed_name = fixed_name.replace(',', '') fixed_name = fixed_name.replace("'", '') fixed_name = fixed_name.replace("/", "") #finding and download from YouTube and tagging if self.__downloadMusicFromYoutube(fixed_name, info['uri'], info['duration_ms']): self.__editor.setTags(data=info) cachepath = os.getcwd() + '/cache' fullpath = os.getcwd() + '/Downloads' if not os.path.exists(fullpath): os.makedirs(fullpath) name = f'{info["artist"][0]} - {info["name"]}' os.rename(f"{cachepath}/{info['uri']}/{info['uri']}.mp3", f"{fullpath}/{getCorrect(name)}.mp3") print(path) if path: os.rename(f"{fullpath}/{getCorrect(name)}.mp3", f"{path}/{getCorrect(name)}.mp3") #deleting cache try: shutil.rmtree(f"cache/{info['uri']}") except: pass notify.send(f'{info["artist"][0]} - {info["name"]}') return True return False def downloadBySearchQuery(self, query, path=None): #get info info = self.__spotify.search(query=query) if not info: info = self.__last.get(query) if info: fixed_name = f'{info["artist"][0]} - {info["name"]}' fixed_name = fixed_name.replace('.', '') fixed_name = fixed_name.replace(',', '') fixed_name = fixed_name.replace("'", '') fixed_name = fixed_name.replace("/", "") #finding and download from YouTube and tagging self.__downloadMusicFromYoutube(fixed_name, info['uri'], info['duration_ms']) self.__editor.setTags(data=info) cachepath = os.getcwd() + '/cache' fullpath = os.getcwd() + '/Downloads' if not os.path.exists(fullpath): os.makedirs(fullpath) name = f'{info["artist"][0]} - {info["name"]}' os.rename(f"{cachepath}/{info['uri']}/{info['uri']}.mp3", f"{fullpath}/{getCorrect(name)}.mp3") if path: os.rename(f"{fullpath}/{getCorrect(name)}.mp3", f"{path}/{getCorrect(name)}.mp3") #deleting cache try: shutil.rmtree(f"cache/{info['uri']}") except: pass notify.send(f'{info["artist"][0]} - {info["name"]}') return True, info else: return False, None def downloadBySpotifyUriFromFile(self, filename): try: with open(filename, 'r') as f: data = f.readlines() except FileNotFoundError: print(f'No such file or directory: "{filename}"') exit(2) #normalize try: data.remove('\n') except: pass links = [str(item).replace('\n', '') for item in data] for i, song in zip(range(len(links)), links): print(f'[{i+1}] - {song}') try: state = self.downloadBySpotifyUri(str(song).split(':')[-1]) if not state: notify.send(f'Failed to download', True) except: print('Something went wrong!') def downloadBySpotifyUriPlaylistMode(self, playlist_uri, path): user = Spotify.User() playlist = user.getPlaylistTracks(playlist_uri) for info, i in zip(playlist, range(len(playlist))): print(f'Downloading {i+1} of {len(playlist)}') fixed_name = f'{info["artist"][0]} - {info["name"]}' fixed_name = fixed_name.replace('.', '') fixed_name = fixed_name.replace(',', '') fixed_name = fixed_name.replace("'", '') fixed_name = fixed_name.replace("/", "") #finding and download from YouTube and tagging self.__downloadMusicFromYoutube(fixed_name, info['uri'], info['duration_ms']) self.__editor.setTags(data=info) cachepath = os.getcwd() + '/cache' fullpath = os.getcwd() + '/Downloads' if not os.path.exists(fullpath): os.makedirs(fullpath) name = f'{info["artist"][0]} - {info["name"]}' os.rename(f"{cachepath}/{info['uri']}/{info['uri']}.mp3", f"{fullpath}/{getCorrect(name)}.mp3") if path: os.rename(f"{fullpath}/{getCorrect(name)}.mp3", f"{path}/{getCorrect(name)}.mp3") #deleting cache try: shutil.rmtree(f"cache/{info['uri']}") except: pass notify.send(f'{info["artist"][0]} - {info["name"]}') def downloadBySpotifyUriAlbumMode(self, album_uri, path): user = Spotify() playlist = user.getAlbum(album_uri) for info, i in zip(playlist['tracks'], range(len(playlist['tracks']))): print(f'Downloading {i+1} of {len(playlist["tracks"])}') fixed_name = f'{info["artist"][0]} - {info["name"]}' fixed_name = fixed_name.replace('.', '') fixed_name = fixed_name.replace(',', '') fixed_name = fixed_name.replace("'", '') fixed_name = fixed_name.replace("/", "") #finding and downloading from YouTube and tagging self.__downloadMusicFromYoutube(fixed_name, info['uri'], info['duration_ms']) self.__editor.setTags(data=info) cachepath = os.getcwd() + '/cache' fullpath = os.getcwd() + '/Downloads' if not os.path.exists(fullpath): os.makedirs(fullpath) name = f'{info["artist"][0]} - {info["name"]}' os.rename(f"{cachepath}/{info['uri']}/{info['uri']}.mp3", f"{fullpath}/{getCorrect(name)}.mp3") if path: os.rename(f"{fullpath}/{getCorrect(name)}.mp3", f"{path}/{getCorrect(name)}.mp3") #deleting cache try: shutil.rmtree(f"cache/{info['uri']}") except: pass notify.send(f'{info["artist"][0]} - {info["name"]}') def downloadByDeezerUrl(self, url, path): link = str(str(url).split('/')[-1]).split('?')[0] #get info info = self.__deezer.getSongInfo(link) if info: fixed_name = f'{info["artist"][0]} - {info["name"]}' fixed_name = fixed_name.replace('.', '') fixed_name = fixed_name.replace(',', '') fixed_name = fixed_name.replace("'", '') fixed_name = fixed_name.replace("/", "") #finding and download from YouTube and tagging if self.__downloadMusicFromYoutube(fixed_name, info['uri'], info['duration_ms']): self.__editor.setTags(data=info) cachepath = os.getcwd() + '/cache' fullpath = os.getcwd() + '/Downloads' if not os.path.exists(fullpath): os.makedirs(fullpath) name = f'{info["artist"][0]} - {info["name"]}' os.rename(f"{cachepath}/{info['uri']}/{info['uri']}.mp3", f"{fullpath}/{getCorrect(name)}.mp3") print(path) if path: os.rename(f"{fullpath}/{getCorrect(name)}.mp3", f"{path}/{getCorrect(name)}.mp3") #deleting cache try: shutil.rmtree(f"cache/{info['uri']}") except: pass notify.send(f'{info["artist"][0]} - {info["name"]}') return True return False def downloadByDeezerUrlAlbumMode(self, album_url, path): link = str(str(album_url).split('/')[-1]).split('?')[0] #get info playlist = self.__deezer.getAlbum(link) for info, i in zip(playlist['tracks'], range(len(playlist['tracks']))): print(f'Downloading {i+1} of {len(playlist["tracks"])}') fixed_name = f'{info["artist"][0]} - {info["name"]}' fixed_name = fixed_name.replace('.', '') fixed_name = fixed_name.replace(',', '') fixed_name = fixed_name.replace("'", '') fixed_name = fixed_name.replace("/", "") #finding and downloading from YouTube and tagging self.__downloadMusicFromYoutube(fixed_name, info['uri'], info['duration_ms']) self.__editor.setTags(data=info) cachepath = os.getcwd() + '/cache' fullpath = os.getcwd() + '/Downloads' if not os.path.exists(fullpath): os.makedirs(fullpath) name = f'{info["artist"][0]} - {info["name"]}' os.rename(f"{cachepath}/{info['uri']}/{info['uri']}.mp3", f"{fullpath}/{getCorrect(name)}.mp3") if path: os.rename(f"{fullpath}/{getCorrect(name)}.mp3", f"{path}/{getCorrect(name)}.mp3") #deleting cache try: shutil.rmtree(f"cache/{info['uri']}") except: pass notify.send(f'{info["artist"][0]} - {info["name"]}') def downloadByDeezerUrlPlaylistMode(self, playlist_url, path): link = str(str(playlist_url).split('/')[-1]).split('?')[0] #get info playlist = self.__deezer.getPlaylist(link) for info, i in zip(playlist['tracks'], range(len(playlist['tracks']))): print(f'Downloading {i+1} of {len(playlist["tracks"])}') fixed_name = f'{info["artist"][0]} - {info["name"]}' fixed_name = fixed_name.replace('.', '') fixed_name = fixed_name.replace(',', '') fixed_name = fixed_name.replace("'", '') fixed_name = fixed_name.replace("/", "") #finding and download from YouTube and tagging self.__downloadMusicFromYoutube(fixed_name, info['uri'], info['duration_ms']) self.__editor.setTags(data=info) cachepath = os.getcwd() + '/cache' fullpath = os.getcwd() + '/Downloads' if not os.path.exists(fullpath): os.makedirs(fullpath) name = f'{info["artist"][0]} - {info["name"]}' os.rename(f"{cachepath}/{info['uri']}/{info['uri']}.mp3", f"{fullpath}/{getCorrect(name)}.mp3") if path: os.rename(f"{fullpath}/{getCorrect(name)}.mp3", f"{path}/{getCorrect(name)}.mp3") #deleting cache try: shutil.rmtree(f"cache/{info['uri']}") except: pass notify.send(f'{info["artist"][0]} - {info["name"]}') def downloadFromYoutubeMusic(self, url, info, path): print(info) uri = info['uri'] #downloading video from youtube if self.__youtube.download(url=url, path=uri, filename=uri): #converting video to mp3 file self.__youtube.convertVideoToMusic(uri=uri) self.__editor.setTags(data=info) cachepath = os.getcwd() + '/cache' fullpath = os.getcwd() + '/Downloads' if not os.path.exists(fullpath): os.makedirs(fullpath) name = f'{info["artist"][0]} - {info["name"]}' os.rename(f"{cachepath}/{info['uri']}/{info['uri']}.mp3", f"{fullpath}/{getCorrect(name)}.mp3") if path: os.rename(f"{fullpath}/{getCorrect(name)}.mp3", f"{path}/{getCorrect(name)}.mp3") #deleting cache try: shutil.rmtree(f"cache/{info['uri']}") except: pass notify.send(f'{info["artist"][0]} - {info["name"]}') return True, info else: return False, None def search(self, query): return self.__spotify.search(query=query)
def setUp(self): self.fm = LastFM() self.artist_name = 'Wintersleep' self.album_name = "New Inheritors" self.album_mbid = '3f46329d-b15c-494b-912e-b802a5a8a3bb'
def setUp(self): self.fm = LastFM() self.artist_name = 'Wintersleep' self.artist_mbid = 'cda8e877-fe39-4939-8b09-045d68617367'
import telebot from lastfm import LastFM TelegramBot = telebot.TeleBot('734127522:AAGBKswjLU9gXLmiEQVbee6D5_PAMJIDtLs') LastFM = LastFM() @TelegramBot.message_handler(content_types=['text']) def get_text_messages(message): """ Main function of bot, which reads messages and does various outputs, according to the input :param message: :return: """ if message.text == '/help': TelegramBot.send_message(message.from_user.id, "/help - помощь. \n" " /artist_albums - показать топ альбомы артиста. \n " "/artist_tracks - показать треки артиста. \n " "/similar_tracks - показать похожие треки") else: if LastFM.state == 'state: home': if message.text == '/artist_albums': TelegramBot.send_message(message.from_user.id, "Напиши артиста") LastFM.state = 'state: /artist_albums. phase: get_artist' elif message.text == '/artist_tracks': LastFM.state = 'state: /artist_tracks. phase: get_artist' TelegramBot.send_message(message.from_user.id, "Напиши артиста") elif message.text == '/similar_tracks': LastFM.state = 'state: /similar_tracks. phase: get_artist' TelegramBot.send_message(message.from_user.id, "Напиши артиста")
def get_text_messages(message): """ Main function of bot, which reads messages and does various outputs, according to the input :param message: :return: """ if message.text == '/help': TelegramBot.send_message(message.from_user.id, "/help - помощь. \n" " /artist_albums - показать топ альбомы артиста. \n " "/artist_tracks - показать треки артиста. \n " "/similar_tracks - показать похожие треки") else: if LastFM.state == 'state: home': if message.text == '/artist_albums': TelegramBot.send_message(message.from_user.id, "Напиши артиста") LastFM.state = 'state: /artist_albums. phase: get_artist' elif message.text == '/artist_tracks': LastFM.state = 'state: /artist_tracks. phase: get_artist' TelegramBot.send_message(message.from_user.id, "Напиши артиста") elif message.text == '/similar_tracks': LastFM.state = 'state: /similar_tracks. phase: get_artist' TelegramBot.send_message(message.from_user.id, "Напиши артиста") else: TelegramBot.send_message(message.from_user.id, "Напиши /help.") elif LastFM.state == 'state: /artist_albums. phase: get_artist': LastFM.artist = message.text LastFM.state = 'state: /artist_albums. phase: get_num' TelegramBot.send_message(message.from_user.id, "Напиши сколько вывести альбомов") elif LastFM.state == 'state: /artist_albums. phase: get_num': try: LastFM.num = int(message.text) data_sender(message, LastFM.artist_albums(LastFM.artist, LastFM.num)) except Exception: TelegramBot.send_message(message.from_user.id, 'Error') LastFM.state = 'state: home' elif LastFM.state == 'state: /artist_tracks. phase: get_artist': LastFM.artist = message.text LastFM.state = 'state: /artist_tracks. phase: get_num' TelegramBot.send_message(message.from_user.id, "Напиши сколько вывести треков") elif LastFM.state == 'state: /artist_tracks. phase: get_num': try: LastFM.num = int(message.text) data_sender(message, LastFM.artist_tracks(LastFM.artist, LastFM.num)) except Exception: TelegramBot.send_message(message.from_user.id, 'Error') LastFM.state = 'state: home' elif LastFM.state == 'state: /similar_tracks. phase: get_artist': LastFM.artist = message.text LastFM.state = 'state: /similar_tracks. phase: get_track' TelegramBot.send_message(message.from_user.id, "Напиши трек") elif LastFM.state == 'state: /similar_tracks. phase: get_track': LastFM.track = message.text LastFM.state = 'state: /similar_tracks. phase: get_num' TelegramBot.send_message(message.from_user.id, "Напиши сколько") elif LastFM.state == 'state: /similar_tracks. phase: get_num': try: LastFM.num = int(message.text) data_sender(message, LastFM.artist_tracks(LastFM.artist, LastFM.num)) except Exception: TelegramBot.send_message(message.from_user.id, 'Error') LastFM.state = 'state: home'
class MusicArtwork(object): '''get metadata and artwork for music''' def __init__(self, metadatautils=None): '''Initialize - optionaly provide our base MetadataUtils class''' if not metadatautils: from metadatautils import MetadataUtils self.metadatautils = MetadataUtils else: self.metadatautils = metadatautils self.cache = self.metadatautils.cache self.lastfm = LastFM() self.mbrainz = MusicBrainz() self.audiodb = TheAudioDb() def get_music_artwork(self, artist, album, track, disc, ignore_cache=False, flush_cache=False, manual=False): ''' get music metadata by providing artist and/or album/track returns combined result of artist and album metadata ''' if artist == track or album == track: track = "" artists = self.get_all_artists(artist, track) album = self.get_clean_title(album) track = self.get_clean_title(track) # retrieve artist and album details artist_details = self.get_artists_metadata(artists, album, track, ignore_cache=ignore_cache, flush_cache=flush_cache, manual=manual) album_artist = artist_details.get("albumartist", artists[0]) if album or track: album_details = self.get_album_metadata(album_artist, album, track, disc, ignore_cache=ignore_cache, flush_cache=flush_cache, manual=manual) else: album_details = {"art": {}} # combine artist details and album details details = extend_dict(album_details, artist_details) # combine artist plot and album plot as extended plot if artist_details.get("plot") and album_details.get("plot"): details["extendedplot"] = "%s -- %s" % (album_details["plot"], artist_details["plot"]) else: details["extendedplot"] = details.get("plot", "") # append track title to results if track: details["title"] = track # return the endresult return details def music_artwork_options(self, artist, album, track, disc): '''show options for music artwork''' options = [] options.append(self.metadatautils.addon.getLocalizedString(32028)) # Refresh item (auto lookup) options.append(self.metadatautils.addon.getLocalizedString(32036)) # Choose art options.append(self.metadatautils.addon.getLocalizedString(32034)) # Open addon settings header = self.metadatautils.addon.getLocalizedString(32015) dialog = xbmcgui.Dialog() ret = dialog.select(header, options) del dialog if ret == 0: # Refresh item (auto lookup) self.get_music_artwork(artist, album, track, disc, ignore_cache=True) elif ret == 1: # Choose art self.get_music_artwork(artist, album, track, disc, ignore_cache=True, manual=True) elif ret == 2: # Open addon settings xbmc.executebuiltin("Addon.OpenSettings(%s)" % ADDON_ID) def get_artists_metadata(self, artists, album, track, ignore_cache=False, flush_cache=False, manual=False): '''collect artist metadata for all artists''' artist_details = {"art": {}} # for multi artist songs/albums we grab details from all artists if len(artists) == 1: # single artist artist_details = self.get_artist_metadata( artists[0], album, track, ignore_cache=ignore_cache, flush_cache=flush_cache, manual=manual) artist_details["albumartist"] = artists[0] else: # multi-artist track # The first artist with details is considered the main artist # all others are assumed as featuring artists artist_details = {"art": {}} feat_artist_details = [] for artist in artists: if not (artist_details.get("plot") or artist_details.get("art")): # get main artist details artist_details["albumartist"] = artist artist_details = self.get_artist_metadata( artist, album, track, ignore_cache=ignore_cache, manual=manual) else: # assume featuring artist feat_artist_details.append(self.get_artist_metadata( artist, album, track, ignore_cache=ignore_cache, manual=manual)) # combined images to use as multiimage (for all artists) # append featuring artist details for arttype in ["banners", "fanarts", "clearlogos", "thumbs"]: combined_art = [] for artist_item in [artist_details] + feat_artist_details: art = artist_item["art"].get(arttype, []) if isinstance(art, list): for item in art: if item not in combined_art: combined_art.append(item) else: for item in self.metadatautils.kodidb.files(art): if item["file"] not in combined_art: combined_art.append(item["file"]) if combined_art: # use the extrafanart plugin entry to display multi images artist_details["art"][arttype] = "plugin://script.skin.helper.service/"\ "?action=extrafanart&fanarts=%s" % quote_plus(repr(combined_art)) # also set extrafanart path if arttype == "fanarts": artist_details["art"]["extrafanart"] = artist_details["art"][arttype] # return the result return artist_details # pylint: disable-msg=too-many-local-variables def get_artist_metadata(self, artist, album, track, ignore_cache=False, flush_cache=False, manual=False): '''collect artist metadata for given artist''' details = {"art": {}} cache_str = "music_artwork.artist.%s" % artist.lower() # retrieve details from cache cache = self.metadatautils.cache.get(cache_str) if not cache and flush_cache: # nothing to do - just return empty results return details elif cache and flush_cache: # only update kodi metadata for updated counts etc details = extend_dict(self.get_artist_kodi_metadata(artist), cache) elif cache and not ignore_cache: # we have a valid cache - return that details = cache elif cache and manual: # user wants to manually override the artwork in the cache details = self.manual_set_music_artwork(cache, "artist") else: # nothing in cache - start metadata retrieval log_msg("get_artist_metadata --> artist: %s - album: %s - track: %s" % (artist, album, track)) details["cachestr"] = cache_str local_path = "" local_path_custom = "" # get metadata from kodi db details = extend_dict(details, self.get_artist_kodi_metadata(artist)) # get artwork from songlevel path if details.get("diskpath") and self.metadatautils.addon.getSetting("music_art_musicfolders") == "true": details["art"] = extend_dict(details["art"], self.lookup_artistart_in_folder(details["diskpath"])) local_path = details["diskpath"] # get artwork from custom folder if self.metadatautils.addon.getSetting("music_art_custom") == "true": custom_path = self.metadatautils.addon.getSetting("music_art_custom_path").decode("utf-8") if custom_path: diskpath = self.get_customfolder_path(custom_path, artist) log_msg("custom path on disk for artist: %s --> %s" % (artist, diskpath)) if diskpath: details["art"] = extend_dict(details["art"], self.lookup_artistart_in_folder(diskpath)) local_path_custom = diskpath details["customartpath"] = diskpath # lookup online metadata if self.metadatautils.addon.getSetting("music_art_scraper") == "true": if not album and not track: album = details.get("ref_album") track = details.get("ref_track") # prefer the musicbrainzid that is already in the kodi database - only perform lookup if missing mb_artistid = details.get("musicbrainzartistid", self.get_mb_artist_id(artist, album, track)) details["musicbrainzartistid"] = mb_artistid if mb_artistid: # get artwork from fanarttv if self.metadatautils.addon.getSetting("music_art_scraper_fatv") == "true": details["art"] = extend_dict(details["art"], self.metadatautils.fanarttv.artist(mb_artistid)) # get metadata from theaudiodb if self.metadatautils.addon.getSetting("music_art_scraper_adb") == "true": details = extend_dict(details, self.audiodb.artist_info(mb_artistid)) # get metadata from lastfm if self.metadatautils.addon.getSetting("music_art_scraper_lfm") == "true": details = extend_dict(details, self.lastfm.artist_info(mb_artistid)) # download artwork to music folder if local_path and self.metadatautils.addon.getSetting("music_art_download") == "true": details["art"] = download_artwork(local_path, details["art"]) # download artwork to custom folder if local_path_custom and self.metadatautils.addon.getSetting("music_art_download_custom") == "true": details["art"] = download_artwork(local_path_custom, details["art"]) # fix extrafanart if details["art"].get("fanarts"): for count, item in enumerate(details["art"]["fanarts"]): details["art"]["fanart.%s" % count] = item if not details["art"].get("extrafanart") and len(details["art"]["fanarts"]) > 1: details["art"]["extrafanart"] = "plugin://script.skin.helper.service/"\ "?action=extrafanart&fanarts=%s" % quote_plus(repr(details["art"]["fanarts"])) # multi-image path for all images for each arttype for arttype in ["banners", "clearlogos", "thumbs"]: art = details["art"].get(arttype, []) if len(art) > 1: # use the extrafanart plugin entry to display multi images details["art"][arttype] = "plugin://script.skin.helper.service/"\ "?action=extrafanart&fanarts=%s" % quote_plus(repr(art)) # set default details if not details.get("artist"): details["artist"] = artist if details["art"].get("thumb"): details["art"]["artistthumb"] = details["art"]["thumb"] # always store results in cache and return results self.metadatautils.cache.set(cache_str, details) return details def get_album_metadata(self, artist, album, track, disc, ignore_cache=False, flush_cache=False, manual=False): '''collect all album metadata''' cache_str = "music_artwork.album.%s.%s.%s" % (artist.lower(), album.lower(), disc.lower()) if not album: cache_str = "music_artwork.album.%s.%s" % (artist.lower(), track.lower()) details = {"art": {}} details["cachestr"] = cache_str # retrieve details from cache cache = self.metadatautils.cache.get(cache_str) if not cache and flush_cache: # nothing to do - just return empty results return details elif cache and flush_cache: # only update kodi metadata for updated counts etc details = extend_dict(self.get_album_kodi_metadata(artist, album, track, disc), cache) elif cache and not ignore_cache: # we have a valid cache - return that details = cache elif cache and manual: # user wants to manually override the artwork in the cache details = self.manual_set_music_artwork(cache, "album") else: # nothing in cache - start metadata retrieval local_path = "" local_path_custom = "" # get metadata from kodi db details = extend_dict(details, self.get_album_kodi_metadata(artist, album, track, disc)) # get artwork from songlevel path if details.get("diskpath") and self.metadatautils.addon.getSetting("music_art_musicfolders") == "true": details["art"] = extend_dict(details["art"], self.lookup_albumart_in_folder(details["diskpath"])) local_path = details["diskpath"] # get artwork from custom folder if self.metadatautils.addon.getSetting("music_art_custom") == "true": custom_path = self.metadatautils.addon.getSetting("music_art_custom_path").decode("utf-8") if custom_path: diskpath = self.get_custom_album_path(custom_path, artist, album, disc) if diskpath: details["art"] = extend_dict(details["art"], self.lookup_albumart_in_folder(diskpath)) local_path_custom = diskpath details["customartpath"] = diskpath # lookup online metadata if self.metadatautils.addon.getSetting("music_art_scraper") == "true": # prefer the musicbrainzid that is already in the kodi database - only perform lookup if missing mb_albumid = details.get("musicbrainzalbumid") if not mb_albumid: mb_albumid = self.get_mb_album_id(artist, album, track) if mb_albumid: # get artwork from fanarttv if self.metadatautils.addon.getSetting("music_art_scraper_fatv") == "true": details["art"] = extend_dict(details["art"], self.metadatautils.fanarttv.album(mb_albumid)) # get metadata from theaudiodb if self.metadatautils.addon.getSetting("music_art_scraper_adb") == "true": details = extend_dict(details, self.audiodb.album_info(mb_albumid)) # get metadata from lastfm if self.metadatautils.addon.getSetting("music_art_scraper_lfm") == "true": details = extend_dict(details, self.lastfm.album_info(mb_albumid)) # metadata from musicbrainz if not details.get("year") or not details.get("genre"): details = extend_dict(details, self.mbrainz.get_albuminfo(mb_albumid)) # musicbrainz thumb as last resort if not details["art"].get("thumb"): details["art"]["thumb"] = self.mbrainz.get_albumthumb(mb_albumid) # download artwork to music folder if local_path and self.metadatautils.addon.getSetting("music_art_download") == "true": details["art"] = download_artwork(local_path, details["art"]) # download artwork to custom folder if local_path_custom and self.metadatautils.addon.getSetting("music_art_download_custom") == "true": details["art"] = download_artwork(local_path_custom, details["art"]) # set default details if not details.get("album") and details.get("title"): details["album"] = details["title"] if details["art"].get("thumb"): details["art"]["albumthumb"] = details["art"]["thumb"] # store results in cache and return results self.metadatautils.cache.set(cache_str, details) return details # pylint: enable-msg=too-many-local-variables def get_artist_kodi_metadata(self, artist): '''get artist details from the kodi database''' details = {} filters = [{"operator": "is", "field": "artist", "value": artist}] result = self.metadatautils.kodidb.artists(filters=filters, limits=(0, 1)) if result: details = result[0] details["title"] = details["artist"] details["plot"] = strip_newlines(details["description"]) if details["musicbrainzartistid"] and isinstance(details["musicbrainzartistid"], list): details["musicbrainzartistid"] = details["musicbrainzartistid"][0] filters = [{"artistid": details["artistid"]}] artist_albums = self.metadatautils.kodidb.albums(filters=filters) details["albums"] = [] details["albumsartist"] = [] details["albumscompilations"] = [] details["tracks"] = [] bullet = "•".decode("utf-8") details["albums.formatted"] = u"" details["tracks.formatted"] = u"" details["tracks.formatted2"] = u"" details["albumsartist.formatted"] = u"" details["albumscompilations.formatted"] = u"" # enumerate albums for this artist for artist_album in artist_albums: details["albums"].append(artist_album["label"]) details["albums.formatted"] += u"%s %s [CR]" % (bullet, artist_album["label"]) if artist in artist_album["displayartist"]: details["albumsartist"].append(artist_album["label"]) details["albumsartist.formatted"] += u"%s %s [CR]" % (bullet, artist_album["label"]) else: details["albumscompilations"].append(artist_album["label"]) details["albumscompilations.formatted"] += u"%s %s [CR]" % (bullet, artist_album["label"]) # enumerate songs for this album filters = [{"albumid": artist_album["albumid"]}] album_tracks = self.metadatautils.kodidb.songs(filters=filters) if album_tracks: # retrieve path on disk by selecting one song for this artist if not details.get("ref_track") and not len(artist_album["artistid"]) > 1: song_path = album_tracks[0]["file"] details["diskpath"] = self.get_artistpath_by_songpath(song_path, artist) details["ref_album"] = artist_album["title"] details["ref_track"] = album_tracks[0]["title"] for album_track in album_tracks: details["tracks"].append(album_track["title"]) tr_title = album_track["title"] if album_track["track"]: tr_title = "%s. %s" % (album_track["track"], album_track["title"]) details["tracks.formatted"] += u"%s %s [CR]" % (bullet, tr_title) duration = album_track["duration"] total_seconds = int(duration) minutes = total_seconds / 60 seconds = total_seconds - (minutes * 60) duration = "%s:%s" % (minutes, str(seconds).zfill(2)) details["tracks.formatted2"] += u"%s %s (%s)[CR]" % (bullet, tr_title, duration) details["albumcount"] = len(details["albums"]) details["albumsartistcount"] = len(details["albumsartist"]) details["albumscompilationscount"] = len(details["albumscompilations"]) # do not retrieve artwork from item as there's no way to write it back # and it will already be retrieved if user enables to get the artwork from the song path return details def get_album_kodi_metadata(self, artist, album, track, disc): '''get album details from the kodi database''' details = {} filters = [{"operator": "contains", "field": "artist", "value": artist}] if artist and track and not album: # get album by track filters.append({"operator": "contains", "field": "title", "value": track}) result = self.metadatautils.kodidb.songs(filters=filters) for item in result: album = item["album"] break if artist and album: filters.append({"operator": "contains", "field": "album", "value": album}) result = self.metadatautils.kodidb.albums(filters=filters) if result: details = result[0] details["plot"] = strip_newlines(details["description"]) filters = [{"albumid": details["albumid"]}] album_tracks = self.metadatautils.kodidb.songs(filters=filters) details["tracks"] = [] bullet = "•".decode("utf-8") details["tracks.formatted"] = u"" details["tracks.formatted2"] = "" details["runtime"] = 0 for item in album_tracks: details["tracks"].append(item["title"]) details["tracks.formatted"] += u"%s %s [CR]" % (bullet, item["title"]) duration = item["duration"] total_seconds = int(duration) minutes = total_seconds / 60 seconds = total_seconds - (minutes * 60) duration = "%s:%s" % (minutes, str(seconds).zfill(2)) details["runtime"] += item["duration"] details["tracks.formatted2"] += u"%s %s (%s)[CR]" % (bullet, item["title"], duration) if not details.get("diskpath"): if not disc or item["disc"] == int(disc): details["diskpath"] = self.get_albumpath_by_songpath(item["file"]) details["art"] = {} details["songcount"] = len(album_tracks) # get album total duration pretty printed as mm:ss total_seconds = int(details["runtime"]) minutes = total_seconds / 60 seconds = total_seconds - (minutes * 60) details["duration"] = "%s:%s" % (minutes, str(seconds).zfill(2)) # do not retrieve artwork from item as there's no way to write it back # and it will already be retrieved if user enables to get the artwork from the song path return details def get_mb_artist_id(self, artist, album, track): '''lookup musicbrainz artist id with query of artist and album/track''' artistid = self.mbrainz.get_artist_id(artist, album, track) if not artistid and self.metadatautils.addon.getSetting("music_art_scraper_lfm") == "true": artistid = self.lastfm.get_artist_id(artist, album, track) if not artistid and self.metadatautils.addon.getSetting("music_art_scraper_adb") == "true": artistid = self.audiodb.get_artist_id(artist, album, track) return artistid def get_mb_album_id(self, artist, album, track): '''lookup musicbrainz album id with query of artist and album/track''' albumid = self.mbrainz.get_album_id(artist, album, track) if not albumid and self.metadatautils.addon.getSetting("music_art_scraper_lfm") == "true": albumid = self.lastfm.get_album_id(artist, album, track) if not albumid and self.metadatautils.addon.getSetting("music_art_scraper_adb") == "true": albumid = self.audiodb.get_album_id(artist, album, track) return albumid def manual_set_music_artwork(self, details, mediatype): '''manual override artwork options''' from utils import manual_set_artwork if mediatype == "artist" and "artist" in details: header = "%s: %s" % (xbmc.getLocalizedString(13511), details["artist"]) else: header = "%s: %s" % (xbmc.getLocalizedString(13511), xbmc.getLocalizedString(558)) changemade, artwork = manual_set_artwork(details["art"], mediatype, header) # save results if any changes made if changemade: details["art"] = artwork refresh_needed = False download_art = self.metadatautils.addon.getSetting("music_art_download") == "true" download_art_custom = self.metadatautils.addon.getSetting("music_art_download_custom") == "true" # download artwork to music folder if needed if details.get("diskpath") and download_art: details["art"] = download_artwork(details["diskpath"], details["art"]) refresh_needed = True # download artwork to custom folder if needed if details.get("customartpath") and download_art_custom: details["art"] = download_artwork(details["customartpath"], details["art"]) refresh_needed = True # reload skin to make sure new artwork is visible if refresh_needed: xbmc.sleep(500) xbmc.executebuiltin("ReloadSkin()") # return endresult return details @staticmethod def get_artistpath_by_songpath(songpath, artist): '''get the artist path on disk by listing the song's path''' result = "" if "\\" in songpath: delim = "\\" else: delim = "/" # just move up the directory tree (max 3 levels) untill we find the directory for trypath in [songpath.rsplit(delim, 2)[0] + delim, songpath.rsplit(delim, 3)[0] + delim, songpath.rsplit(delim, 1)[0] + delim]: if trypath.split(delim)[-2].lower() == artist.lower(): result = trypath break return result @staticmethod def get_albumpath_by_songpath(songpath): '''get the album path on disk by listing the song's path''' if "\\" in songpath: delim = "\\" else: delim = "/" return songpath.rsplit(delim, 1)[0] + delim @staticmethod def lookup_artistart_in_folder(folderpath): '''lookup artwork in given folder''' artwork = {} files = xbmcvfs.listdir(folderpath)[1] for item in files: item = item.decode("utf-8") if item in ["banner.jpg", "clearart.png", "poster.png", "fanart.jpg", "landscape.jpg"]: key = item.split(".")[0] artwork[key] = folderpath + item elif item == "logo.png": artwork["clearlogo"] = folderpath + item elif item == "folder.jpg": artwork["thumb"] = folderpath + item # extrafanarts efa_path = folderpath + "extrafanart/" if xbmcvfs.exists(efa_path): files = xbmcvfs.listdir(efa_path)[1] artwork["fanarts"] = [] if files: artwork["extrafanart"] = efa_path for item in files: item = efa_path + item.decode("utf-8") artwork["fanarts"].append(item) return artwork @staticmethod def lookup_albumart_in_folder(folderpath): '''lookup artwork in given folder''' artwork = {} files = xbmcvfs.listdir(folderpath)[1] for item in files: item = item.decode("utf-8") if item in ["cdart.png", "disc.png"]: artwork["discart"] = folderpath + item if item == "thumbback.jpg": artwork["thumbback"] = folderpath + item if item == "spine.jpg": artwork["spine"] = folderpath + item elif item == "folder.jpg": artwork["thumb"] = folderpath + item return artwork def get_custom_album_path(self, custom_path, artist, album, disc): '''try to locate the custom path for the album''' artist_path = self.get_customfolder_path(custom_path, artist) album_path = "" if artist_path: album_path = self.get_customfolder_path(artist_path, album) if album_path and disc: if "\\" in album_path: delim = "\\" else: delim = "/" dirs = xbmcvfs.listdir(album_path)[0] for directory in dirs: directory = directory.decode("utf-8") if disc in directory: return os.path.join(album_path, directory) + delim return album_path def get_customfolder_path(self, customfolder, foldername, sublevel=False): '''search recursively (max 2 levels) for a specific folder''' cachestr = "customfolder_path.%s.%s" % (customfolder, foldername) folder_path = self.cache.get(cachestr) if not folder_path: if "\\" in customfolder: delim = "\\" else: delim = "/" dirs = xbmcvfs.listdir(customfolder)[0] for strictness in [1, 0.95, 0.9, 0.8]: for directory in dirs: directory = directory.decode("utf-8") curpath = os.path.join(customfolder, directory) + delim match = SM(None, foldername.lower(), directory.lower()).ratio() if match >= strictness: folder_path = curpath elif not sublevel: # check if our requested path is in a sublevel of the current path # restrict the number of sublevels to just one for now for performance reasons folder_path = self.get_customfolder_path(curpath, foldername, True) if folder_path: break if folder_path: break if not sublevel: self.cache.set(cachestr, folder_path) return folder_path @staticmethod def get_clean_title(title): '''strip all unwanted characters from track name''' title = title.split("/")[0] title = title.split("(")[0] title = title.split("[")[0] title = title.split("ft.")[0] title = title.split("Ft.")[0] title = title.split("Feat.")[0] title = title.split("Featuring")[0] title = title.split("featuring")[0] return title.strip() @staticmethod def get_all_artists(artist, track): '''extract multiple artists from both artist and track string''' artists = [] feat_artists = [] # fix for band names which actually contain the kodi splitter (slash) in their name... specials = ["AC/DC"] # to be completed with more artists for special in specials: if special in artist: artist = artist.replace(special, special.replace("/", "")) for splitter in ["ft.", "feat.", "featuring", "Ft.", "Feat.", "Featuring"]: # replace splitter by kodi default splitter for easier split all later artist = artist.replace(splitter, u"/") # extract any featuring artists from trackname if splitter in track: track_parts = track.split(splitter) if len(track_parts) > 1: feat_artist = track_parts[1].replace(")", "").replace("(", "").strip() feat_artists.append(feat_artist) # break all artists string into list all_artists = artist.split("/") + feat_artists for item in all_artists: item = item.strip() if item not in artists: artists.append(item) # & can be a both a splitter or part of artist name for item2 in item.split("&"): item2 = item2.strip() if item2 not in artists: artists.append(item2) return artists
def __init__(self): self.mb = MusicBrainz() self.lastfm = LastFM()
class MusicArtwork(object): '''get metadata and artwork for music''' def __init__(self, metadatautils=None): '''Initialize - optionaly provide our base MetadataUtils class''' if not metadatautils: from metadatautils import MetadataUtils self.metadatautils = MetadataUtils else: self.metadatautils = metadatautils self.cache = self.metadatautils.cache self.lastfm = LastFM() self.mbrainz = MusicBrainz() self.audiodb = TheAudioDb() def get_music_artwork(self, artist, album, track, disc, ignore_cache=False, flush_cache=False, manual=False): ''' get music metadata by providing artist and/or album/track returns combined result of artist and album metadata ''' if artist == track or album == track: track = "" artists = self.get_all_artists(artist, track) album = self.get_clean_title(album) track = self.get_clean_title(track) # retrieve artist and album details artist_details = self.get_artists_metadata(artists, album, track, ignore_cache=ignore_cache, flush_cache=flush_cache, manual=manual) album_artist = artist_details.get("albumartist", artist) if album or track: album_details = self.get_album_metadata(album_artist, album, track, disc, ignore_cache=ignore_cache, flush_cache=flush_cache, manual=manual) else: album_details = {"art": {}} # combine artist details and album details details = extend_dict(album_details, artist_details) # combine artist plot and album plot as extended plot if artist_details.get("plot") and album_details.get("plot"): details["extendedplot"] = "%s -- %s" % (album_details["plot"], artist_details["plot"]) else: details["extendedplot"] = details.get("plot", "") # append track title to results if track: details["title"] = track # return the endresult return details def music_artwork_options(self, artist, album, track, disc): '''show options for music artwork''' options = [] options.append(self.metadatautils.addon.getLocalizedString( 32028)) # Refresh item (auto lookup) options.append( self.metadatautils.addon.getLocalizedString(32036)) # Choose art options.append(self.metadatautils.addon.getLocalizedString( 32034)) # Open addon settings header = self.metadatautils.addon.getLocalizedString(32015) dialog = xbmcgui.Dialog() ret = dialog.select(header, options) del dialog if ret == 0: # Refresh item (auto lookup) self.get_music_artwork(artist, album, track, disc, ignore_cache=True) elif ret == 1: # Choose art self.get_music_artwork(artist, album, track, disc, ignore_cache=True, manual=True) elif ret == 2: # Open addon settings xbmc.executebuiltin("Addon.OpenSettings(%s)" % ADDON_ID) def get_artists_metadata(self, artists, album, track, ignore_cache=False, flush_cache=False, manual=False): '''collect artist metadata for all artists''' artist_details = {"art": {}} # for multi artist songs/albums we grab details from all artists if len(artists) == 1: # single artist artist_details = self.get_artist_metadata( artists[0], album, track, ignore_cache=ignore_cache, flush_cache=flush_cache, manual=manual) artist_details["albumartist"] = artists[0] else: # multi-artist track # The first artist with details is considered the main artist # all others are assumed as featuring artists artist_details = {"art": {}} feat_artist_details = {"art": {}} for artist in artists: if not (artist_details.get("plot") or artist_details.get("art")): # get main artist details artist_details["albumartist"] = artist artist_details = self.get_artist_metadata( artist, album, track, ignore_cache=ignore_cache, manual=manual) else: # assume featuring artist feat_artist_details = extend_dict( feat_artist_details, self.get_artist_metadata(artist, album, track, ignore_cache=ignore_cache, manual=manual)) # combined images to use as multiimage (for all artists) # append featuring artist details for arttype in ["banners", "fanarts", "clearlogos", "thumbs"]: art = artist_details["art"].get(arttype, []) art += feat_artist_details["art"].get(arttype, []) if art: # use the extrafanart plugin entry to display multi images artist_details["art"][arttype] = "plugin://script.skin.helper.service/"\ "?action=extrafanart&fanarts=%s" % quote_plus(repr(art)) # also set extrafanart path if arttype == "fanarts": artist_details["art"]["extrafanart"] = artist_details[ "art"][arttype] # return the result return artist_details # pylint: disable-msg=too-many-local-variables def get_artist_metadata(self, artist, album, track, ignore_cache=False, flush_cache=False, manual=False): '''collect artist metadata for given artist''' details = {"art": {}} cache_str = "music_artwork.artist.%s" % artist.lower() # retrieve details from cache cache = self.metadatautils.cache.get(cache_str) if not cache and flush_cache: # nothing to do - just return empty results return details elif cache and flush_cache: # only update kodi metadata for updated counts etc details = extend_dict(self.get_artist_kodi_metadata(artist), cache) elif cache and not ignore_cache: # we have a valid cache - return that details = cache elif cache and manual: # user wants to manually override the artwork in the cache details = self.manual_set_music_artwork(cache, "artist") else: # nothing in cache - start metadata retrieval log_msg( "get_artist_metadata --> artist: %s - album: %s - track: %s" % (artist, album, track)) details["cachestr"] = cache_str local_path = "" local_path_custom = "" # get metadata from kodi db details = extend_dict(details, self.get_artist_kodi_metadata(artist)) # get artwork from songlevel path if details.get("diskpath") and self.metadatautils.addon.getSetting( "music_art_musicfolders") == "true": details["art"] = extend_dict( details["art"], self.lookup_artistart_in_folder(details["diskpath"])) local_path = details["diskpath"] # get artwork from custom folder if self.metadatautils.addon.getSetting( "music_art_custom") == "true": custom_path = self.metadatautils.addon.getSetting( "music_art_custom_path").decode("utf-8") if custom_path: diskpath = self.get_customfolder_path(custom_path, artist) log_msg("custom path on disk for artist: %s --> %s" % (artist, diskpath)) if diskpath: details["art"] = extend_dict( details["art"], self.lookup_artistart_in_folder(diskpath)) local_path_custom = diskpath details["customartpath"] = diskpath # lookup online metadata if self.metadatautils.addon.getSetting( "music_art_scraper") == "true": if not album and not track: album = details.get("ref_album") track = details.get("ref_track") # prefer the musicbrainzid that is already in the kodi database - only perform lookup if missing mb_artistid = details.get( "musicbrainzartistid", self.get_mb_artist_id(artist, album, track)) details["musicbrainzartistid"] = mb_artistid if mb_artistid: # get artwork from fanarttv if self.metadatautils.addon.getSetting( "music_art_scraper_fatv") == "true": details["art"] = extend_dict( details["art"], self.metadatautils.fanarttv.artist(mb_artistid)) # get metadata from theaudiodb if self.metadatautils.addon.getSetting( "music_art_scraper_adb") == "true": details = extend_dict( details, self.audiodb.artist_info(mb_artistid)) # get metadata from lastfm if self.metadatautils.addon.getSetting( "music_art_scraper_lfm") == "true": details = extend_dict( details, self.lastfm.artist_info(mb_artistid)) # download artwork to music folder if local_path and self.metadatautils.addon.getSetting( "music_art_download") == "true": details["art"] = download_artwork( local_path, details["art"]) # download artwork to custom folder if local_path_custom and self.metadatautils.addon.getSetting( "music_art_download_custom") == "true": details["art"] = download_artwork( local_path_custom, details["art"]) # fix extrafanart if details["art"].get("fanarts"): for count, item in enumerate( details["art"]["fanarts"]): details["art"]["fanart.%s" % count] = item if not details["art"].get("extrafanart") and len( details["art"]["fanarts"]) > 1: details["art"]["extrafanart"] = "plugin://script.skin.helper.service/"\ "?action=extrafanart&fanarts=%s" % quote_plus(repr(details["art"]["fanarts"])) # multi-image path for all images for each arttype for arttype in ["banners", "clearlogos", "thumbs"]: art = details["art"].get(arttype, []) if len(art) > 1: # use the extrafanart plugin entry to display multi images details["art"][arttype] = "plugin://script.skin.helper.service/"\ "?action=extrafanart&fanarts=%s" % quote_plus(repr(art)) # set default details if not details.get("artist"): details["artist"] = artist if details["art"].get("thumb"): details["art"]["artistthumb"] = details["art"]["thumb"] # always store results in cache and return results self.metadatautils.cache.set(cache_str, details) return details def get_album_metadata(self, artist, album, track, disc, ignore_cache=False, flush_cache=False, manual=False): '''collect all album metadata''' cache_str = "music_artwork.album.%s.%s.%s" % ( artist.lower(), album.lower(), disc.lower()) if not album: cache_str = "music_artwork.album.%s.%s" % (artist.lower(), track.lower()) details = {"art": {}} details["cachestr"] = cache_str # retrieve details from cache cache = self.metadatautils.cache.get(cache_str) if not cache and flush_cache: # nothing to do - just return empty results return details elif cache and flush_cache: # only update kodi metadata for updated counts etc details = extend_dict( self.get_album_kodi_metadata(artist, album, track, disc), cache) elif cache and not ignore_cache: # we have a valid cache - return that details = cache elif cache and manual: # user wants to manually override the artwork in the cache details = self.manual_set_music_artwork(cache, "album") else: # nothing in cache - start metadata retrieval local_path = "" local_path_custom = "" # get metadata from kodi db details = extend_dict( details, self.get_album_kodi_metadata(artist, album, track, disc)) # get artwork from songlevel path if details.get("diskpath") and self.metadatautils.addon.getSetting( "music_art_musicfolders") == "true": details["art"] = extend_dict( details["art"], self.lookup_albumart_in_folder(details["diskpath"])) local_path = details["diskpath"] # get artwork from custom folder if self.metadatautils.addon.getSetting( "music_art_custom") == "true": custom_path = self.metadatautils.addon.getSetting( "music_art_custom_path").decode("utf-8") if custom_path: diskpath = self.get_custom_album_path( custom_path, artist, album, disc) if diskpath: details["art"] = extend_dict( details["art"], self.lookup_albumart_in_folder(diskpath)) local_path_custom = diskpath details["customartpath"] = diskpath # lookup online metadata if self.metadatautils.addon.getSetting( "music_art_scraper") == "true": # prefer the musicbrainzid that is already in the kodi database - only perform lookup if missing mb_albumid = details.get("musicbrainzalbumid") if not mb_albumid: mb_albumid = self.get_mb_album_id(artist, album, track) if mb_albumid: # get artwork from fanarttv if self.metadatautils.addon.getSetting( "music_art_scraper_fatv") == "true": details["art"] = extend_dict( details["art"], self.metadatautils.fanarttv.album(mb_albumid)) # get metadata from theaudiodb if self.metadatautils.addon.getSetting( "music_art_scraper_adb") == "true": details = extend_dict( details, self.audiodb.album_info(mb_albumid)) # get metadata from lastfm if self.metadatautils.addon.getSetting( "music_art_scraper_lfm") == "true": details = extend_dict( details, self.lastfm.album_info(mb_albumid)) # metadata from musicbrainz if not details.get("year") or not details.get("genre"): details = extend_dict( details, self.mbrainz.get_albuminfo(mb_albumid)) # musicbrainz thumb as last resort if not details["art"].get("thumb"): details["art"]["thumb"] = self.mbrainz.get_albumthumb( mb_albumid) # download artwork to music folder if local_path and self.metadatautils.addon.getSetting( "music_art_download") == "true": details["art"] = download_artwork( local_path, details["art"]) # download artwork to custom folder if local_path_custom and self.metadatautils.addon.getSetting( "music_art_download_custom") == "true": details["art"] = download_artwork( local_path_custom, details["art"]) # set default details if not details.get("album") and details.get("title"): details["album"] = details["title"] if details["art"].get("thumb"): details["art"]["albumthumb"] = details["art"]["thumb"] # store results in cache and return results self.metadatautils.cache.set(cache_str, details) return details # pylint: enable-msg=too-many-local-variables def get_artist_kodi_metadata(self, artist): '''get artist details from the kodi database''' details = {} filters = [{"operator": "is", "field": "artist", "value": artist}] result = self.metadatautils.kodidb.artists(filters=filters, limits=(0, 1)) if result: details = result[0] details["title"] = details["artist"] details["plot"] = strip_newlines(details["description"]) if details["musicbrainzartistid"] and isinstance( details["musicbrainzartistid"], list): details["musicbrainzartistid"] = details[ "musicbrainzartistid"][0] filters = [{"artistid": details["artistid"]}] artist_albums = self.metadatautils.kodidb.albums(filters=filters) details["albums"] = [] details["albumsartist"] = [] details["albumscompilations"] = [] details["tracks"] = [] bullet = "•".decode("utf-8") details["albums.formatted"] = u"" details["tracks.formatted"] = u"" details["tracks.formatted2"] = u"" details["albumsartist.formatted"] = u"" details["albumscompilations.formatted"] = u"" # enumerate albums for this artist for artist_album in artist_albums: details["albums"].append(artist_album["label"]) details["albums.formatted"] += u"%s %s [CR]" % ( bullet, artist_album["label"]) if artist in artist_album["displayartist"]: details["albumsartist"].append(artist_album["label"]) details["albumsartist.formatted"] += u"%s %s [CR]" % ( bullet, artist_album["label"]) else: details["albumscompilations"].append(artist_album["label"]) details[ "albumscompilations.formatted"] += u"%s %s [CR]" % ( bullet, artist_album["label"]) # enumerate songs for this album filters = [{"albumid": artist_album["albumid"]}] album_tracks = self.metadatautils.kodidb.songs(filters=filters) if album_tracks: # retrieve path on disk by selecting one song for this artist if not details.get("ref_track") and not len( artist_album["artistid"]) > 1: song_path = album_tracks[0]["file"] details["diskpath"] = self.get_artistpath_by_songpath( song_path, artist) details["ref_album"] = artist_album["title"] details["ref_track"] = album_tracks[0]["title"] for album_track in album_tracks: details["tracks"].append(album_track["title"]) tr_title = album_track["title"] if album_track["track"]: tr_title = "%s. %s" % (album_track["track"], album_track["title"]) details["tracks.formatted"] += u"%s %s [CR]" % ( bullet, tr_title) duration = album_track["duration"] total_seconds = int(duration) minutes = total_seconds / 60 seconds = total_seconds - (minutes * 60) duration = "%s:%s" % (minutes, str(seconds).zfill(2)) details["tracks.formatted2"] += u"%s %s (%s)[CR]" % ( bullet, tr_title, duration) details["albumcount"] = len(details["albums"]) details["albumsartistcount"] = len(details["albumsartist"]) details["albumscompilationscount"] = len( details["albumscompilations"]) # do not retrieve artwork from item as there's no way to write it back # and it will already be retrieved if user enables to get the artwork from the song path return details def get_album_kodi_metadata(self, artist, album, track, disc): '''get album details from the kodi database''' details = {} filters = [{"operator": "is", "field": "album", "value": album}] filters.append({"operator": "is", "field": "artist", "value": artist}) if artist and track and not album: # get album by track result = self.metadatautils.kodidb.songs(filters=filters) for item in result: album = item["album"] break if artist and album: result = self.metadatautils.kodidb.albums(filters=filters) if result: details = result[0] details["plot"] = strip_newlines(details["description"]) filters = [{"albumid": details["albumid"]}] album_tracks = self.metadatautils.kodidb.songs(filters=filters) details["tracks"] = [] bullet = "•".decode("utf-8") details["tracks.formatted"] = u"" details["tracks.formatted2"] = "" details["runtime"] = 0 for item in album_tracks: details["tracks"].append(item["title"]) details["tracks.formatted"] += u"%s %s [CR]" % ( bullet, item["title"]) duration = item["duration"] total_seconds = int(duration) minutes = total_seconds / 60 seconds = total_seconds - (minutes * 60) duration = "%s:%s" % (minutes, str(seconds).zfill(2)) details["runtime"] += item["duration"] details["tracks.formatted2"] += u"%s %s (%s)[CR]" % ( bullet, item["title"], duration) if not details.get("diskpath"): if not disc or item["disc"] == int(disc): details[ "diskpath"] = self.get_albumpath_by_songpath( item["file"]) details["art"] = {} details["songcount"] = len(album_tracks) # get album total duration pretty printed as mm:ss total_seconds = int(details["runtime"]) minutes = total_seconds / 60 seconds = total_seconds - (minutes * 60) details["duration"] = "%s:%s" % (minutes, str(seconds).zfill(2)) # do not retrieve artwork from item as there's no way to write it back # and it will already be retrieved if user enables to get the artwork from the song path return details def get_mb_artist_id(self, artist, album, track): '''lookup musicbrainz artist id with query of artist and album/track''' artistid = self.mbrainz.get_artist_id(artist, album, track) if not artistid and self.metadatautils.addon.getSetting( "music_art_scraper_lfm") == "true": artistid = self.lastfm.get_artist_id(artist, album, track) if not artistid and self.metadatautils.addon.getSetting( "music_art_scraper_adb") == "true": artistid = self.audiodb.get_artist_id(artist, album, track) return artistid def get_mb_album_id(self, artist, album, track): '''lookup musicbrainz album id with query of artist and album/track''' albumid = self.mbrainz.get_album_id(artist, album, track) if not albumid and self.metadatautils.addon.getSetting( "music_art_scraper_lfm") == "true": albumid = self.lastfm.get_album_id(artist, album, track) if not albumid and self.metadatautils.addon.getSetting( "music_art_scraper_adb") == "true": albumid = self.audiodb.get_album_id(artist, album, track) return albumid def manual_set_music_artwork(self, details, mediatype): '''manual override artwork options''' from utils import manual_set_artwork if mediatype == "artist" and "artist" in details: header = "%s: %s" % (xbmc.getLocalizedString(13511), details["artist"]) else: header = "%s: %s" % (xbmc.getLocalizedString(13511), xbmc.getLocalizedString(558)) changemade, artwork = manual_set_artwork(details["art"], mediatype, header) # save results if any changes made if changemade: details["art"] = artwork refresh_needed = False download_art = self.metadatautils.addon.getSetting( "music_art_download") == "true" download_art_custom = self.metadatautils.addon.getSetting( "music_art_download_custom") == "true" # download artwork to music folder if needed if details.get("diskpath") and download_art: details["art"] = download_artwork(details["diskpath"], details["art"]) refresh_needed = True # download artwork to custom folder if needed if details.get("customartpath") and download_art_custom: details["art"] = download_artwork(details["customartpath"], details["art"]) refresh_needed = True # reload skin to make sure new artwork is visible if refresh_needed: xbmc.sleep(500) xbmc.executebuiltin("ReloadSkin()") # return endresult return details @staticmethod def get_artistpath_by_songpath(songpath, artist): '''get the artist path on disk by listing the song's path''' result = "" if "\\" in songpath: delim = "\\" else: delim = "/" # just move up the directory tree (max 3 levels) untill we find the directory for trypath in [ songpath.rsplit(delim, 2)[0] + delim, songpath.rsplit(delim, 3)[0] + delim, songpath.rsplit(delim, 1)[0] + delim ]: if trypath.split(delim)[-2].lower() == artist.lower(): result = trypath break return result @staticmethod def get_albumpath_by_songpath(songpath): '''get the album path on disk by listing the song's path''' if "\\" in songpath: delim = "\\" else: delim = "/" return songpath.rsplit(delim, 1)[0] + delim @staticmethod def lookup_artistart_in_folder(folderpath): '''lookup artwork in given folder''' artwork = {} files = xbmcvfs.listdir(folderpath)[1] for item in files: item = item.decode("utf-8") if item in [ "banner.jpg", "clearart.png", "poster.png", "fanart.jpg", "landscape.jpg" ]: key = item.split(".")[0] artwork[key] = folderpath + item elif item == "logo.png": artwork["clearlogo"] = folderpath + item elif item == "folder.jpg": artwork["thumb"] = folderpath + item # extrafanarts efa_path = folderpath + "extrafanart/" if xbmcvfs.exists(efa_path): files = xbmcvfs.listdir(efa_path)[1] artwork["fanarts"] = [] if files: artwork["extrafanart"] = efa_path for item in files: item = efa_path + item.decode("utf-8") artwork["fanarts"].append(item) return artwork @staticmethod def lookup_albumart_in_folder(folderpath): '''lookup artwork in given folder''' artwork = {} files = xbmcvfs.listdir(folderpath)[1] for item in files: item = item.decode("utf-8") if item in ["cdart.png", "disc.png"]: artwork["discart"] = folderpath + item elif item == "folder.jpg": artwork["thumb"] = folderpath + item return artwork def get_custom_album_path(self, custom_path, artist, album, disc): '''try to locate the custom path for the album''' artist_path = self.get_customfolder_path(custom_path, artist) album_path = "" if artist_path: album_path = self.get_customfolder_path(artist_path, album) if album_path and disc: if "\\" in album_path: delim = "\\" else: delim = "/" dirs = xbmcvfs.listdir(album_path)[0] for directory in dirs: directory = directory.decode("utf-8") if disc in directory: return os.path.join(album_path, directory) + delim return album_path def get_customfolder_path(self, customfolder, foldername, sublevel=False): '''search recursively (max 2 levels) for a specific folder''' cachestr = "customfolder_path.%s.%s" % (customfolder, foldername) folder_path = self.cache.get(cachestr) if not folder_path: if "\\" in customfolder: delim = "\\" else: delim = "/" dirs = xbmcvfs.listdir(customfolder)[0] for strictness in [1, 0.95, 0.9, 0.8]: for directory in dirs: directory = directory.decode("utf-8") curpath = os.path.join(customfolder, directory) + delim match = SM(None, foldername.lower(), directory.lower()).ratio() if match >= strictness: folder_path = curpath elif not sublevel: # check if our requested path is in a sublevel of the current path # restrict the number of sublevels to just one for now for performance reasons folder_path = self.get_customfolder_path( curpath, foldername, True) if folder_path: break if folder_path: break if not sublevel: self.cache.set(cachestr, folder_path) return folder_path @staticmethod def get_clean_title(title): '''strip all unwanted characters from track name''' title = title.split("/")[0] title = title.split("(")[0] title = title.split("[")[0] title = title.split("ft.")[0] title = title.split("Ft.")[0] title = title.split("Feat.")[0] title = title.split("Featuring")[0] title = title.split("featuring")[0] return title.strip() @staticmethod def get_all_artists(artist, track): '''extract multiple artists from both artist and track string''' artists = [] feat_artists = [] # fix for band names which actually contain the kodi splitter (slash) in their name... specials = ["AC/DC"] # to be completed with more artists for special in specials: if special in artist: artist = artist.replace(special, special.replace("/", "")) for splitter in [ "ft.", "feat.", "featuring", "Ft.", "Feat.", "Featuring" ]: # replace splitter by kodi default splitter for easier split all later artist = artist.replace(splitter, u"/") # extract any featuring artists from trackname if splitter in track: track_parts = track.split(splitter) if len(track_parts) > 1: feat_artist = track_parts[1].replace(")", "").replace( "(", "").strip() feat_artists.append(feat_artist) # break all artists string into list all_artists = artist.split("/") + feat_artists for item in all_artists: item = item.strip() if item not in artists: artists.append(item) # & can be a both a splitter or part of artist name for item2 in item.split("&"): item2 = item2.strip() if item2 not in artists: artists.append(item2) return artists
def setUp(self): self.fm = LastFM() self.query = 'winter'
def writeRawData(data, page): track_file = 'db/tracks-%05d.db' % page with open(track_file, 'w') as db: pickle.dump(data, db) db.close() registerLastPage(page) def itertracks(tracks): return (t for t in tracks.findall('recenttracks/track') if t.get('nowplaying') is None) if __name__ == '__main__': service = LastFM('7cc9edbf1289e55d01f6d0b6a6fd159b', 'lsdr') starting_page = startingPage(service) for page in reversed(range(starting_page)): print 'processing page %s now...' % str(page) tracks = service.fetch('user.getrecenttracks', limit='200', page=str(page)) data = [extractTrackData(t) for t in itertracks(tracks)] # print data writeRawData(data, page) ''' # Tratando o UTS timestamp __timestamp_tuple = time.gmtime(float(UTS)) __timestamp = time.time.asctime(__timestamp_tuple)
class MusicPlayer(object): """the music playing class.""" def __init__(self): mixer.init() self._paused = False self.currentTrack = None self.last = LastFM() self.offset = 0 self.playQueue = Queue.Queue(-1) # queue of 'infinite' size self.previous = [] #using a list as a stack to hold previous plays @property def paused(self): """Boolean, for determining if the music is paused""" return self._paused @paused.setter def paused(self, value): self._paused = value @property def scrobblingEnabled(self): """Boolean, for determining if scrobbling is Enabled""" return self._scrobblingEnabled @scrobblingEnabled.setter def scrobblingEnabled(self, value): self._scrobblingEnabled = value def update(self): #if the playback is over half way (last.fm regulation) then scrobble it if self.currentTrack != None and mixer.music.get_pos() / 1000 >= self.currentTrack.length/2: if not self.currentTrack.scrobbled: self.last.scrobble(self.currentTrack.artist, self.currentTrack.title, self.currentTrack.time) self.currentTrack.scrobbled = True """Checks if the playing track is over and if so, changes it. returns changed if the track has changed""" if self.currentTrack != None and (mixer.music.get_pos() / 1000 ) >= self.currentTrack.length: self.setNext() return 'changed' def setNext(self, event=None): if not self.playQueue.empty(): if self.currentTrack != None: self.previous.append(self.currentTrack.path) trackname = self.playQueue.get() self.currentTrack = Track(trackname) mixer.music.load(trackname) self.offset = 0 self.play() def setPrevious(self, event=None): if len(self.previous) > 0: trackname = self.previous.pop() self.currentTrack = Track(trackname) mixer.music.load(trackname) self.play() def play(self): try: if self.currentTrack != None: if not self.paused: mixer.music.play() else: mixer.music.unpause() self._paused = False self.last.nowPlaying(self.currentTrack.artist, self.currentTrack.title) else: raise Exception("No track loaded") except pygame.error as error: raise error def pause(self): if mixer.music.get_busy() and not self.paused: mixer.music.pause() self._paused = True def stop(self): mixer.music.stop() def seek(self, position): if self.currentTrack != None: self.stop() self.offset = position pygame.mixer.music.play(0, position) def setVolume(self, vol): mixer.music.set_volume(vol) def load(self, toLoad): if not self.playQueue.empty(): self.playQueue = Queue.Queue(-1)#empty the queue if isinstance(toLoad, basestring): #checking if a string or a list toLoad = toLoad.encode('utf-8') print toLoad if os.path.isdir(toLoad): # we've been given a directory os.chdir(toLoad) for track in glob.glob('*.mp3'): print track self.playQueue.put(track) elif os.path.isfile(toLoad): #a file from the dirctrl self.playQueue.put(toLoad) else: # a list from the file -> open dialogue for track in toLoad: track = track.encode('utf-8') self.playQueue.put(track) self.setNext() def getPos(self): return mixer.music.get_pos() + self.offset def quit(self): pygame.quit()