Update again from master
This commit is contained in:
commit
afda8f7505
1
3rdparty/vreen/CMakeLists.txt
vendored
1
3rdparty/vreen/CMakeLists.txt
vendored
@ -14,6 +14,7 @@ if(NOT VREEN_FOUND)
|
|||||||
if(NOT CMAKE_INSTALL_PREFIX STREQUAL "/usr")
|
if(NOT CMAKE_INSTALL_PREFIX STREQUAL "/usr")
|
||||||
set(VREEN_IMPORTS_DIR bin)
|
set(VREEN_IMPORTS_DIR bin)
|
||||||
endif()
|
endif()
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++0x")
|
||||||
set(VREEN_WITH_QMLAPI OFF CACHE INTERNAL "")
|
set(VREEN_WITH_QMLAPI OFF CACHE INTERNAL "")
|
||||||
set(VREEN_WITH_OAUTH ON CACHE INTERNAL "")
|
set(VREEN_WITH_OAUTH ON CACHE INTERNAL "")
|
||||||
set(VREEN_INSTALL_HEADERS OFF CACHE INTERNAL "")
|
set(VREEN_INSTALL_HEADERS OFF CACHE INTERNAL "")
|
||||||
|
@ -45,7 +45,8 @@ CREATE TABLE jamendo.songs (
|
|||||||
etag TEXT,
|
etag TEXT,
|
||||||
|
|
||||||
performer TEXT,
|
performer TEXT,
|
||||||
grouping TEXT
|
grouping TEXT,
|
||||||
|
lyrics TEXT
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE VIRTUAL TABLE jamendo.songs_fts USING fts3(
|
CREATE VIRTUAL TABLE jamendo.songs_fts USING fts3(
|
||||||
|
@ -65,3 +65,11 @@ void DoInAMinuteOrSo(QObject* receiver, const char* slot) {
|
|||||||
int msec = (60 + (qrand() % 60)) * kMsecPerSec;
|
int msec = (60 + (qrand() % 60)) * kMsecPerSec;
|
||||||
DoAfter(receiver, slot, msec);
|
DoAfter(receiver, slot, msec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DoAfter(std::function<void()> callback, int msec) {
|
||||||
|
QTimer* timer = new QTimer;
|
||||||
|
timer->setSingleShot(true);
|
||||||
|
NewClosure(timer, SIGNAL(timeout()), callback);
|
||||||
|
QObject::connect(timer, SIGNAL(timeout()), timer, SLOT(deleteLater()));
|
||||||
|
timer->start(msec);
|
||||||
|
}
|
||||||
|
@ -188,6 +188,7 @@ _detail::ClosureBase* NewClosure(QObject* sender, const char* signal,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DoAfter(QObject* receiver, const char* slot, int msec);
|
void DoAfter(QObject* receiver, const char* slot, int msec);
|
||||||
|
void DoAfter(std::function<void()> callback, int msec);
|
||||||
void DoInAMinuteOrSo(QObject* receiver, const char* slot);
|
void DoInAMinuteOrSo(QObject* receiver, const char* slot);
|
||||||
|
|
||||||
#endif // CLOSURE_H
|
#endif // CLOSURE_H
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
|
|
||||||
#include "internet/amazon/amazonclouddrive.h"
|
#include "internet/amazon/amazonclouddrive.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
@ -28,13 +31,16 @@
|
|||||||
#include "core/logging.h"
|
#include "core/logging.h"
|
||||||
#include "core/network.h"
|
#include "core/network.h"
|
||||||
#include "core/player.h"
|
#include "core/player.h"
|
||||||
|
#include "core/timeconstants.h"
|
||||||
#include "core/waitforsignal.h"
|
#include "core/waitforsignal.h"
|
||||||
#include "internet/core/oauthenticator.h"
|
#include "internet/core/oauthenticator.h"
|
||||||
#include "internet/amazon/amazonurlhandler.h"
|
#include "internet/amazon/amazonurlhandler.h"
|
||||||
#include "library/librarybackend.h"
|
#include "library/librarybackend.h"
|
||||||
#include "ui/settingsdialog.h"
|
#include "ui/settingsdialog.h"
|
||||||
|
|
||||||
const char* AmazonCloudDrive::kServiceName = "Cloud Drive";
|
using std::placeholders::_1;
|
||||||
|
|
||||||
|
const char* AmazonCloudDrive::kServiceName = "Amazon Cloud Drive";
|
||||||
const char* AmazonCloudDrive::kSettingsGroup = "AmazonCloudDrive";
|
const char* AmazonCloudDrive::kSettingsGroup = "AmazonCloudDrive";
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -127,10 +133,7 @@ void AmazonCloudDrive::ConnectFinished(OAuthenticator* oauth) {
|
|||||||
void AmazonCloudDrive::FetchEndpoint() {
|
void AmazonCloudDrive::FetchEndpoint() {
|
||||||
QUrl url(kEndpointEndpoint);
|
QUrl url(kEndpointEndpoint);
|
||||||
QNetworkRequest request(url);
|
QNetworkRequest request(url);
|
||||||
AddAuthorizationHeader(&request);
|
Get(request, std::bind(&AmazonCloudDrive::FetchEndpointFinished, this, _1));
|
||||||
QNetworkReply* reply = network_->get(request);
|
|
||||||
NewClosure(reply, SIGNAL(finished()), this,
|
|
||||||
SLOT(FetchEndpointFinished(QNetworkReply*)), reply);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmazonCloudDrive::FetchEndpointFinished(QNetworkReply* reply) {
|
void AmazonCloudDrive::FetchEndpointFinished(QNetworkReply* reply) {
|
||||||
@ -139,6 +142,11 @@ void AmazonCloudDrive::FetchEndpointFinished(QNetworkReply* reply) {
|
|||||||
QJsonObject json_response = QJsonDocument::fromJson(reply->readAll()).object();
|
QJsonObject json_response = QJsonDocument::fromJson(reply->readAll()).object();
|
||||||
content_url_ = json_response["contentUrl"].toString();
|
content_url_ = json_response["contentUrl"].toString();
|
||||||
metadata_url_ = json_response["metadataUrl"].toString();
|
metadata_url_ = json_response["metadataUrl"].toString();
|
||||||
|
if (content_url_.isEmpty() || metadata_url_.isEmpty()) {
|
||||||
|
qLog(Debug) << "Couldn't fetch Amazon endpoint";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QSettings s;
|
QSettings s;
|
||||||
s.beginGroup(kSettingsGroup);
|
s.beginGroup(kSettingsGroup);
|
||||||
QString checkpoint = s.value("checkpoint", "").toString();
|
QString checkpoint = s.value("checkpoint", "").toString();
|
||||||
@ -162,10 +170,51 @@ void AmazonCloudDrive::RequestChanges(const QString& checkpoint) {
|
|||||||
QByteArray json = data.toBinaryData();
|
QByteArray json = data.toBinaryData();
|
||||||
|
|
||||||
QNetworkRequest request(url);
|
QNetworkRequest request(url);
|
||||||
|
Post(request, json,
|
||||||
|
std::bind(&AmazonCloudDrive::RequestChangesFinished, this, _1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmazonCloudDrive::Get(QNetworkRequest request,
|
||||||
|
std::function<void(QNetworkReply*)> done,
|
||||||
|
int retries) {
|
||||||
AddAuthorizationHeader(&request);
|
AddAuthorizationHeader(&request);
|
||||||
QNetworkReply* reply = network_->post(request, json);
|
MonitorReply(network_->get(request), done, QByteArray(), retries);
|
||||||
NewClosure(reply, SIGNAL(finished()), this,
|
}
|
||||||
SLOT(RequestChangesFinished(QNetworkReply*)), reply);
|
|
||||||
|
void AmazonCloudDrive::Post(QNetworkRequest request, const QByteArray& data,
|
||||||
|
std::function<void(QNetworkReply*)> done,
|
||||||
|
int retries) {
|
||||||
|
AddAuthorizationHeader(&request);
|
||||||
|
MonitorReply(network_->post(request, data), done, data, retries);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmazonCloudDrive::MonitorReply(QNetworkReply* reply,
|
||||||
|
std::function<void(QNetworkReply*)> done,
|
||||||
|
const QByteArray& post_data, int retries) {
|
||||||
|
NewClosure(reply, SIGNAL(finished()), [=]() {
|
||||||
|
if (reply->error() == QNetworkReply::NoError) {
|
||||||
|
done(reply);
|
||||||
|
} else {
|
||||||
|
int code =
|
||||||
|
reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
if (code >= 500) { // Retry with exponential backoff.
|
||||||
|
int max_delay_s = std::pow(std::min(retries + 1, 8), 2);
|
||||||
|
int delay_s = qrand() % max_delay_s;
|
||||||
|
qLog(Debug) << "Request failed with code:" << code << "- retrying after"
|
||||||
|
<< delay_s << "seconds";
|
||||||
|
DoAfter([=]() {
|
||||||
|
if (post_data.isEmpty()) {
|
||||||
|
Get(reply->request(), done, retries + 1);
|
||||||
|
} else {
|
||||||
|
Post(reply->request(), post_data, done, retries + 1);
|
||||||
|
}
|
||||||
|
}, delay_s * kMsecPerSec);
|
||||||
|
} else {
|
||||||
|
// Request failed permanently.
|
||||||
|
done(reply);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmazonCloudDrive::RequestChangesFinished(QNetworkReply* reply) {
|
void AmazonCloudDrive::RequestChangesFinished(QNetworkReply* reply) {
|
||||||
@ -221,7 +270,8 @@ void AmazonCloudDrive::RequestChangesFinished(QNetworkReply* reply) {
|
|||||||
song.set_title(node["name"].toString());
|
song.set_title(node["name"].toString());
|
||||||
song.set_filesize(content_properties["size"].toInt());
|
song.set_filesize(content_properties["size"].toInt());
|
||||||
|
|
||||||
MaybeAddFileToDatabase(song, mime_type, content_url, QString("Bearer %1").arg(access_token_));
|
MaybeAddFileToDatabase(song, mime_type, content_url,
|
||||||
|
QString("Bearer %1").arg(access_token_));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +54,14 @@ class AmazonCloudDrive : public CloudFileService {
|
|||||||
void RequestChanges(const QString& checkpoint);
|
void RequestChanges(const QString& checkpoint);
|
||||||
void AddAuthorizationHeader(QNetworkRequest* request);
|
void AddAuthorizationHeader(QNetworkRequest* request);
|
||||||
void EnsureConnected();
|
void EnsureConnected();
|
||||||
|
void Get(QNetworkRequest, std::function<void(QNetworkReply*)>,
|
||||||
|
int retries = 0);
|
||||||
|
void Post(QNetworkRequest, const QByteArray& data,
|
||||||
|
std::function<void(QNetworkReply*)>, int retries = 0);
|
||||||
|
void MonitorReply(QNetworkReply* reply,
|
||||||
|
std::function<void(QNetworkReply*)> done,
|
||||||
|
const QByteArray& post_data = QByteArray(),
|
||||||
|
int retries = 0);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void ConnectFinished(OAuthenticator*);
|
void ConnectFinished(OAuthenticator*);
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Amazon</string>
|
<string>Amazon Cloud Drive</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowIcon">
|
<property name="windowIcon">
|
||||||
<iconset resource="../../data/data.qrc">
|
<iconset resource="../../data/data.qrc">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user