2011-11-28 20:07:18 +01:00
|
|
|
/* This file is part of Clementine.
|
|
|
|
Copyright 2011, David Sansome <me@davidsansome.com>
|
|
|
|
|
|
|
|
Clementine is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Clementine is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2010-11-26 16:16:48 +01:00
|
|
|
#include "jamendodynamicplaylist.h"
|
|
|
|
|
2011-07-15 15:27:50 +02:00
|
|
|
#include "jamendoplaylistitem.h"
|
|
|
|
#include "jamendoservice.h"
|
|
|
|
|
2010-11-26 16:16:48 +01:00
|
|
|
#include <QEventLoop>
|
2010-11-27 19:37:53 +01:00
|
|
|
#include <QHttp>
|
|
|
|
#include <QHttpRequestHeader>
|
2010-11-26 17:03:13 +01:00
|
|
|
#include <QtDebug>
|
2010-11-26 16:16:48 +01:00
|
|
|
|
2011-04-22 18:50:29 +02:00
|
|
|
#include "core/logging.h"
|
2010-11-26 16:16:48 +01:00
|
|
|
#include "core/network.h"
|
|
|
|
#include "library/librarybackend.h"
|
|
|
|
|
2010-11-27 17:14:09 +01:00
|
|
|
const char* JamendoDynamicPlaylist::kUrl =
|
|
|
|
"http://api.jamendo.com/get2/id/track/plain/";
|
2010-11-26 16:16:48 +01:00
|
|
|
|
|
|
|
JamendoDynamicPlaylist::JamendoDynamicPlaylist()
|
2010-11-27 17:14:09 +01:00
|
|
|
: order_by_(OrderBy_Rating),
|
|
|
|
order_direction_(Order_Descending),
|
2010-11-26 16:16:48 +01:00
|
|
|
current_page_(0),
|
|
|
|
current_index_(0) {
|
2010-11-27 18:52:08 +01:00
|
|
|
}
|
2010-11-26 16:16:48 +01:00
|
|
|
|
2010-11-27 18:52:08 +01:00
|
|
|
JamendoDynamicPlaylist::JamendoDynamicPlaylist(const QString& name, OrderBy order_by)
|
|
|
|
: order_by_(order_by),
|
|
|
|
order_direction_(Order_Descending),
|
|
|
|
current_page_(0),
|
|
|
|
current_index_(0) {
|
|
|
|
set_name(name);
|
2010-11-26 16:16:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void JamendoDynamicPlaylist::Load(const QByteArray& data) {
|
2010-11-27 17:14:09 +01:00
|
|
|
QDataStream s(data);
|
|
|
|
s >> *this;
|
|
|
|
}
|
2010-11-26 16:16:48 +01:00
|
|
|
|
2010-11-27 17:14:09 +01:00
|
|
|
void JamendoDynamicPlaylist::Load(OrderBy order_by, OrderDirection order_direction) {
|
|
|
|
order_by_ = order_by;
|
|
|
|
order_direction_ = order_direction;
|
2010-11-26 16:16:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
QByteArray JamendoDynamicPlaylist::Save() const {
|
2010-11-27 17:14:09 +01:00
|
|
|
QByteArray ret;
|
|
|
|
QDataStream s(&ret, QIODevice::WriteOnly);
|
|
|
|
s << *this;
|
|
|
|
|
|
|
|
return ret;
|
2010-11-26 16:16:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
PlaylistItemList JamendoDynamicPlaylist::Generate() {
|
|
|
|
return GenerateMore(20);
|
|
|
|
}
|
|
|
|
|
|
|
|
PlaylistItemList JamendoDynamicPlaylist::GenerateMore(int count) {
|
2010-11-27 18:52:08 +01:00
|
|
|
int tries = 0;
|
|
|
|
|
2010-11-26 16:16:48 +01:00
|
|
|
PlaylistItemList items;
|
2010-11-27 18:52:08 +01:00
|
|
|
while (items.size() < count && tries++ < kApiRetryLimit) {
|
2010-11-26 16:16:48 +01:00
|
|
|
// Add items from current list.
|
|
|
|
if (current_index_ < current_items_.size()) {
|
|
|
|
PlaylistItemList more_items = current_items_.mid(current_index_, count);
|
|
|
|
items << more_items;
|
|
|
|
current_index_ += more_items.size();
|
|
|
|
} else {
|
|
|
|
// We need more songs!
|
|
|
|
Fetch();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return items;
|
|
|
|
}
|
|
|
|
|
2010-11-27 17:14:09 +01:00
|
|
|
QString JamendoDynamicPlaylist::OrderSpec(OrderBy by, OrderDirection dir) {
|
|
|
|
QString ret;
|
|
|
|
switch (by) {
|
|
|
|
case OrderBy_Listened: ret += "listened"; break;
|
|
|
|
case OrderBy_Rating: ret += "rating"; break;
|
|
|
|
case OrderBy_RatingMonth: ret += "ratingmonth"; break;
|
|
|
|
case OrderBy_RatingWeek: ret += "ratingweek"; break;
|
|
|
|
}
|
|
|
|
switch (dir) {
|
|
|
|
case Order_Ascending: ret += "_asc"; break;
|
|
|
|
case Order_Descending: ret += "_desc"; break;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-11-26 16:16:48 +01:00
|
|
|
void JamendoDynamicPlaylist::Fetch() {
|
2010-11-27 17:14:09 +01:00
|
|
|
QUrl url(kUrl);
|
2010-11-26 16:16:48 +01:00
|
|
|
url.addQueryItem("pn", QString::number(current_page_++));
|
|
|
|
url.addQueryItem("n", QString::number(kPageSize));
|
2010-11-27 17:14:09 +01:00
|
|
|
url.addQueryItem("order", OrderSpec(order_by_, order_direction_));
|
2010-11-26 16:16:48 +01:00
|
|
|
|
2010-11-27 19:37:53 +01:00
|
|
|
// We have to use QHttp here because there's no way to disable Keep-Alive
|
|
|
|
// with QNetworkManager.
|
|
|
|
QHttpRequestHeader header("GET", url.encodedPath() + "?" + url.encodedQuery());
|
|
|
|
header.setValue("Host", url.encodedHost());
|
2010-11-27 18:52:08 +01:00
|
|
|
|
2010-11-27 19:37:53 +01:00
|
|
|
QHttp http(url.host());
|
|
|
|
http.request(header);
|
2010-11-26 16:16:48 +01:00
|
|
|
|
2010-11-27 19:37:53 +01:00
|
|
|
// Wait for the reply
|
2010-11-26 16:16:48 +01:00
|
|
|
{
|
|
|
|
QEventLoop event_loop;
|
2010-11-27 19:37:53 +01:00
|
|
|
connect(&http, SIGNAL(requestFinished(int,bool)), &event_loop, SLOT(quit()));
|
2010-11-26 16:16:48 +01:00
|
|
|
event_loop.exec();
|
|
|
|
}
|
|
|
|
|
2010-11-27 19:37:53 +01:00
|
|
|
if (http.error() != QHttp::NoError) {
|
2011-04-22 18:50:29 +02:00
|
|
|
qLog(Warning) << "HTTP error returned from Jamendo:" << http.errorString()
|
2010-11-27 19:37:53 +01:00
|
|
|
<< ", url:" << url.toString();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-11-27 17:14:09 +01:00
|
|
|
// The reply will contain one track ID per line
|
2010-11-27 19:37:53 +01:00
|
|
|
QStringList lines = QString::fromAscii(http.readAll()).split('\n');
|
2010-11-27 17:14:09 +01:00
|
|
|
|
|
|
|
// Get the songs from the database
|
|
|
|
SongList songs = backend_->GetSongsByForeignId(
|
|
|
|
lines, JamendoService::kTrackIdsTable, JamendoService::kTrackIdsColumn);
|
2010-11-27 18:52:08 +01:00
|
|
|
|
2010-11-26 16:16:48 +01:00
|
|
|
if (songs.empty()) {
|
2011-04-22 18:50:29 +02:00
|
|
|
qLog(Warning) << "No songs returned from Jamendo:"
|
2010-11-27 17:14:09 +01:00
|
|
|
<< url.toString();
|
2010-11-26 16:16:48 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
current_items_.clear();
|
|
|
|
foreach (const Song& song, songs) {
|
2010-11-27 17:14:09 +01:00
|
|
|
if (song.is_valid())
|
|
|
|
current_items_ << PlaylistItemPtr(new JamendoPlaylistItem(song));
|
2010-11-26 16:16:48 +01:00
|
|
|
}
|
|
|
|
current_index_ = 0;
|
|
|
|
}
|
2010-11-27 17:14:09 +01:00
|
|
|
|
|
|
|
QDataStream& operator <<(QDataStream& s, const JamendoDynamicPlaylist& p) {
|
|
|
|
s << quint8(p.order_by_) << quint8(p.order_direction_);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
QDataStream& operator >>(QDataStream& s, JamendoDynamicPlaylist& p) {
|
|
|
|
quint8 order_by, order_direction;
|
|
|
|
s >> order_by >> order_direction;
|
|
|
|
p.order_by_ = JamendoDynamicPlaylist::OrderBy(order_by);
|
|
|
|
p.order_direction_ = JamendoDynamicPlaylist::OrderDirection(order_direction);
|
|
|
|
return s;
|
|
|
|
}
|