/src/pyechonest/pyechonest/playlist.py

http://echo-nest-remix.googlecode.com/ · Python · 439 lines · 404 code · 10 blank · 25 comment · 0 complexity · 707acdbd49b1d42e1be4162737f77b9f MD5 · raw file

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