1
/****************************************************************************************
2
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
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 *
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. *
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
****************************************************************************************/
18
#include "Playlist_p.h"
19
#include "Parsing_p.h"
20
#include <QtNetwork/QNetworkReply>
22
Echonest::DynamicPlaylist::DynamicPlaylist()
23
: d( new DynamicPlaylistData )
28
Echonest::DynamicPlaylist::DynamicPlaylist(const Echonest::DynamicPlaylist& other)
34
Echonest::DynamicPlaylist::~DynamicPlaylist()
40
Echonest::DynamicPlaylist& Echonest::DynamicPlaylist::operator=(const Echonest::DynamicPlaylist& playlist)
46
QNetworkReply* Echonest::DynamicPlaylist::start(const Echonest::DynamicPlaylist::PlaylistParams& params) const
48
// params are the same, if user passes in format parsing will throw, but it should be expected..
49
return generateInternal( params, "dynamic" );
52
Echonest::Song Echonest::DynamicPlaylist::parseStart(QNetworkReply* reply) throw( Echonest::ParseError )
54
Echonest::Parser::checkForErrors( reply );
55
QByteArray data = reply->readAll();
57
QXmlStreamReader xml( data );
59
Echonest::Parser::readStatus( xml );
60
d->sessionId = Echonest::Parser::parsePlaylistSessionId( xml );
61
Echonest::SongList songs = Echonest::Parser::parseSongList( xml );
62
if( !songs.size() == 1 )
63
throw Echonest::ParseError( UnknownParseError );
65
d->currentSong = songs.front();
68
return d->currentSong;
71
QByteArray Echonest::DynamicPlaylist::sessionId() const
76
void Echonest::DynamicPlaylist::setSessionId(const QByteArray& id)
81
Echonest::Song Echonest::DynamicPlaylist::currentSong() const
83
return d->currentSong;
86
void Echonest::DynamicPlaylist::setCurrentSong(const Echonest::Song& song)
88
d->currentSong = song;
91
QNetworkReply* Echonest::DynamicPlaylist::fetchNextSong(int rating) const
93
QUrl url = Echonest::baseGetQuery( "playlist", "dynamic" );
94
url.addEncodedQueryItem( "session_id", d->sessionId );
97
url.addEncodedQueryItem( "rating", QByteArray::number( rating ) );
99
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
103
QNetworkReply* Echonest::DynamicPlaylist::fetchNextSong(const DynamicControls& controls) const
105
QUrl url = Echonest::baseGetQuery( "playlist", "dynamic" );
106
url.addEncodedQueryItem( "session_id", d->sessionId );
108
DynamicControls::const_iterator iter = controls.begin();
109
for( ; iter != controls.end(); ++iter ) {
110
QString value = iter->second;
111
url.addEncodedQueryItem( dynamicControlToString( iter->first ), Echonest::escapeSpacesAndPluses( value ) );
114
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
117
QNetworkReply* Echonest::DynamicPlaylist::fetchSessionInfo() const
119
QUrl url = Echonest::baseGetQuery( "playlist", "session_info" );
120
url.addEncodedQueryItem( "session_id", d->sessionId );
122
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
126
Echonest::Song Echonest::DynamicPlaylist::parseNextSong(QNetworkReply* reply)
128
return parseStart( reply );
131
Echonest::SessionInfo Echonest::DynamicPlaylist::parseSessionInfo(QNetworkReply* reply) throw( Echonest::ParseError )
133
Echonest::Parser::checkForErrors( reply );
135
QXmlStreamReader xml( reply->readAll() );
137
Echonest::Parser::readStatus( xml );
139
reply->deleteLater();
140
return Echonest::Parser::parseSessionInfo( xml );
145
QNetworkReply* Echonest::DynamicPlaylist::staticPlaylist(const Echonest::DynamicPlaylist::PlaylistParams& params)
147
return Echonest::DynamicPlaylist::generateInternal( params, "static" );
150
Echonest::SongList Echonest::DynamicPlaylist::parseStaticPlaylist(QNetworkReply* reply) throw( Echonest::ParseError )
152
Echonest::Parser::checkForErrors( reply );
154
QXmlStreamReader xml( reply->readAll() );
156
Echonest::Parser::readStatus( xml );
158
Echonest::SongList songs = Echonest::Parser::parseSongList( xml );
159
reply->deleteLater();
163
QByteArray Echonest::DynamicPlaylist::parseXSPFPlaylist(QNetworkReply* reply) throw( Echonest::ParseError )
165
QByteArray data = reply->readAll();
166
Echonest::Parser::checkForErrors( reply );
168
reply->deleteLater();
172
QNetworkReply* Echonest::DynamicPlaylist::generateInternal(const Echonest::DynamicPlaylist::PlaylistParams& params, const QByteArray& type)
174
QUrl url = Echonest::baseGetQuery( "playlist", type );
176
Echonest::DynamicPlaylist::PlaylistParams::const_iterator iter = params.constBegin();
177
for( ; iter < params.constEnd(); ++iter ) {
178
if( iter->first == Format ) // If it's a format, we have to remove the xml format we automatically specify
179
url.removeEncodedQueryItem( "format" );
181
if( iter->first == Type ) { // convert type enum to string
182
switch( static_cast<Echonest::DynamicPlaylist::ArtistTypeEnum>( iter->second.toInt() ) )
185
url.addEncodedQueryItem( playlistParamToString( iter->first ), "artist" );
187
case ArtistRadioType:
188
url.addEncodedQueryItem( playlistParamToString( iter->first ), "artist-radio" );
190
case ArtistDescriptionType:
191
url.addEncodedQueryItem( playlistParamToString( iter->first ), "artist-description" );
194
url.addEncodedQueryItem( playlistParamToString( iter->first ), "catalog" );
196
case CatalogRadioType:
197
url.addEncodedQueryItem( playlistParamToString( iter->first ), "catalog-radio" );
200
url.addEncodedQueryItem( playlistParamToString( iter->first ), "song-radio" );
204
} else if( iter->first == Sort ) {
205
url.addEncodedQueryItem( playlistParamToString( iter->first ), playlistSortToString( static_cast<Echonest::DynamicPlaylist::SortingType>( iter->second.toInt() ) ) );
206
} else if( iter->first == Pick ) {
207
url.addEncodedQueryItem( playlistParamToString( iter->first ), playlistArtistPickToString( static_cast<Echonest::DynamicPlaylist::ArtistPick>( iter->second.toInt() ) ) );
208
} else if( iter->first == SongInformation ){
209
Echonest::Song::addQueryInformation( url, Echonest::SongInformation( iter->second.value< Echonest::SongInformation >() ) );
211
url.addEncodedQueryItem( playlistParamToString( iter->first ), Echonest::escapeSpacesAndPluses( iter->second.toString() ) );
215
qDebug() << "Creating playlist URL" << url;
216
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
220
QByteArray Echonest::DynamicPlaylist::playlistParamToString(Echonest::DynamicPlaylist::PlaylistParam param)
224
case Echonest::DynamicPlaylist::Type :
226
case Echonest::DynamicPlaylist::Format :
228
case Echonest::DynamicPlaylist::Pick:
229
return "artist_pick";
230
case Echonest::DynamicPlaylist::Variety :
232
case Echonest::DynamicPlaylist::ArtistId :
234
case Echonest::DynamicPlaylist::Artist :
236
case Echonest::DynamicPlaylist::ArtistSeedCatalog :
237
return "artist_seed_catalog";
238
case Echonest::DynamicPlaylist::SourceCatalog :
239
return "seed_catalog";
240
case Echonest::DynamicPlaylist::SongId :
242
case Echonest::DynamicPlaylist::Description :
243
return "description";
244
case Echonest::DynamicPlaylist::Results :
246
case Echonest::DynamicPlaylist::MaxTempo :
248
case Echonest::DynamicPlaylist::MinTempo :
250
case Echonest::DynamicPlaylist::MaxDuration :
251
return "max_duration";
252
case Echonest::DynamicPlaylist::MinDuration :
253
return "min_duration";
254
case Echonest::DynamicPlaylist::MaxLoudness :
255
return "max_loudness";
256
case Echonest::DynamicPlaylist::MinLoudness :
257
return "min_loudness";
258
case Echonest::DynamicPlaylist::ArtistMaxFamiliarity :
259
return "artist_max_familiarity";
260
case Echonest::DynamicPlaylist::ArtistMinFamiliarity :
261
return "artist_min_familiarity";
262
case Echonest::DynamicPlaylist::MinDanceability :
263
return "min_danceability";
264
case Echonest::DynamicPlaylist::MaxDanceability :
265
return "max_danceability";
266
case Echonest::DynamicPlaylist::MinEnergy :
268
case Echonest::DynamicPlaylist::MaxEnergy :
270
case Echonest::DynamicPlaylist::ArtistMaxHotttnesss :
271
return "artist_max_hotttnesss";
272
case Echonest::DynamicPlaylist::ArtistMinHotttnesss :
273
return "artist_min_hotttnesss";
274
case Echonest::DynamicPlaylist::SongMaxHotttnesss :
275
return "song_max_hotttnesss";
276
case Echonest::DynamicPlaylist::SongMinHotttnesss :
277
return "song_min_hotttnesss";
278
case Echonest::DynamicPlaylist::ArtistMinLongitude :
279
return "min_longitude";
280
case Echonest::DynamicPlaylist::ArtistMaxLongitude :
281
return "max_longitude";
282
case Echonest::DynamicPlaylist::ArtistMinLatitude :
283
return "min_latitude";
284
case Echonest::DynamicPlaylist::ArtistMaxLatitude :
285
return "max_latitude";
286
case Echonest::DynamicPlaylist::Mode :
288
case Echonest::DynamicPlaylist::Key :
290
case Echonest::DynamicPlaylist::SongInformation:
292
case Echonest::DynamicPlaylist::Sort :
294
case Echonest::DynamicPlaylist::Limit :
296
case Echonest::DynamicPlaylist::Audio :
298
case Echonest::DynamicPlaylist::DMCA :
300
case Echonest::DynamicPlaylist::ChainXSPF :
302
case Echonest::DynamicPlaylist::Mood :
304
case Echonest::DynamicPlaylist::Style :
306
case Echonest::DynamicPlaylist::Adventurousness :
307
return "adventurousness";
312
QByteArray Echonest::DynamicPlaylist::playlistArtistPickToString(Echonest::DynamicPlaylist::ArtistPick pick)
316
case PickSongHotttnesssAscending:
317
return "song_hotttnesss-asc";
318
case PickTempoAscending:
320
case PickDurationAscending:
321
return "duration-asc";
322
case PickLoudnessAscending:
323
return "loudness-asc";
324
case PickModeAscending:
326
case PickKeyAscending:
328
case PickSongHotttnesssDescending:
329
return "song_hotttnesss-desc";
330
case PickTempoDescending:
332
case PickDurationDescending:
333
return "duration-desc";
334
case PickLoudnessDescending:
335
return "loudness-desc";
336
case PickModeDescending:
338
case PickKeyDescending:
344
QByteArray Echonest::DynamicPlaylist::playlistSortToString(Echonest::DynamicPlaylist::SortingType sorting)
348
case SortTempoAscending:
350
case SortTempoDescending:
352
case SortDurationAscending:
353
return "duration-asc";
354
case SortDurationDescending:
355
return "duration-desc";
356
case SortLoudnessAscending:
357
return "loudness-asc";
358
case SortLoudnessDescending:
359
return "loudness-desc";
360
case SortArtistFamiliarityAscending:
361
return "artist_familiarity-asc";
362
case SortArtistFamiliarityDescending:
363
return "artist_familiarity-desc";
364
case SortArtistHotttnessAscending:
365
return "artist_hotttnesss-asc";
366
case SortArtistHotttnessDescending:
367
return "artist_hotttnesss-desc";
368
case SortSongHotttnesssAscending:
369
return "song_hotttnesss-asc";
370
case SortSongHotttnesssDescending:
371
return "song_hotttnesss-desc";
372
case SortLatitudeAscending:
373
return "latitude-asc";
374
case SortLatitudeDescending:
375
return "latitude-desc";
376
case SortLongitudeAscending:
377
return "longitude-asc";
378
case SortLongitudeDescending:
379
return "longitude-desc";
380
case SortModeAscending:
382
case SortModeDescending:
384
case SortKeyAscending:
386
case SortKeyDescending:
388
case SortEnergyAscending:
390
case SortEnergyDescending:
391
return "energy-desc";
392
case SortDanceabilityAscending:
393
return "danceability-asc";
394
case SortDanceabilityDescending:
395
return "danceability-desc";
400
QByteArray Echonest::DynamicPlaylist::dynamicControlToString(Echonest::DynamicPlaylist::DynamicControlItem control)
406
case SteerDescription:
407
return "steer_description";
418
QDebug Echonest::operator<<(QDebug d, const Echonest::DynamicPlaylist& playlist)
420
d << QString::fromLatin1( "DynamicPlaylist(%1, %2)" ).arg( QLatin1String( playlist.sessionId() ), playlist.currentSong().toString() );
421
return d.maybeSpace();