PageRenderTime 62ms CodeModel.GetById 16ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 1ms

/src/pyechonest/pyechonest/playlist.py

http://echo-nest-remix.googlecode.com/
Python | 439 lines | 414 code | 5 blank | 20 comment | 1 complexity | 707acdbd49b1d42e1be4162737f77b9f MD5 | raw file
  1#!/usr/bin/env python
  2# encoding: utf-8
  3
  4"""
  5Copyright (c) 2010 The Echo Nest. All rights reserved.
  6Created by Tyler Williams on 2010-04-25.
  7
  8The Playlist module loosely covers http://developer.echonest.com/docs/v4/playlist.html
  9Refer to the official api documentation if you are unsure about something.
 10"""
 11
 12import util
 13from proxies import PlaylistProxy
 14from song import Song
 15import catalog
 16
 17class Playlist(PlaylistProxy):
 18    """
 19    A Dynamic Playlist object
 20    
 21    Attributes:
 22        session_id (str): Playlist Session ID
 23
 24        song (song object): The current song
 25
 26        info (dictionary): Information about this playlist
 27    
 28    Example:
 29        >>> p = Playlist(type='artist-radio', artist=['ida maria', 'florence + the machine'])
 30        >>> p
 31        <Dynamic Playlist - 9c210205d4784144b4fa90770fa55d0b>
 32        >>> p.song
 33        <song - Later On>
 34        >>> p.get_next_song()
 35        <song - Overall>
 36        >>> 
 37
 38    """
 39    
 40    def __init__(self, session_id=None, type='artist', artist_pick='song_hotttnesss-desc', variety=.5, artist_id=None, artist=None, \
 41                        song_id=None, description=None, style=None, mood=None, \
 42                        max_tempo=None, min_tempo=None, max_duration=None, \
 43                        min_duration=None, max_loudness=None, min_loudness=None, max_danceability=None, min_danceability=None, \
 44                        max_energy=None, min_energy=None, artist_max_familiarity=None, artist_min_familiarity=None, \
 45                        artist_max_hotttnesss=None, artist_min_hotttnesss=None, song_max_hotttnesss=None, song_min_hotttnesss=None, \
 46                        min_longitude=None, max_longitude=None, min_latitude=None, max_latitude=None, \
 47                        mode=None, key=None, buckets=[], sort=None, limit=False, dmca=False, chain_xspf=False, \
 48                        seed_catalog=None, steer=None, source_catalog=None, steer_description=None, test_new_things=None, rank_type=None,
 49                        artist_start_year_after=None, artist_start_year_before=None, artist_end_year_after=None, artist_end_year_before=None):
 50        """
 51        Args:
 52
 53        Kwargs:
 54            type (str): a string representing the playlist type ('artist', 'artist-radio', ...)
 55
 56            artist_pick (str): How songs should be chosen for each artist
 57
 58            variety (float): A number between 0 and 1 specifying the variety of the playlist
 59
 60            artist_id (str): the artist_id
 61
 62            artist (str): the name of an artist
 63
 64            song_id (str): the song_id
 65
 66            description (str): A string describing the artist and song
 67            
 68            style (str): A string describing the style/genre of the artist and song
 69
 70            mood (str): A string describing the mood of the artist and song
 71            
 72            results (int): An integer number of results to return
 73
 74            max_tempo (float): The max tempo of song results
 75
 76            min_tempo (float): The min tempo of song results
 77
 78            max_duration (float): The max duration of song results
 79
 80            min_duration (float): The min duration of song results
 81
 82            max_loudness (float): The max loudness of song results
 83
 84            min_loudness (float): The min loudness of song results
 85
 86            artist_max_familiarity (float): A float specifying the max familiarity of artists to search for
 87
 88            artist_min_familiarity (float): A float specifying the min familiarity of artists to search for
 89
 90            artist_max_hotttnesss (float): A float specifying the max hotttnesss of artists to search for
 91
 92            artist_min_hotttnesss (float): A float specifying the max hotttnesss of artists to search for
 93
 94            song_max_hotttnesss (float): A float specifying the max hotttnesss of songs to search for
 95
 96            song_min_hotttnesss (float): A float specifying the max hotttnesss of songs to search for
 97
 98            max_energy (float): The max energy of song results
 99
100            min_energy (float): The min energy of song results
101
102            max_dancibility (float): The max dancibility of song results
103
104            min_dancibility (float): The min dancibility of song results
105
106            mode (int): 0 or 1 (minor or major)
107
108            key (int): 0-11 (c, c-sharp, d, e-flat, e, f, f-sharp, g, a-flat, a, b-flat, b)
109
110            max_latitude (float): A float specifying the max latitude of artists to search for
111
112            min_latitude (float): A float specifying the min latitude of artists to search for
113
114            max_longitude (float): A float specifying the max longitude of artists to search for
115
116            min_longitude (float): A float specifying the min longitude of artists to search for                        
117
118            sort (str): A string indicating an attribute and order for sorting the results
119
120            buckets (list): A list of strings specifying which buckets to retrieve
121
122            limit (bool): A boolean indicating whether or not to limit the results to one of the id spaces specified in buckets
123
124            seed_catalog (str or Catalog): A Catalog object or catalog id to use as a seed
125            
126            source_catalog (str or Catalog): A Catalog object or catalog id
127            
128            steer (str): A steering value to determine the target song attributes
129            
130            steer_description (str): A steering value to determine the target song description term attributes
131            
132            rank_type (str): A string denoting the desired ranking for description searches, either 'relevance' or 'familiarity'
133            
134            artist_start_year_before (int): Returned songs's artists will have started recording music before this year.
135            
136            artist_start_year_after (int): Returned songs's artists will have started recording music after this year.
137            
138            artist_end_year_before (int): Returned songs's artists will have stopped recording music before this year.
139            
140            artist_end_year_after (int): Returned songs's artists will have stopped recording music after this year.
141            
142        Returns:
143            A dynamic playlist object
144        
145            
146        """
147        limit = str(limit).lower()
148        dmca = str(dmca).lower()
149        chain_xspf = str(chain_xspf).lower()
150        
151        if isinstance(seed_catalog, catalog.Catalog):
152            seed_catalog = seed_catalog.id
153
154        if isinstance(source_catalog, catalog.Catalog):
155            source_catalog = source_catalog.id
156
157        kwargs = locals()
158        kwargs['bucket'] = kwargs['buckets']
159        del kwargs['buckets']
160        del kwargs['self']
161        del kwargs['session_id']
162        
163        super(Playlist, self).__init__(session_id, **kwargs)
164    
165    def __repr__(self):
166        return "<Dynamic Playlist - %s>" % self.session_id.encode('utf-8')
167    
168    # def __str__(self):
169    #     return self.name.encode('utf-8')
170    
171    def get_next_song(self, **kwargs):
172        """Get the next song in the playlist
173        
174        Args:
175        
176        Kwargs:
177        
178        Returns:
179            A song object
180        
181        Example:
182        
183        >>> p = playlist.Playlist(type='artist-radio', artist=['ida maria', 'florence + the machine'])
184        >>> p.get_next_song()
185        <song - She Said>
186        >>>
187        
188        """
189        response = self.get_attribute('dynamic', session_id=self.session_id, **kwargs)
190        self.cache['songs'] = response['songs']
191        # we need this to fix up all the dict keys to be strings, not unicode objects
192        fix = lambda x : dict((str(k), v) for (k,v) in x.iteritems())
193        if len(self.cache['songs']):
194            return Song(**fix(self.cache['songs'][0]))
195        else:
196            return None
197    
198    def get_current_song(self):
199        """Get the current song in the playlist
200        
201        Args:
202        
203        Kwargs:
204        
205        Returns:
206            A song object
207        
208        Example:
209        
210        >>> p = playlist.Playlist(type='artist-radio', artist=['ida maria', 'florence + the machine'])
211        >>> p.song
212        <song - Later On>
213        >>> p.get_current_song()
214        <song - Later On>
215        >>> 
216
217        """
218        # we need this to fix up all the dict keys to be strings, not unicode objects
219        if not 'songs' in self.cache:
220            self.get_next_song()
221        if len(self.cache['songs']):
222            return Song(**util.fix(self.cache['songs'][0]))
223        else:
224            return None
225
226    song = property(get_current_song)
227    
228    def session_info(self):
229        """Get information about the playlist
230        
231        Args:
232        
233        Kwargs:
234        
235        Returns:
236            A dict with diagnostic information about the currently running playlist
237        
238        Example:
239        
240        >>> p = playlist.Playlist(type='artist-radio', artist=['ida maria', 'florence + the machine'])
241        >>> p.info
242        {
243            u 'terms': [{
244                u 'frequency': 1.0,
245                u 'name': u 'rock'
246            },
247            {
248                u 'frequency': 0.99646542152360207,
249                u 'name': u 'pop'
250            },
251            {
252                u 'frequency': 0.90801905502131963,
253                u 'name': u 'indie'
254            },
255            {
256                u 'frequency': 0.90586455490260576,
257                u 'name': u 'indie rock'
258            },
259            {
260                u 'frequency': 0.8968907243373172,
261                u 'name': u 'alternative'
262            },
263            [...]
264            {
265                u 'frequency': 0.052197425644931635,
266                u 'name': u 'easy listening'
267            }],
268            u 'description': [],
269            u 'seed_songs': [],
270            u 'banned_artists': [],
271            u 'rules': [{
272                u 'rule': u "Don't put two copies of the same song in a playlist."
273            },
274            {
275                u 'rule': u 'Give preference to artists that are not already in the playlist'
276            }],
277            u 'session_id': u '9c1893e6ace04c8f9ce745f38b35ff95',
278            u 'seeds': [u 'ARI4XHX1187B9A1216', u 'ARNCHOP121318C56B8'],
279            u 'skipped_songs': [],
280            u 'banned_songs': [],
281            u 'playlist_type': u 'artist-radio',
282            u 'seed_catalogs': [],
283            u 'rated_songs': [],
284            u 'history': [{
285                u 'artist_id': u 'ARN6QMG1187FB56C8D',
286                u 'artist_name': u 'Laura Marling',
287                u 'id': u 'SOMSHNP12AB018513F',
288                u 'served_time': 1291412277.204201,
289                u 'title': u 'Hope In The Air'
290            }]
291        }
292        
293        >>> p.session_info()
294        (same result as above)
295        >>> 
296
297        """
298        return self.get_attribute("session_info", session_id=self.session_id)
299    
300    info = property(session_info)
301
302
303def static(type='artist', artist_pick='song_hotttnesss-desc', variety=.5, artist_id=None, artist=None, \
304                    song_id=None, description=None, style=None, mood=None, \
305                    results=15, max_tempo=None, min_tempo=None, max_duration=None, \
306                    min_duration=None, max_loudness=None, min_loudness=None, max_danceability=None, min_danceability=None, \
307                    max_energy=None, min_energy=None, artist_max_familiarity=None, artist_min_familiarity=None, \
308                    artist_max_hotttnesss=None, artist_min_hotttnesss=None, song_max_hotttnesss=None, song_min_hotttnesss=None, \
309                    min_longitude=None, max_longitude=None, min_latitude=None, max_latitude=None, \
310                    mode=None, key=None, buckets=[], sort=None, limit=False, seed_catalog=None, source_catalog=None, rank_type=None, test_new_things=None,
311                    artist_start_year_after=None, artist_start_year_before=None, artist_end_year_after=None, artist_end_year_before=None):
312    """Get a static playlist
313    
314    Args:
315    
316    Kwargs:
317        type (str): a string representing the playlist type ('artist', 'artist-radio', ...)
318        
319        artist_pick (str): How songs should be chosen for each artist
320        
321        variety (float): A number between 0 and 1 specifying the variety of the playlist
322        
323        artist_id (str): the artist_id
324        
325        artist (str): the name of an artist
326        
327        song_id (str): the song_id
328    
329        description (str): A string describing the artist and song
330        
331        style (str): A string describing the style/genre of the artist and song
332    
333        mood (str): A string describing the mood of the artist and song
334        
335        results (int): An integer number of results to return
336    
337        max_tempo (float): The max tempo of song results
338    
339        min_tempo (float): The min tempo of song results
340    
341        max_duration (float): The max duration of song results
342    
343        min_duration (float): The min duration of song results
344    
345        max_loudness (float): The max loudness of song results
346    
347        min_loudness (float): The min loudness of song results
348    
349        artist_max_familiarity (float): A float specifying the max familiarity of artists to search for
350    
351        artist_min_familiarity (float): A float specifying the min familiarity of artists to search for
352    
353        artist_max_hotttnesss (float): A float specifying the max hotttnesss of artists to search for
354    
355        artist_min_hotttnesss (float): A float specifying the max hotttnesss of artists to search for
356    
357        song_max_hotttnesss (float): A float specifying the max hotttnesss of songs to search for
358    
359        song_min_hotttnesss (float): A float specifying the max hotttnesss of songs to search for
360    
361        max_energy (float): The max energy of song results
362    
363        min_energy (float): The min energy of song results
364    
365        max_dancibility (float): The max dancibility of song results
366    
367        min_dancibility (float): The min dancibility of song results
368    
369        mode (int): 0 or 1 (minor or major)
370    
371        key (int): 0-11 (c, c-sharp, d, e-flat, e, f, f-sharp, g, a-flat, a, b-flat, b)
372    
373        max_latitude (float): A float specifying the max latitude of artists to search for
374    
375        min_latitude (float): A float specifying the min latitude of artists to search for
376    
377        max_longitude (float): A float specifying the max longitude of artists to search for
378    
379        min_longitude (float): A float specifying the min longitude of artists to search for                        
380    
381        sort (str): A string indicating an attribute and order for sorting the results
382    
383        buckets (list): A list of strings specifying which buckets to retrieve
384    
385        limit (bool): A boolean indicating whether or not to limit the results to one of the id spaces specified in buckets
386        
387        seed_catalog (str or Catalog): An Artist Catalog object or Artist Catalog id to use as a seed
388        
389        source_catalog (str or Catalog): A Catalog object or catalog id
390
391        rank_type (str): A string denoting the desired ranking for description searches, either 'relevance' or 'familiarity'    
392        
393        artist_start_year_before (int): Returned songs's artists will have started recording music before this year.
394        
395        artist_start_year_after (int): Returned songs's artists will have started recording music after this year.
396        
397        artist_end_year_before (int): Returned songs's artists will have stopped recording music before this year.
398        
399        artist_end_year_after (int): Returned songs's artists will have stopped recording music after this year.
400
401    Returns:
402        A list of Song objects
403    
404    Example:
405    
406    >>> p = playlist.static(type='artist-radio', artist=['ida maria', 'florence + the machine'])
407    >>> p
408    [<song - Pickpocket>,
409     <song - Self-Taught Learner>,
410     <song - Maps>,
411     <song - Window Blues>,
412     <song - That's Not My Name>,
413     <song - My Lover Will Go>,
414     <song - Home Sweet Home>,
415     <song - Stella & God>,
416     <song - Don't You Want To Share The Guilt?>,
417     <song - Forget About It>,
418     <song - Dull Life>,
419     <song - This Trumpet In My Head>,
420     <song - Keep Your Head>,
421     <song - One More Time>,
422     <song - Knights in Mountain Fox Jackets>]
423    >>> 
424
425    """
426    limit = str(limit).lower()
427
428    if seed_catalog and isinstance(seed_catalog, catalog.Catalog):
429        seed_catalog = seed_catalog.id
430
431    if source_catalog and isinstance(source_catalog, catalog.Catalog):
432        source_catalog = source_catalog.id
433
434    kwargs = locals()
435    kwargs['bucket'] = kwargs['buckets']
436    del kwargs['buckets']
437    
438    result = util.callm("%s/%s" % ('playlist', 'static'), kwargs)
439    return [Song(**util.fix(s_dict)) for s_dict in result['response']['songs']]