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_SONG_H 19 #define ECHONEST_SONG_H 20 21 #include "echonest_export.h" 22 #include "Track.h" 23 #include "TypeInformation.h" 24 25 #include <QSharedData> 26 #include <QHash> 27 #include <QVariant> 28 #include <QDebug> 29 #include <QVector> 30 #include "Config.h" 31 32 class QNetworkReply; 33 class SongData; 34 35 namespace Echonest{ 36 37 class DynamicPlaylist; // forward declare for friend declaration 38 class Catalog; 39 class AudioSummary; 40 41 /** 42 * This encapsulates an Echo Nest song---use it if you wish to get information about a song, 43 * search for a song, etc. 44 * 45 * This class is implicitly shared. 46 */ 47 class ECHONEST_EXPORT Song 48 { 49 50 public: 51 52 enum SearchParam { 53 Title, 54 Artist, 55 Combined, 56 Description, 57 ArtistId, 58 Start, 59 Results, 60 MaxTempo, 61 MinTempo, 62 MaxDanceability, 63 MinDanceability, 64 MaxComplexity, 65 MinComplexity, 66 MaxDuration, 67 MinDuration, 68 MaxLoudness, 69 MinLoudness, 70 MaxFamiliarity, 71 MinFamiliarity, 72 MaxHotttnesss, 73 MinHotttnesss, 74 MaxLongitude, 75 MinLongitude, 76 MaxEnergy, 77 MinEnergy, 78 Mode, 79 Key, 80 Sort, 81 SongType, 82 ArtistStartYearBefore, 83 ArtistStartYearAfter, 84 ArtistEndYearBefore, 85 ArtistEndYearAfter, 86 MaxAcousticness, 87 MinAcousticness, 88 MaxSpeechiness, 89 MinSpeechiness, 90 MaxLiveness, 91 MinLiveness, 92 MaxValence, 93 MinValence 94 }; 95 typedef QPair< Echonest::Song::SearchParam, QVariant > SearchParamData; 96 typedef QVector< SearchParamData > SearchParams; 97 98 enum IdentifyParam { 99 Code, 100 IdentifyArtist, 101 IdentifyTitle, 102 IdentifyRelease, 103 IdentifyDuration, 104 IdentifyGenre 105 }; 106 typedef QPair< Echonest::Song::IdentifyParam, QVariant > IdentifyParamData; 107 typedef QVector< IdentifyParamData > IdentifyParams; 108 109 Song(); 110 Song( const QByteArray& id, const QString& title, const QByteArray& artistId, const QString& artistName ); 111 Song( const QByteArray& id ); 112 Song( const Song& other ); 113 Song& operator=(const Song& song); 114 virtual ~Song(); 115 116 /** 117 * The following pieces of data are present in all Song objects, and do not require 118 * on-demand fetching. 119 */ 120 QByteArray id() const; 121 void setId( const QByteArray& id ); 122 123 QString title() const; 124 void setTitle( const QString& title ); 125 126 QString artistName() const; 127 void setArtistName( const QString& artistName ); 128 129 QByteArray artistId() const; 130 void setArtistId( const QByteArray& artistId ); 131 132 QString release() const; 133 void setRelease( const QString& release ); 134 135 /** 136 * The following require fetching from The Echo Nest, so call 137 * fetchInformation() with the type of data you want first. 138 * 139 * If you ask for this information before calling parseInformation() 140 * with the respective data, the result is undefined. 141 */ 142 143 /** 144 * The full audio summary and analysis of this song. 145 * 146 * NOTE: This will return a copy of the AudioSummary object, which 147 * is implicitly shared. If you make modifications to the returned 148 * summary, for example by calling parseFullAnalysis(), it will detach 149 * and you will have to call setAudioSummary() to save the changes back 150 * to this Song object. 151 */ 152 AudioSummary audioSummary() const; 153 void setAudioSummary( const AudioSummary& summary ); 154 155 /** 156 * The associated Track objects with acoustic track information 157 */ 158 QVector< Track > tracks() const; 159 void setTracks( const QVector< Track >& tracks ); 160 161 /** 162 * The "hotttnesss" metric of this song. 163 */ 164 qreal hotttnesss() const; 165 void setHotttnesss( qreal hotttnesss ); 166 167 /** 168 * The "hotttnesss" metric of this song's artist. 169 */ 170 qreal artistHotttnesss() const; 171 void setArtistHotttnesss( qreal artistHotttnesss ); 172 173 /** 174 * The familiarity metric of this song's artist. 175 */ 176 qreal artistFamiliarity() const; 177 void setArtistFamiliarity( qreal artistFamiliarity ); 178 179 /** 180 * The location of this artist. 181 */ 182 ArtistLocation artistLocation() const; 183 void setArtistLocation( const ArtistLocation& artistLocation ); 184 185 /** 186 * The type of the song (atm: christmas, studio, live) 187 */ 188 QList< QString > songTypes() const; 189 void setSongTypes( const QList< QString >& songTypes ); 190 void addSongType( const QString& songType ); 191 192 /** 193 * This fetches the data from The Echo Nest for the requested data, so it 194 * returns a QNetworkReply*. When the finished() signal is emitted 195 * from the QNetworkReply object call parseInformation() to save the 196 * data back to this Song object. 197 * 198 */ 199 QNetworkReply* fetchInformation( SongInformation information = SongInformation() ) const; 200 201 /** 202 * Search for a song from The Echo Nest with the given search parameters. See 203 * http://developer.echonest.com/docs/v4/song.html#search for a description of the 204 * parameters and data types. 205 * 206 * The result will contain the requested information from the SongInformation flags, and 207 * can be extracted in the parseSearch() function. 208 * 209 */ 210 static QNetworkReply* search( const SearchParams& params, SongInformation information = SongInformation() ); 211 212 /** 213 * Identify a song from a given Echo Nest fingerprint hash code. 214 * NOTE: SongInformation is currently not parsed yet. 215 * 216 */ 217 static QNetworkReply* identify( const IdentifyParams& params, const SongInformation& information = SongInformation() ); 218 219 /** 220 * Identify a song from the Echoprint hash code, this time using the output of the 'echoprint-codegen' command-line 221 * tool 222 */ 223 // static QNetworkReply* identify( const QByteArray& jsonData ); 224 225 /** 226 * Parses the reply of the identify call and returns a list of songs found. 227 * 228 */ 229 static QVector< Song > parseIdentify( QNetworkReply* ) throw( ParseError ); 230 231 /** 232 * Parse the result of the fetchInformation() call. 233 * For each requested SongInformationFlag in the original request, the respective 234 * data will be saved to this Song object. 235 */ 236 void parseInformation( QNetworkReply* reply ) throw( ParseError ); 237 238 /** 239 * Parse the result of the search() call. 240 */ 241 static QVector<Song> parseSearch( QNetworkReply* reply ) throw( ParseError ); 242 243 QString toString() const; 244 245 friend class DynamicPlaylist; 246 friend class Catalog; // for access to searchParamToString 247 private: 248 static QByteArray searchParamToString( SearchParam param ); 249 static QByteArray identifyParamToString( IdentifyParam param ); 250 static void addQueryInformation( QUrl& url, SongInformation information ); 251 252 QSharedDataPointer<SongData> d; 253 }; 254 255 typedef QVector< Song > SongList; 256 257 ECHONEST_EXPORT QDebug operator<<(QDebug d, const Song &song); 258 259 } // namespace 260 261 Q_DECLARE_METATYPE( Echonest::Song ) 262 263 #endif 264