1 /**************************************************************************************** 2 * Copyright (c) 2010-2012 Leo Franchi <lfranchi@kde.org> * 3 * * 4 * This program is free software; you can redistribute it and/or modify it under * 5 * the terms of the GNU General Public License as published by the Free Software * 6 * Foundation; either version 2 of the License, or (at your option) any later * 7 * version. * 8 * * 9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 10 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 11 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 12 * * 13 * You should have received a copy of the GNU General Public License along with * 14 * this program. If not, see <http://www.gnu.org/licenses/>. * 15 ****************************************************************************************/ 16 17 18 #ifndef ECHONEST_PLAYLIST_H 19 #define ECHONEST_PLAYLIST_H 20 21 #include "echonest_export.h" 22 #include "Song.h" 23 24 #include <QSharedData> 25 #include <QDebug> 26 #include "Artist.h" 27 #include <QtCore/QString> 28 #include "Catalog.h" 29 30 class QNetworkReply; 31 class DynamicPlaylistData; 32 33 namespace Echonest{ 34 35 typedef struct { 36 QByteArray session_id; 37 Artists banned_artists; 38 Artists favorited_artists; 39 SongList banned_songs; 40 SongList favorited_songs; 41 QVariantMap options; 42 QVariantMap ratingsMap; 43 // TODO favorites_map 44 // TODO constraints 45 46 } SessionInfo; 47 48 /** 49 * This encapsulates an Echo Nest dynamic playlist. It contains a playlist ID and 50 * the current song, and can fetch the next song. 51 * 52 * See http://developer.echonest.com/docs/v4/playlist.html 53 * for more information 54 */ 55 class ECHONEST_EXPORT DynamicPlaylist 56 { 57 public: 58 /** 59 * The types of playlist that can be generated. Artist plays songs for the given artist, 60 * ArtistRadio takes into account similar artists, and ArtistDescription plays songs matching 61 * the given description. 62 */ 63 enum ArtistTypeEnum { 64 ArtistType, 65 ArtistRadioType, 66 ArtistDescriptionType, 67 CatalogType, 68 CatalogRadioType, 69 SongRadioType, 70 GenreRadioType 71 }; 72 73 /** 74 * Different ways to sort a generated playlist 75 */ 76 enum SortingType { 77 SortTempoAscending, 78 SortTempoDescending, 79 SortDurationAscending, 80 SortDurationDescending, 81 SortArtistFamiliarityAscending, 82 SortArtistFamiliarityDescending, 83 SortArtistHotttnessAscending, 84 SortArtistHotttnessDescending, 85 SortSongHotttnesssAscending, 86 SortSongHotttnesssDescending, 87 SortLatitudeAscending, 88 SortLatitudeDescending, 89 SortLongitudeAscending, 90 SortLongitudeDescending, 91 SortModeAscending, 92 SortModeDescending, 93 SortKeyAscending, 94 SortKeyDescending, 95 SortLoudnessAscending, 96 SortLoudnessDescending, 97 SortEnergyAscending, 98 SortEnergyDescending, 99 SortDanceabilityAscending, 100 SortDanceabilityDescending, 101 SortAcousticnessAscending, 102 SortAcousticnessDescending, 103 SortSpeechinessAscending, 104 SortSpeechinessDescending, 105 SortLivenessAscending, 106 SortLivenessDescending, 107 SortValenceAscending, 108 SortValenceDescending 109 }; 110 111 /** 112 * Different ways of picking artists in Artist radios. 113 */ 114 enum ArtistPick { 115 PickSongHotttnesssAscending, 116 PickTempoAscending, 117 PickDurationAscending, 118 PickLoudnessAscending, 119 PickModeAscending, 120 PickKeyAscending, 121 PickSongHotttnesssDescending, 122 PickTempoDescending, 123 PickDurationDescending, 124 PickLoudnessDescending, 125 PickModeDescending, 126 PickKeyDescending 127 }; 128 129 /** 130 * The various parameters that can be passed to the playlist building 131 * functions. 132 */ 133 enum PlaylistParam { 134 Type, /// The type of playlist to generate. Value is the DynamicPlaylist::ArtistTypeEnum enum 135 Format, /// Either xml (default) or xspf. If the result is xspf, the raw xspf playlist is returned, else the xml is parsed and exposed programmatically. If using XSPF, you must specify a catalog, the tracks bucket, and limit = true 136 Pick, /// How the artists are picked for each artist in ArtistType playlists. Value is Playlist::ArtistPick enum value. 137 Variety, /// 0 < variety < 1 The maximum variety of artists to be represented in the playlist. A higher number will allow for more variety in the artists. 138 ArtistId, /// ID(s) of seed artist(s) for the playlist 139 Artist, /// Artist names of seeds for playlist 140 ArtistSeedCatalog, /// ID of seed artist catalog for the playlist 141 SourceCatalog, /// ID of catalog (artist or song) for catalog type playlists 142 SongId, /// IDs of seed songs for the playlist 143 Description, /// Textual description for sort of songs that can be included in the playlist 144 Results, /// 0-100, how many sonsg to include in the playlist, default 15 145 MaxTempo, /// 0.0 < tempo < 500.0 (BPM) The maximum tempo for any included songs 146 MinTempo, /// 0.0 < tempo < 500.0 (BPM) the minimum tempo for any included songs 147 MaxDuration, /// 0.0 < duration < 3600.0 (seconds) the maximum duration of any song on the playlist 148 MinDuration, /// 0.0 < duration < 3600.0 (seconds) the minimum duration of any song on the playlist 149 MaxLoudness, /// -100.0 < loudness < 100.0 (dB) the maximum loudness of any song on the playlist 150 MinLoudness, /// -100.0 < loudness < 100.0 (dB) the minimum loudness of any song on the playlist 151 MinDanceability, /// 0 < danceability < 1 a measure of the minimum danceability of the song 152 MaxDanceability, /// 0 < danceability < 1 a measure of the maximum danceability of the song 153 MinEnergy, /// 0 < danceability < 1 a measure of the maximum energy of the song 154 MaxEnergy, /// 0 < danceability < 1 a measure of the maximum energy of the song 155 ArtistMaxFamiliarity, /// 0.0 < familiarity < 1.0 the maximum artist familiarity for songs in the playlist 156 ArtistMinFamiliarity, /// 0.0 < familiarity < 1.0 the minimum artist familiarity for songs in the playlist 157 ArtistMaxHotttnesss, /// 0.0 < hotttnesss < 1.0 the maximum hotttnesss for artists in the playlist 158 ArtistMinHotttnesss, /// 0.0 < hotttnesss < 1.0 the maximum hotttnesss for artists in the playlist 159 SongMaxHotttnesss, /// 0.0 < hotttnesss < 1.0 the maximum hotttnesss for songs in the playlist 160 SongMinHotttnesss, /// 0.0 < hotttnesss < 1.0 the maximum hotttnesss for songs in the playlist 161 ArtistMinLongitude, /// -180.0 < longitude < 180.0 the minimum longitude for the location of artists in the playlist 162 ArtistMaxLongitude, /// -180.0 < longitude < 180.0 the maximum longitude for the location of artists in the playlist 163 ArtistMinLatitude, /// -90.0 < latitude < 90.0 the minimum latitude for the location of artists in the playlist 164 ArtistMaxLatitude, /// -90.0 < latitude < 90.0 the maximum latitude for the location of artists in the playlist 165 Mode, /// (minor, major) 0, 1 the mode of songs in the playlist 166 Key, /// (c, c-sharp, d, e-flat, e, f, f-sharp, g, a-flat, a, b-flat, b) 0 - 11 the key of songs in the playlist 167 SongInformation, /// what sort of song information should be returned. Should be an Echonest::SongInformation object 168 Sort, /// SortingType enum, the type of sorting to use, 169 Limit, /// true, false if true songs will be limited to those that appear in the catalog specified by the id: bucket 170 Audio, /// true, false, if true songs will be limited to those that have associated audio 171 DMCA, /// true, false Only valid for dynamic playlists. Sets if playlist will follow DMCA rules (see web api doc for details) 172 ChainXSPF, /// true, false If true, returns an xspf for this dynamic playlist with 2 items. The second item will be a link to the API call for the next track in the chain. Please note that this sidesteps libechonest's handling of the tracks. 173 Mood, /// A mood to limit this playlist to, for example "happy" or "sad". Multiples of this param are okay. See the method Artist::listTerms for details on what moods are currently available 174 Style, /// A style to limit this playlist to, for example "happy" or "sad". Multiples of this param are okay. See the method Artist::listTerms for details on what styles are currently available 175 Adventurousness, /// A value of 0 means no adventurousness, only known and preferred music will be played. A value of 1 means high adventurousness, mostly unknown music will be played. This parameter only applies to catalog and catalog-radio type playlists. 176 MoreLikeThis, /// When steering: Supply a song id to steer this session towards. Can be boosted from 0-5 like so: SO12341234^2. Default is 1 177 LessLikeThis, /// When steering: Supply a song id to steer this session away from. Can be boosted from 0-5 like so: SO12341234^2. Default is 1 178 TargetTempo, /// When steering: 0.0 < tempo < 500. (BPM). Target a desired tempo for the songs in this dynamic playlist session 179 TargetLoudness, /// When steering: -100. < loudness < 100. (BPM)dB. Target a desired loudness for the songs in this dynamic playlist session 180 TargetDanceability, /// When steering: 0.0 < danceability < 1. Target a desired danceability for the songs in this dynamic playlist session 181 TargetEnergy, /// When steering: 0.0 < energy < 1.Target a desired energy for the songs in this dynamic playlist session 182 TargetSongHotttnesss, /// When steering: 0.0 < song_hotttnesss < 1.Target a desired song_hotttnesss for the songs in this dynamic playlist session 183 TargetArtistHotttnesss, /// When steering: 0.0 < artist_hottttnesss < 1.Target a desired artist_hottttnesss for the songs in this dynamic playlist session 184 TargetArtistFamiliarity, /// When steering: 0.0 < artist_familiarity < 1.Target a desired energy for the artist_familiarity in this dynamic playlist session 185 SongType, /// Type of Song (atm: Live, Studio, Christmas, Acoustic, Electric) 186 Genre, /// Genre Parameter needed for GenreRadio Playlist 187 ArtistStartYearBefore, 188 ArtistStartYearAfter, 189 ArtistEndYearBefore, 190 ArtistEndYearAfter, 191 MaxAcousticness, /// 0 < acousticness < 1 a measure of the maximum acousticness of the song 192 MinAcousticness, /// 0 < acousticness < 1 a measure of the minimum acousticness of the song 193 MaxSpeechiness, /// 0 < speechiness < 1 a measure of the maximum speechiness of the song 194 MinSpeechiness, /// 0 < speechiness < 1 a measure of the minimum speechiness of the song 195 MaxLiveness, /// 0 < liveness < 1 a measure of the maximum liveness of the song 196 MinLiveness, /// 0 < liveness < 1 a measure of the minimum liveness of the song 197 MaxValence, /// 0 < valence < 1 a measure of the maximum valence of the song 198 MinValence, /// 0 < valence < 1 a measure of the minimum valence of the song 199 Distribution, /// focused or wandering 200 GenrePreset /// core-best, core-shuffled, in_rotation-best, in_rotation-shuffled, emerging-best or emerging-shuffled 201 }; 202 203 /** 204 * The types of feedback that can be used to steer a dynamic playlist 205 */ 206 enum DynamicFeedbackParam { 207 BanArtist, /// Ban this artist from this dynamic session. [artist_id, track_id, song_id, "last"] 208 FavoriteArtist, /// Mark this artist as 'liked' for this session. [artist_id, track_id, song_id, "last"] 209 BanSong, /// Ban this song from this dynamic session. [track_id, song_id, "last"] 210 SkipSong, /// Mark this song as skipped by the user. Will not appear for the rest of the session. [track_id, song_id, "last"] 211 FavoriteSong, /// Mark this song as a favorite. [track_id, song_id, "last"] 212 PlaySong, /// Mark this song as played. Unneeded unless you want to pre-seed a station. [track_id, song_id, "last"] 213 UnplaySong, /// Remove a song from a dynamic session's history. Will not blacklist the song. [track_id, song_id, "last"] 214 RateSong, /// Rate the desired song. [track_id, song_id, "last"]^[0-10]. E.g: "last^3" or "TRTLKZV12E5AC92E11^5" 215 }; 216 217 /** 218 * The parameters that can be passed to GenrePreset 219 */ 220 enum GenrePresetParam { 221 CoreBest, 222 CoreShuffled, 223 InRotationBest, 224 InRotationShuffled, 225 EmergingBest, 226 EmerginShuffled, 227 }; 228 229 typedef QPair< PlaylistParam, QVariant > PlaylistParamData; 230 typedef QVector< PlaylistParamData > PlaylistParams; 231 232 typedef QPair< DynamicFeedbackParam, QByteArray > DynamicFeedbackParamData; 233 typedef QVector< DynamicFeedbackParamData > DynamicFeedback; 234 235 typedef QPair< SongList, SongList > FetchPair; 236 237 DynamicPlaylist(); 238 virtual ~DynamicPlaylist(); 239 DynamicPlaylist( const DynamicPlaylist& other ); 240 DynamicPlaylist& operator=( const DynamicPlaylist& playlist ); 241 242 /** 243 * Start a dynamic playlist with the given parameters. 244 * Once the QNetworkReply has finished, pass it to parseStart() 245 * 246 * To fetch tracks, call fetchNextSong(). The info() method can be used 247 * to extract session information 248 */ 249 QNetworkReply* create( const PlaylistParams& params ) const; 250 void parseCreate( QNetworkReply* ) throw( ParseError ); 251 252 /** 253 * Retart a dynamic playlist with the given parameters. 254 * Once the QNetworkReply has finished, pass it to parseStart() 255 * 256 * This is the same as start(), except it maintains the history from an 257 * already-existing playing station. 258 */ 259 QNetworkReply* restart( const PlaylistParams& params ) const; 260 261 /** 262 * The session id of this dynamic playlist. If the playlist has ended, or has not been started, 263 * the result is empty. 264 * 265 */ 266 QByteArray sessionId() const; 267 void setSessionId( const QByteArray& id ); 268 269 /** 270 * The current song of this dynamic playlist. Once this song has been played, 271 * or whenever is desired, call fetchNextSong() to get the next song. 272 */ 273 Song currentSong() const; 274 void setCurrentSong( const Song& song ); 275 276 /** 277 * Queries The Echo Nest for the next playable song(s) in this 278 * dynamic playlist. 279 * 280 * \param @results How many results to return, 1-5. This lets you 281 * reduce the calls if you need more than one. Default is 1. 282 * \param @lookahead The potential next songs (after the results) 283 * if there is no steering applied. 0-5, default of 0. 284 */ 285 QNetworkReply* next( int results = 1, int lookahead = 0 ) const; 286 287 /** 288 * Return the result of a dynamic/next API call. This will return two lists: 289 * the "next" list and the "lookahead" list. Consult the \ref next() docs 290 * and The Echo Nest documentation for more information. 291 */ 292 FetchPair parseNext( QNetworkReply* reply ) throw( ParseError ); 293 294 /** 295 * Returns feedback to The Echo Nest for the currently playing dynamic 296 * playlist. 297 * 298 * See The Echo Nest api documentation for complete details. 299 * 300 * \param feedback A list of feedback items to apply. 301 */ 302 QNetworkReply* feedback(const DynamicFeedback& feedback) const; 303 304 /** 305 * Parses the result of the feedback call. 306 * 307 * Will throw an exception if the return code is not successful (as other parse methods do). 308 */ 309 void parseFeedback(QNetworkReply* reply) const throw( ParseError ); 310 311 /** 312 * Modifies the upcoming tracks in this dynamic playlist session by steering it. 313 * 314 * Steering is additive, and can be reset for a dynamic playlist by calling reset. 315 * 316 * \param steerParams The desired steering params. Only use the enum values that correspond to valid steering commands. 317 */ 318 QNetworkReply* steer(const PlaylistParams& steerParams) const; 319 320 /** 321 * Parses the result of the steer call. 322 * 323 * Will throw an exception if the return code is not successful (as other parse methods do). 324 */ 325 void parseSteer(QNetworkReply* reply) const throw( ParseError ); 326 327 /** 328 * Returns a description of this dynamic playlist session 329 */ 330 QNetworkReply* fetchInfo() const; 331 SessionInfo parseInfo( QNetworkReply* reply ) throw( ParseError ); 332 333 /** 334 * Deletes a currently active playlist session. A non-commercial API can have, at most 1,000 active playlist sessions. 335 */ 336 QNetworkReply* deleteSession() const; 337 void parseDeleteSession(QNetworkReply* reply); 338 339 /** 340 * Generate a static playlist, according to the desired criteria. Use parseXSPFPlaylist if 341 * you pass format=xspf to \c staticPlaylist(). 342 */ 343 static QNetworkReply* staticPlaylist( const PlaylistParams& params ); 344 static SongList parseStaticPlaylist( QNetworkReply* reply ) throw( ParseError ); 345 346 /** 347 * Parse an xspf playlist. Returns the full xspf content with no modifications. 348 */ 349 static QByteArray parseXSPFPlaylist( QNetworkReply* reply ) throw( ParseError ); 350 351 private: 352 static QByteArray playlistParamToString( PlaylistParam param ); 353 static QNetworkReply* generateInternal( const PlaylistParams& params, const QByteArray& type ); 354 static QByteArray playlistSortToString(SortingType sorting); 355 static QByteArray playlistArtistPickToString(ArtistPick pick); 356 static QByteArray playlistGenrePresetToString(GenrePresetParam param); 357 static QByteArray dynamicFeedbackToString(DynamicFeedbackParam param); 358 359 QSharedDataPointer<DynamicPlaylistData> d; 360 }; 361 362 ECHONEST_EXPORT QDebug operator<<(QDebug d, const Echonest::DynamicPlaylist& playlist); 363 364 365 } // namespace 366 367 368 Q_DECLARE_METATYPE( Echonest::DynamicPlaylist ) 369 370 #endif 371