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 #include "PlaylistTest.h"
18
19 #include "Config.h"
20 #include "Playlist.h"
21
22 #include <QDebug>
23 #include <QtXml/QDomDocument>
24 #include <QVariant>
25 #include <QNetworkReply>
26 #include <QtNetwork/QNetworkReply>
27
28 using namespace Echonest;
29
initTestCase()30 void PlaylistTest::initTestCase()
31 {
32 Config::instance()->setAPIKey( "JGJCRKWLXLBZIFAZB" );
33 }
34
testStatic1()35 void PlaylistTest::testStatic1()
36 {
37 DynamicPlaylist::PlaylistParams p;
38 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "tallest man on earth" ) ) );
39 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "bon iver" ) ) );
40 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "mumford and sons" ) ) );
41 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Type, Echonest::DynamicPlaylist::ArtistRadioType ) );
42 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Results, 10 ) );
43
44 QNetworkReply* reply = DynamicPlaylist::staticPlaylist( p );
45
46 qDebug() << reply->url().toString();
47 QVERIFY( reply->url().toString() == QLatin1String( "http://developer.echonest.com/api/v4/playlist/static?api_key=JGJCRKWLXLBZIFAZB&format=xml&artist=tallest+man+on+earth&artist=bon+iver&artist=mumford+and+sons&type=artist-radio&results=10" ) );
48
49 QEventLoop loop;
50 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
51 loop.exec();
52 SongList songs = DynamicPlaylist::parseStaticPlaylist( reply );
53
54 QVERIFY( songs.size() == 10 );
55 Q_FOREACH( const Song& song, songs )
56 QVERIFY( !song.id().isEmpty() );
57
58 }
59
testStatic2()60 void PlaylistTest::testStatic2()
61 {
62 DynamicPlaylist::PlaylistParams p;
63 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Artist, QLatin1String( "tallest man on earth" ) ) );
64 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Artist, QLatin1String( "bon iver" ) ) );
65 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Artist, QLatin1String( "mumford and sons" ) ) );
66 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Artist, QLatin1String( "Florence + The Machine" ) ) );
67 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::ArtistMaxFamiliarity, 0.4 ) );
68 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::MinDanceability, 0.7 ) );
69 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Type, Echonest::DynamicPlaylist::ArtistType ) );
70 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::SongInformation, QVariant::fromValue( Echonest::SongInformation( Echonest::SongInformation::Hotttnesss | Echonest::SongInformation::ArtistHotttnesss | Echonest::SongInformation::ArtistFamiliarity ) ) ) );
71 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Results, 4 ) );
72
73 QNetworkReply* reply = DynamicPlaylist::staticPlaylist( p );
74
75 qDebug() << reply->url().toEncoded();
76 QCOMPARE( QLatin1String( reply->url().toEncoded() ), QLatin1String( "http://developer.echonest.com/api/v4/playlist/static?api_key=JGJCRKWLXLBZIFAZB&format=xml&artist=tallest+man+on+earth&artist=bon+iver&artist=mumford+and+sons&artist=Florence+%252B+The+Machine&artist_max_familiarity=0.4&min_danceability=0.7&type=artist&bucket=song_hotttnesss&bucket=artist_hotttnesss&bucket=artist_familiarity&results=4" ) );
77
78 QEventLoop loop;
79 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
80 loop.exec();
81 SongList songs = DynamicPlaylist::parseStaticPlaylist( reply );
82
83 // qDebug() << "Got songs;" << songs;
84 QVERIFY( songs.size() > 1 );
85 Q_FOREACH( const Song& song, songs ) {
86 QVERIFY( !song.id().isEmpty() );
87 }
88
89 p.clear();
90 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Description, QLatin1String( "70s" ) ) );
91 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Description, QLatin1String( "folk^2" ) ) );
92 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::ArtistMinFamiliarity, 0.4 ) );
93 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::MaxTempo, 100 ) );
94 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Mode, 0 ) );
95 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Type, Echonest::DynamicPlaylist::ArtistDescriptionType ) );
96 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Style, QLatin1String( "acoustic" ) ) );
97 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::SongInformation, QVariant::fromValue( Echonest::SongInformation( Echonest::SongInformation::AudioSummaryInformation | Echonest::SongInformation::Hotttnesss | Echonest::SongInformation::ArtistHotttnesss | Echonest::SongInformation::ArtistFamiliarity ) ) ) );
98 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Results, 7 ) );
99
100 reply = DynamicPlaylist::staticPlaylist( p );
101
102 // qDebug() << reply->url().toString();
103 QVERIFY( reply->url().toString() == QLatin1String( "http://developer.echonest.com/api/v4/playlist/static?api_key=JGJCRKWLXLBZIFAZB&format=xml&description=70s&description=folk^2&artist_min_familiarity=0.4&max_tempo=100&mode=0&type=artist-description&style=acoustic&bucket=audio_summary&bucket=song_hotttnesss&bucket=artist_hotttnesss&bucket=artist_familiarity&results=7" ) );
104
105 QEventLoop loop2;
106 loop2.connect( reply, SIGNAL(finished()), SLOT(quit()) );
107 loop2.exec();
108 songs = DynamicPlaylist::parseStaticPlaylist( reply );
109
110 QVERIFY( songs.size() == 7 );
111 Q_FOREACH( const Song& song, songs ) {
112 QVERIFY( !song.id().isEmpty() );
113 // qDebug() << song << song.audioSummary();
114 QVERIFY( song.audioSummary().duration() > 0 );
115 }
116
117 }
118
119
testStaticArtistYears()120 void PlaylistTest::testStaticArtistYears()
121 {
122 DynamicPlaylist::PlaylistParams p;
123 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Type, DynamicPlaylist::ArtistDescriptionType ) );
124 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Description, QLatin1String( "rock" ) ) );
125 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::ArtistStartYearBefore, 1970 ) );
126 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::ArtistEndYearBefore, 1980 ) );
127 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::SongInformation, QVariant::fromValue( Echonest::SongInformation( Echonest::SongInformation::Hotttnesss | Echonest::SongInformation::ArtistHotttnesss | Echonest::SongInformation::ArtistFamiliarity ) ) ) );
128 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Results, 4 ) );
129
130 QNetworkReply* reply = DynamicPlaylist::staticPlaylist( p );
131
132 qDebug() << reply->url().toEncoded();
133 QCOMPARE( QLatin1String( reply->url().toEncoded() ), QLatin1String( "http://developer.echonest.com/api/v4/playlist/static?api_key=JGJCRKWLXLBZIFAZB&format=xml&type=artist-description&description=rock&artist_start_year_before=1970&artist_end_year_before=1980&bucket=song_hotttnesss&bucket=artist_hotttnesss&bucket=artist_familiarity&results=4" ) );
134 QEventLoop loop;
135 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
136 loop.exec();
137 SongList songs = DynamicPlaylist::parseStaticPlaylist( reply );
138
139 // qDebug() << "Got songs;" << songs;
140 QCOMPARE( songs.size(), 4 );
141 Q_FOREACH( const Song& song, songs ) {
142 QVERIFY( !song.id().isEmpty() );
143 }
144
145 }
146
testStaticWithSongType()147 void PlaylistTest::testStaticWithSongType()
148 {
149 DynamicPlaylist::PlaylistParams p;
150 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Artist, QLatin1String( "The Beatles" ) ) );
151 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::SongType, QLatin1String( "live" ) ) );
152 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::SongInformation, QVariant::fromValue( Echonest::SongInformation( Echonest::SongInformation::AudioSummaryInformation | Echonest::SongInformation::Hotttnesss | Echonest::SongInformation::ArtistHotttnesss | Echonest::SongInformation::ArtistFamiliarity | Echonest::SongInformation::SongType ) ) ) );
153 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Sort, DynamicPlaylist::SortLivenessAscending ) );
154 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Results, 20 ) );
155
156 QNetworkReply* reply = DynamicPlaylist::staticPlaylist( p );
157
158 qDebug() << reply->url().toEncoded();
159
160 QEventLoop loop;
161 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
162 loop.exec();
163 SongList songs = DynamicPlaylist::parseStaticPlaylist( reply );
164
165 Q_FOREACH( const Song& song, songs ) {
166 QVERIFY( song.songTypes().contains( QLatin1String("live" ) ) );
167 }
168 }
169
testStaticXSPF()170 void PlaylistTest::testStaticXSPF()
171 {
172 DynamicPlaylist::PlaylistParams p;
173 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Artist, QLatin1String( "balmorhea" ) ) );
174 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Artist, QLatin1String( "tallest man on earth" ) ) );
175 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Artist, QLatin1String( "explosions in the sky" ) ) );
176 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::ArtistMaxFamiliarity, 0.4 ) );
177 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Format, QLatin1String( "xspf" ) ) );
178 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::MaxDanceability, 0.5 ) );
179 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Type, Echonest::DynamicPlaylist::ArtistType ) );
180 Echonest::SongInformation info( Echonest::SongInformation::Hotttnesss | Echonest::SongInformation::ArtistHotttnesss | Echonest::SongInformation::ArtistFamiliarity | Echonest::SongInformation::Tracks );
181 info.setIdSpaces( QStringList() << QLatin1String( "musicbrainz" ) << QLatin1String( "7digital" ) << QLatin1String( "playme" ) );
182 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::SongInformation, QVariant::fromValue( info ) ) );
183 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Limit, true ) );
184 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Results, 40 ) );
185
186 QNetworkReply* reply = DynamicPlaylist::staticPlaylist( p );
187
188 qDebug() << reply->url().toString();
189 QVERIFY( reply->url().toString() == QLatin1String( "http://developer.echonest.com/api/v4/playlist/static?api_key=JGJCRKWLXLBZIFAZB&artist=balmorhea&artist=tallest+man+on+earth&artist=explosions+in+the+sky&artist_max_familiarity=0.4&format=xspf&max_danceability=0.5&type=artist&bucket=tracks&bucket=song_hotttnesss&bucket=artist_hotttnesss&bucket=artist_familiarity&bucket=id:musicbrainz&bucket=id:7digital&bucket=id:playme&limit=true&results=40" ) );
190
191 QEventLoop loop;
192 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
193 loop.exec();
194 QByteArray xspf = DynamicPlaylist::parseXSPFPlaylist( reply );
195
196 // verify it's valid
197 QDomDocument doc;
198 QVERIFY( doc.setContent( xspf ) );
199 QVERIFY( !xspf.isEmpty() );
200
201 }
202
203
testDynamic1()204 void PlaylistTest::testDynamic1()
205 {
206 DynamicPlaylist::PlaylistParams p;
207 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "tallest man on earth" ) ) );
208 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "fleet foxes" ) ) );
209 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "johnny cash" ) ) );
210 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Type, Echonest::DynamicPlaylist::ArtistRadioType ) );
211 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::ArtistMinHotttnesss, .6 ) );
212 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::ArtistMaxFamiliarity, .4 ) );
213 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Mood, QLatin1String( "sad" ) ) );
214
215 DynamicPlaylist playlist;
216 QNetworkReply* reply = playlist.create( p );
217
218 qDebug() << reply->url().toString();
219 QCOMPARE( reply->url().toString(), QLatin1String( "http://developer.echonest.com/api/v4/playlist/dynamic/create?api_key=JGJCRKWLXLBZIFAZB&format=xml&artist=tallest+man+on+earth&artist=fleet+foxes&artist=johnny+cash&type=artist-radio&artist_min_hotttnesss=0.6&artist_max_familiarity=0.4&mood=sad" ) );
220
221 QEventLoop loop;
222 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
223 loop.exec();
224 playlist.parseCreate( reply );
225
226 reply = playlist.next( 1 );
227
228 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
229 loop.exec();
230
231 Song song = playlist.parseNext( reply ).first.first();
232 // qDebug() << "next:" << song;
233
234 QVERIFY( !song.id().isEmpty() );
235 QVERIFY( !song.title().isEmpty() );
236
237 reply = playlist.next( 1 );
238
239 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
240 loop.exec();
241 song = playlist.parseNext( reply ).first.first();
242
243 // qDebug() << "next:" << song;
244 QVERIFY( !song.id().isEmpty() );
245 QVERIFY( !song.title().isEmpty() );
246
247 reply = playlist.next( 1 );
248
249 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
250 loop.exec();
251 song = playlist.parseNext( reply ).first.first();
252
253 // qDebug() << "next:" << song;
254 QVERIFY( !song.id().isEmpty() );
255 QVERIFY( !song.title().isEmpty() );
256 }
257
testDynamic2()258 void PlaylistTest::testDynamic2()
259 {
260 DynamicPlaylist::PlaylistParams p;
261 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "pink floyd^-1" ) ) );
262 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "the who" ) ) );
263 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "queen" ) ) );
264 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "led zeppelin^2" ) ) );
265 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "-the beatles" ) ) ); //exclude
266 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Type, Echonest::DynamicPlaylist::ArtistType ) );
267 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::ArtistMinHotttnesss, .7 ) );
268 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::ArtistMaxFamiliarity, .3 ) );
269 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::MinLoudness, -10 ) );
270 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Mode, 1 ) );
271 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::SongInformation, QVariant::fromValue( Echonest::SongInformation( Echonest::SongInformation::AudioSummaryInformation | Echonest::SongInformation::Hotttnesss | Echonest::SongInformation::ArtistHotttnesss | Echonest::SongInformation::ArtistFamiliarity ) ) ) );
272
273 DynamicPlaylist playlist;
274 QNetworkReply* reply = playlist.create( p );
275
276 qDebug() << reply->url().toString();
277 QCOMPARE( reply->url().toString(), QLatin1String( "http://developer.echonest.com/api/v4/playlist/dynamic/create?api_key=JGJCRKWLXLBZIFAZB&format=xml&artist=pink+floyd^-1&artist=the+who&artist=queen&artist=led+zeppelin^2&artist=-the+beatles&type=artist&artist_min_hotttnesss=0.7&artist_max_familiarity=0.3&min_loudness=-10&mode=1&bucket=audio_summary&bucket=song_hotttnesss&bucket=artist_hotttnesss&bucket=artist_familiarity" ) );
278
279 QEventLoop loop;
280 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
281 loop.exec();
282 playlist.parseCreate( reply );
283
284 reply = playlist.next( 1 );
285 qDebug() << reply->url().toString();
286
287 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
288 loop.exec();
289 Echonest::Song song = playlist.parseNext( reply ).first.first();
290
291 // qDebug() << "next:" << song;
292 QVERIFY( !song.id().isEmpty() );
293 QVERIFY( !song.title().isEmpty() );
294
295 // GET NEXT
296 reply = playlist.next( 1 );
297 qDebug() << reply->url().toString();
298
299 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
300 loop.exec();
301 song = playlist.parseNext( reply ).first.first();
302
303 // qDebug() << "next:" << song;
304 QVERIFY( !song.id().isEmpty() );
305 QVERIFY( !song.title().isEmpty() );
306
307 // GET NEXT
308 reply = playlist.next( 1 );
309 qDebug() << reply->url().toString();
310
311 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
312 loop.exec();
313 song = playlist.parseNext( reply ).first.first();
314
315 // qDebug() << "next:" << song;
316 QVERIFY( !song.id().isEmpty() );
317 QVERIFY( !song.title().isEmpty() );
318
319 // GET NEXT
320 DynamicPlaylist::PlaylistParams steering;
321 steering.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::TargetEnergy, QLatin1String( ".8" ) ) );
322 steering.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::ArtistMinFamiliarity, QLatin1String( ".5" ) ) );
323
324 reply = playlist.steer( steering );
325 qDebug() << reply->url().toString();
326
327 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
328 loop.exec();
329 playlist.parseSteer( reply );
330
331 reply = playlist.next( 1 );
332 qDebug() << reply->url().toString();
333
334
335 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
336 loop.exec();
337 song = playlist.parseNext( reply ).first.first();
338 // qDebug() << "next steered:" << song;
339 QVERIFY( !song.id().isEmpty() );
340 QVERIFY( !song.title().isEmpty() );
341
342 // GET NEXT
343 steering.clear();
344 steering.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::TargetLoudness, QLatin1String( ".9" ) ) );
345 //steering.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::MoreLikeThis, QLatin1String( "last" ) ) ); //BUG: this no longer seems to work
346
347 reply = playlist.steer( steering );
348 qDebug() << reply->url().toString();
349
350 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
351 loop.exec();
352 playlist.parseSteer( reply );
353
354 playlist.next();
355
356 reply = playlist.next( 1 );
357 qDebug() << reply->url().toString();
358
359 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
360 loop.exec();
361 song = playlist.parseNext( reply ).first.first();
362 // qDebug() << "next steered:" << song;
363 QVERIFY( !song.id().isEmpty() );
364 QVERIFY( !song.title().isEmpty() );
365
366 // GET INFO TODO
367 /*reply = playlist.fetchSessionInfo();
368 qDebug() << "session info URL:" << reply->url().toString();
369 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
370 loop.exec();
371 Echonest::SessionInfo info = playlist.parseSessionInfo( reply );
372 QVERIFY( !info.banned_artists.isEmpty() );
373 QVERIFY( !info.banned_songs.isEmpty() );
374 QVERIFY( !info.banned_songs.at( 0 ).artist_id.isEmpty() );
375 QVERIFY( !info.banned_songs.at( 0 ).artist_name.isEmpty() );
376 QVERIFY( !info.banned_songs.at( 0 ).id.isEmpty() );
377 QVERIFY( !info.banned_songs.at( 0 ).title.isEmpty() );
378 QVERIFY( !info.skipped_songs.isEmpty() );
379 QVERIFY( !info.skipped_songs.at( 0 ).artist_id.isEmpty() );
380 QVERIFY( !info.skipped_songs.at( 0 ).artist_name.isEmpty() );
381 QVERIFY( !info.skipped_songs.at( 0 ).id.isEmpty() );
382 QVERIFY( !info.skipped_songs.at( 0 ).title.isEmpty() );
383 QVERIFY( !info.rated_songs.isEmpty() );
384 QVERIFY( !info.rated_songs.at( 0 ).artist_id.isEmpty() );
385 QVERIFY( !info.rated_songs.at( 0 ).artist_name.isEmpty() );
386 QVERIFY( !info.rated_songs.at( 0 ).id.isEmpty() );
387 QVERIFY( !info.rated_songs.at( 0 ).title.isEmpty() );
388 QVERIFY( !info.history.isEmpty() );
389 QVERIFY( !info.history.at( 0 ).artist_id.isEmpty() );
390 QVERIFY( !info.history.at( 0 ).artist_name.isEmpty() );
391 QVERIFY( !info.history.at( 0 ).id.isEmpty() );
392 QVERIFY( !info.history.at( 0 ).title.isEmpty() );
393 QVERIFY( !info.playlist_type.isEmpty() );
394 QVERIFY( !info.rules.isEmpty() );
395 QVERIFY( !info.session_id.isEmpty() );
396
397 QVERIFY( !song.id().isEmpty() );
398 QVERIFY( !song.title().isEmpty() );*/
399 QByteArray oldId = playlist.sessionId();
400 // now reset it
401 p.clear();
402 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Type, Echonest::DynamicPlaylist::ArtistRadioType ) );
403 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "pink floyd" ) ) );
404 reply = playlist.create( p );
405 qDebug() << reply->url().toString();
406
407 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
408 loop.exec();
409 playlist.parseCreate( reply );
410
411 reply = playlist.next();
412 qDebug() << reply->url().toString();
413
414 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
415 loop.exec();
416
417 song = playlist.parseNext( reply ).first.first();
418 // qDebug() << "new:" << song << song.artistFamiliarity() << song.artistHotttnesss();
419
420 QVERIFY( !song.id().isEmpty() );
421 QVERIFY( !song.title().isEmpty() );
422 QVERIFY( song.artistHotttnesss() == -1 ); // make sure we are in a new playlist, and we didn't ask for this info so it shouldn't be there
423 QVERIFY( song.artistFamiliarity() == -1 ); // make sure we are in a new playlist, and we didn't ask for this info so it shouldn't be there
424
425 reply = playlist.deleteSession();
426 qDebug() << reply->url().toString();
427
428 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
429 loop.exec();
430
431 playlist.parseDeleteSession(reply);
432 Q_ASSERT(playlist.sessionId().isEmpty());
433
434 }
435
testNewDynamicAPI()436 void PlaylistTest::testNewDynamicAPI()
437 {
438 DynamicPlaylist::PlaylistParams p;
439 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "frightened rabbit" ) ) );
440 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "wilco" ) ) );
441 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "the tallest man on earth" ) ) );
442 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "noah and the whale" ) ) );
443 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::ArtistMaxFamiliarity, QLatin1String( ".4" ) ) );
444 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Key, QLatin1String( "3" ) ) );
445 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Type, Echonest::DynamicPlaylist::ArtistRadioType ) );
446
447 DynamicPlaylist playlist;
448 QNetworkReply* reply = playlist.create( p );
449
450 // qDebug() << reply->url().toString();
451 QCOMPARE( reply->url().toString(), QLatin1String( "http://developer.echonest.com/api/v4/playlist/dynamic/create?api_key=JGJCRKWLXLBZIFAZB&format=xml&artist=frightened+rabbit&artist=wilco&artist=the+tallest+man+on+earth&artist=noah+and+the+whale&artist_max_familiarity=.4&key=3&type=artist-radio" ) );
452
453 QEventLoop loop;
454 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
455 loop.exec();
456 playlist.parseCreate( reply );
457
458 reply = playlist.next( 2 );
459
460 // qDebug() << reply->url().toString();
461 QCOMPARE( reply->url().toString(), QString( QLatin1String( "http://developer.echonest.com/api/v4/playlist/dynamic/next?api_key=JGJCRKWLXLBZIFAZB&format=xml&session_id=%1&results=2&lookahead=0" ) ).arg( QString::fromLatin1( playlist.sessionId() ) ) );
462 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
463 loop.exec();
464
465 QPair< SongList, SongList > ret;
466 ret = playlist.parseNext( reply );
467
468 QCOMPARE( ret.first.size(), 2 );
469 QCOMPARE( ret.second.size(), 0 );
470
471 QVERIFY( !ret.first.at( 0 ).id().isNull() );
472 QVERIFY( !ret.first.at( 0 ).title().isNull() );
473 QVERIFY( !ret.first.at( 1 ).id().isNull() );
474 QVERIFY( !ret.first.at( 1 ).title().isNull() );
475
476 DynamicPlaylist::DynamicFeedback feedback;
477 feedback.append( DynamicPlaylist::DynamicFeedbackParamData( DynamicPlaylist::FavoriteArtist, "last" ) );
478 feedback.append( DynamicPlaylist::DynamicFeedbackParamData( DynamicPlaylist::FavoriteSong, "last" ) );
479 reply = playlist.feedback( feedback );
480
481 // qDebug() << reply->url().toString();
482 QString u = QString::fromUtf8( "http://developer.echonest.com/api/v4/playlist/dynamic/feedback?api_key=JGJCRKWLXLBZIFAZB&format=xml&session_id=%1&favorite_artist=last&favorite_song=last" );
483 QCOMPARE( reply->url().toString(), u.arg( QString::fromUtf8( playlist.sessionId() ) ) );
484 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
485 loop.exec();
486 playlist.parseFeedback( reply );
487
488 DynamicPlaylist::PlaylistParams steering;
489 steering.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::MoreLikeThis, QLatin1String( "SONRAMP13775DE8214^4" ) ) );
490 steering.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Mood, QLatin1String( "happy^2" ) ) );
491
492 reply = playlist.steer( steering );
493
494 // qDebug() << reply->url().toString();
495 u = QString::fromUtf8( "http://developer.echonest.com/api/v4/playlist/dynamic/steer?api_key=JGJCRKWLXLBZIFAZB&format=xml&session_id=%1&more_like_this=SONRAMP13775DE8214^4&mood=happy^2" );
496 QCOMPARE( reply->url().toString(), u.arg( QString::fromUtf8( playlist.sessionId() ) ) );
497 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
498 loop.exec();
499 playlist.parseSteer( reply );
500
501 reply = playlist.next( 3, 3 );
502
503 // qDebug() << reply->url().toString();
504 u = QString::fromUtf8( "http://developer.echonest.com/api/v4/playlist/dynamic/next?api_key=JGJCRKWLXLBZIFAZB&format=xml&session_id=%1&results=3&lookahead=3" );
505 QCOMPARE( reply->url().toString(), u.arg( QString::fromUtf8( playlist.sessionId() ) ) );
506 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
507 loop.exec();
508
509 ret = playlist.parseNext( reply );
510
511 QCOMPARE( ret.first.size(), 3 );
512 QCOMPARE( ret.second.size(), 3 );
513
514 QVERIFY( !ret.first.at( 0 ).id().isNull() );
515 QVERIFY( !ret.first.at( 0 ).title().isNull() );
516 QVERIFY( !ret.first.at( 1 ).id().isNull() );
517 QVERIFY( !ret.first.at( 1 ).title().isNull() );
518 QVERIFY( !ret.first.at( 2 ).id().isNull() );
519 QVERIFY( !ret.first.at( 2 ).title().isNull() );
520 QVERIFY( !ret.second.at( 0 ).id().isNull() );
521 QVERIFY( !ret.second.at( 0 ).title().isNull() );
522 QVERIFY( !ret.second.at( 1 ).id().isNull() );
523 QVERIFY( !ret.second.at( 1 ).title().isNull() );
524 QVERIFY( !ret.second.at( 2 ).id().isNull() );
525 QVERIFY( !ret.second.at( 2 ).title().isNull() );
526 }
527
testDynamicChainXSPF()528 void PlaylistTest::testDynamicChainXSPF()
529 {
530 DynamicPlaylist::PlaylistParams p;
531 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "pink floyd^-1" ) ) );
532 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "the who" ) ) );
533 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "queen" ) ) );
534 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "led zeppelin^2" ) ) );
535 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "-the beatles" ) ) ); //exclude
536 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Type, Echonest::DynamicPlaylist::ArtistType ) );
537 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::ArtistMinHotttnesss, .7 ) );
538 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::ArtistMaxFamiliarity, .3 ) );
539 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::MinLoudness, -10 ) );
540 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Mode, 1 ) );
541 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::ChainXSPF, true ) );
542 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Format, QLatin1String( "xspf" ) ) );
543 Echonest::SongInformation info( Echonest::SongInformation::Hotttnesss | Echonest::SongInformation::ArtistHotttnesss | Echonest::SongInformation::ArtistFamiliarity | Echonest::SongInformation::Tracks );
544 info.setIdSpaces( QStringList() << QLatin1String( "musicbrainz" ) << QLatin1String( "7digital" ) << QLatin1String( "playme" ) );
545 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::SongInformation, QVariant::fromValue( info ) ) );
546 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Limit, true ) );
547
548 DynamicPlaylist playlist;
549 QNetworkReply* reply = playlist.create( p );
550
551 qDebug() << reply->url().toString();
552 // QVERIFY( reply->url().toString() == QLatin1String( "http://developer.echonest.com/api/v4/playlist/dynamic?api_key=JGJCRKWLXLBZIFAZB&artist=pink+floyd^-1&artist=the+who&artist=queen&artist=led+zeppelin^2&artist=-the+beatles&type=artist&artist_min_hotttnesss=0.7&artist_max_familiarity=0.3&min_loudness=-10&mode=1&chain_xspf=true&format=xspf&bucket=audio_summary&bucket=song_hotttnesss&bucket=artist_hotttnesss&bucket=artist_familiarity" ) );
553
554 QEventLoop loop;
555 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
556 loop.exec();
557 QByteArray xspf = Echonest::DynamicPlaylist::parseXSPFPlaylist( reply );
558
559 // qDebug() << "xspf:" << xspf; // verify it's valid
560 QDomDocument doc;
561 QVERIFY( doc.setContent( xspf ) );
562 QVERIFY( !xspf.isEmpty() );
563
564 }
565
testGenreRadio()566 void PlaylistTest::testGenreRadio()
567 {
568 DynamicPlaylist::PlaylistParams p;
569 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Genre, QLatin1String( "dance pop" ) ) );
570 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Type, Echonest::DynamicPlaylist::GenreRadioType ) );
571 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::SongInformation, QVariant::fromValue( Echonest::SongInformation( Echonest::SongInformation::AudioSummaryInformation | Echonest::SongInformation::Hotttnesss | Echonest::SongInformation::ArtistHotttnesss | Echonest::SongInformation::ArtistFamiliarity | Echonest::SongInformation::SongType ) ) ) );
572 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Results, 20 ) );
573
574 QNetworkReply* reply = DynamicPlaylist::staticPlaylist( p );
575
576 qDebug() << reply->url().toEncoded();
577
578 QEventLoop loop;
579 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
580 loop.exec();
581 SongList songs = DynamicPlaylist::parseStaticPlaylist( reply );
582 QVERIFY( songs.size() == 20 );
583
584 /*Q_FOREACH( const Song& song, songs ) {
585 //no usefull test code can be inserted here, because genres are not (yet?) supported in songs (e.g. to check via SongInformation if a song is genre "dance pop")
586 qDebug() << song;
587 }*/
588 }
589
testAudioSummaryAttributes()590 void PlaylistTest::testAudioSummaryAttributes()
591 {
592 DynamicPlaylist::PlaylistParams p;
593 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Artist, QLatin1String( "The Doors" ) ) );
594 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::MinLiveness, 0.7 ) );
595 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::MaxValence, 0.7 ) );
596 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Sort, DynamicPlaylist::SortValenceDescending ) );
597 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::SongInformation, QVariant::fromValue( Echonest::SongInformation( Echonest::SongInformation::AudioSummaryInformation | Echonest::SongInformation::Hotttnesss | Echonest::SongInformation::ArtistHotttnesss | Echonest::SongInformation::ArtistFamiliarity | Echonest::SongInformation::SongType ) ) ) );
598 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Results, 10 ) );
599
600 QNetworkReply* reply = DynamicPlaylist::staticPlaylist( p );
601
602 qDebug() << reply->url().toEncoded();
603
604 QEventLoop loop;
605 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
606 loop.exec();
607 SongList songs = DynamicPlaylist::parseStaticPlaylist( reply );
608
609 Q_FOREACH( const Song& song, songs ) {
610 QVERIFY( song.audioSummary().liveness() >= 0.7 );
611 }
612 }
613
testGenrePresets()614 void PlaylistTest::testGenrePresets()
615 {
616 DynamicPlaylist::PlaylistParams p;
617 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Genre, QLatin1String( "classic rock" ) ) );
618 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Type, Echonest::DynamicPlaylist::GenreRadioType ) );
619 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::GenrePreset, DynamicPlaylist::CoreBest ) );
620 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Results, 30 ) );
621
622 QNetworkReply* reply = DynamicPlaylist::staticPlaylist( p );
623
624 qDebug() << reply->url().toEncoded();
625
626 QEventLoop loop;
627 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
628 loop.exec();
629 SongList songs = DynamicPlaylist::parseStaticPlaylist( reply );
630
631 QVERIFY( songs.size() == 30 );
632 }
633
testDistribution()634 void PlaylistTest::testDistribution()
635 {
636 DynamicPlaylist::PlaylistParams p;
637 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Artist, QLatin1String( "the doors" ) ) );
638 p.append( DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Type, Echonest::DynamicPlaylist::ArtistRadioType ) );
639 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Results, 50 ) );
640 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Distribution, QLatin1String( "wandering" ) ) );
641 p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::GenrePreset, DynamicPlaylist::CoreBest ) );
642
643 QNetworkReply* reply = DynamicPlaylist::staticPlaylist( p );
644
645 qDebug() << reply->url().toEncoded();
646
647 QEventLoop loop;
648 loop.connect( reply, SIGNAL(finished()), SLOT(quit()) );
649 loop.exec();
650 SongList songs = DynamicPlaylist::parseStaticPlaylist( reply );
651
652 Q_FOREACH( const Song& song, songs) {
653 qDebug() << song;
654 }
655
656 QVERIFY( songs.size() == 50 );
657 }
658
659 QTEST_MAIN( PlaylistTest )
660
661 #include "PlaylistTest.moc"
662
663