diff --git a/data/data.qrc b/data/data.qrc
index d68a182b9..b3cc9f408 100644
--- a/data/data.qrc
+++ b/data/data.qrc
@@ -336,6 +336,7 @@
schema/schema-3.sql
schema/schema-40.sql
schema/schema-41.sql
+ schema/schema-42.sql
schema/schema-4.sql
schema/schema-5.sql
schema/schema-6.sql
diff --git a/data/schema/schema-42.sql b/data/schema/schema-42.sql
new file mode 100644
index 000000000..9c5d954cb
--- /dev/null
+++ b/data/schema/schema-42.sql
@@ -0,0 +1,48 @@
+CREATE TABLE skydrive_songs(
+ title TEXT,
+ album TEXT,
+ artist TEXT,
+ albumartist TEXT,
+ composer TEXT,
+ track INTEGER,
+ disc INTEGER,
+ bpm REAL,
+ year INTEGER,
+ genre TEXT,
+ comment TEXT,
+ compilation INTEGER,
+
+ length INTEGER,
+ bitrate INTEGER,
+ samplerate INTEGER,
+
+ directory INTEGER NOT NULL,
+ filename TEXT NOT NULL,
+ mtime INTEGER NOT NULL,
+ ctime INTEGER NOT NULL,
+ filesize INTEGER NOT NULL,
+ sampler INTEGER NOT NULL DEFAULT 0,
+ art_automatic TEXT,
+ art_manual TEXT,
+ filetype INTEGER NOT NULL DEFAULT 0,
+ playcount INTEGER NOT NULL DEFAULT 0,
+ lastplayed INTEGER,
+ rating INTEGER,
+ forced_compilation_on INTEGER NOT NULL DEFAULT 0,
+ forced_compilation_off INTEGER NOT NULL DEFAULT 0,
+ effective_compilation NOT NULL DEFAULT 0,
+ skipcount INTEGER NOT NULL DEFAULT 0,
+ score INTEGER NOT NULL DEFAULT 0,
+ beginning INTEGER NOT NULL DEFAULT 0,
+ cue_path TEXT,
+ unavailable INTEGER DEFAULT 0,
+ effective_albumartist TEXT,
+ etag TEXT
+);
+
+CREATE VIRTUAL TABLE skydrive_songs_fts USING fts3 (
+ ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsgenre, ftscomment,
+ tokenize=unicode
+);
+
+UPDATE schema_version SET version=42;
diff --git a/ext/clementine-tagreader/cloudstream.cpp b/ext/clementine-tagreader/cloudstream.cpp
index 86ad2ae22..100174cca 100644
--- a/ext/clementine-tagreader/cloudstream.cpp
+++ b/ext/clementine-tagreader/cloudstream.cpp
@@ -110,7 +110,7 @@ TagLib::ByteVector CloudStream::readBlock(ulong length) {
}
QNetworkRequest request = QNetworkRequest(url_);
- if (!auth_.isNull()) {
+ if (!auth_.isEmpty()) {
request.setRawHeader("Authorization", auth_.toUtf8());
}
request.setRawHeader(
diff --git a/src/core/database.cpp b/src/core/database.cpp
index 58d410fe9..c30b2362f 100644
--- a/src/core/database.cpp
+++ b/src/core/database.cpp
@@ -37,7 +37,7 @@
#include
const char* Database::kDatabaseFilename = "clementine.db";
-const int Database::kSchemaVersion = 41;
+const int Database::kSchemaVersion = 42;
const char* Database::kMagicAllSongsTables = "%allsongstables";
int Database::sNextConnectionId = 1;
diff --git a/src/internet/cloudfileservice.cpp b/src/internet/cloudfileservice.cpp
index 0f6273b29..c48c12768 100644
--- a/src/internet/cloudfileservice.cpp
+++ b/src/internet/cloudfileservice.cpp
@@ -180,3 +180,18 @@ bool CloudFileService::IsSupportedMimeType(const QString& mime_type) const {
mime_type == "application/x-flac" ||
mime_type == "audio/x-ms-wma";
}
+
+QString CloudFileService::GuessMimeTypeForFile(const QString& filename) const {
+ if (filename.endsWith(".mp3")) {
+ return "audio/mpeg";
+ } else if (filename.endsWith(".m4a")) {
+ return "audio/mpeg";
+ } else if (filename.endsWith(".ogg")) {
+ return "application/ogg";
+ } else if (filename.endsWith(".flac")) {
+ return "application/x-flac";
+ } else if (filename.endsWith(".wma")) {
+ return "audio/x-ms-wma";
+ }
+ return QString::null;
+}
diff --git a/src/internet/cloudfileservice.h b/src/internet/cloudfileservice.h
index 5c6f9dbdc..ef3627cc5 100644
--- a/src/internet/cloudfileservice.h
+++ b/src/internet/cloudfileservice.h
@@ -41,6 +41,7 @@ class CloudFileService : public InternetService {
const QUrl& download_url,
const QString& authorisation);
virtual bool IsSupportedMimeType(const QString& mime_type) const;
+ QString GuessMimeTypeForFile(const QString& filename) const;
protected slots:
diff --git a/src/internet/skydriveservice.cpp b/src/internet/skydriveservice.cpp
index 6f490e60a..838645b6e 100644
--- a/src/internet/skydriveservice.cpp
+++ b/src/internet/skydriveservice.cpp
@@ -1,5 +1,7 @@
#include "skydriveservice.h"
+#include
+
#include "oauthenticator.h"
namespace {
@@ -17,6 +19,9 @@ static const char* kOAuthTokenEndpoint =
"https://login.live.com/oauth20_token.srf";
static const char* kOAuthScope = "wl.basic wl.skydrive wl.offline_access";
+static const char* kLiveUserInfo = "https://apis.live.net/v5.0/me";
+static const char* kSkydriveBase = "https://apis.live.net/v5.0/";
+
} // namespace
SkydriveService::SkydriveService(
@@ -51,11 +56,89 @@ void SkydriveService::Connect() {
}
void SkydriveService::ConnectFinished(OAuthenticator* oauth) {
- qLog(Debug) << oauth->access_token()
- << oauth->refresh_token();
+ oauth->deleteLater();
QSettings s;
s.beginGroup(kSettingsGroup);
-
s.setValue("refresh_token", oauth->refresh_token());
+
+ access_token_ = oauth->access_token();
+ expiry_time_ = oauth->expiry_time();
+
+ QUrl url(kLiveUserInfo);
+ QNetworkRequest request(url);
+ AddAuthorizationHeader(&request);
+
+ QNetworkReply* reply = network_->get(request);
+ NewClosure(reply, SIGNAL(finished()),
+ this, SLOT(FetchUserInfoFinished(QNetworkReply*)), reply);
+}
+
+void SkydriveService::AddAuthorizationHeader(QNetworkRequest* request) {
+ request->setRawHeader(
+ "Authorization", QString("Bearer %1").arg(access_token_).toUtf8());
+}
+
+void SkydriveService::FetchUserInfoFinished(QNetworkReply* reply) {
+ reply->deleteLater();
+ QJson::Parser parser;
+ QVariantMap response = parser.parse(reply).toMap();
+ qLog(Debug) << response;
+
+ QString name = response["name"].toString();
+ if (!name.isEmpty()) {
+ QSettings s;
+ s.beginGroup(kSettingsGroup);
+ s.setValue("name", name);
+ }
+
+ ListFiles("me/skydrive");
+}
+
+void SkydriveService::ListFiles(const QString& folder) {
+ QUrl url(QString(kSkydriveBase) + folder + "/files");
+ url.addQueryItem("filter", "audio,folders");
+ QNetworkRequest request(url);
+ AddAuthorizationHeader(&request);
+
+ QNetworkReply* reply = network_->get(request);
+ NewClosure(reply, SIGNAL(finished()),
+ this, SLOT(ListFilesFinished(QNetworkReply*)), reply);
+}
+
+void SkydriveService::ListFilesFinished(QNetworkReply* reply) {
+ reply->deleteLater();
+ QJson::Parser parser;
+ QVariantMap response = parser.parse(reply).toMap();
+ qLog(Debug) << response;
+
+ QVariantList files = response["data"].toList();
+ foreach (const QVariant& f, files) {
+ QVariantMap file = f.toMap();
+ if (file["type"].toString() == "audio") {
+ QString mime_type = GuessMimeTypeForFile(file["name"].toString());
+ QUrl url;
+ url.setScheme("skydrive");
+ url.setPath(file["id"].toString());
+
+ Song song;
+ song.set_url(url);
+ song.set_ctime(file["created_time"].toDateTime().toTime_t());
+ song.set_mtime(file["updated_time"].toDateTime().toTime_t());
+ song.set_comment(file["description"].toString());
+ song.set_filesize(file["size"].toInt());
+ song.set_title(file["name"].toString());
+
+ QUrl download_url = file["source"].toUrl();
+ // HTTPS appears to be broken somehow between Qt & Skydrive downloads.
+ // Fortunately, just changing the scheme to HTTP works.
+ download_url.setScheme("http");
+ MaybeAddFileToDatabase(
+ song,
+ mime_type,
+ download_url,
+ QString::null);
+
+ }
+ }
}
diff --git a/src/internet/skydriveservice.h b/src/internet/skydriveservice.h
index 190ecc457..a6b0245ac 100644
--- a/src/internet/skydriveservice.h
+++ b/src/internet/skydriveservice.h
@@ -3,7 +3,11 @@
#include "cloudfileservice.h"
+#include
+
class OAuthenticator;
+class QNetworkRequest;
+class QNetworkReply;
class SkydriveService : public CloudFileService {
Q_OBJECT
@@ -20,7 +24,15 @@ class SkydriveService : public CloudFileService {
private slots:
void ConnectFinished(OAuthenticator* oauth);
+ void FetchUserInfoFinished(QNetworkReply* reply);
+ void ListFilesFinished(QNetworkReply* reply);
+ private:
+ void AddAuthorizationHeader(QNetworkRequest* request);
+ void ListFiles(const QString& folder);
+
+ QString access_token_;
+ QDateTime expiry_time_;
};
#endif // SKYDRIVESERVICE_H
diff --git a/src/internet/ubuntuoneservice.cpp b/src/internet/ubuntuoneservice.cpp
index cc0266c89..d9718e23d 100644
--- a/src/internet/ubuntuoneservice.cpp
+++ b/src/internet/ubuntuoneservice.cpp
@@ -128,25 +128,6 @@ void UbuntuOneService::RequestFileList(const QString& path) {
this, SLOT(FileListRequestFinished(QNetworkReply*)), files_reply);
}
-namespace {
-
-QString GuessMimeTypeForFile(const QString& filename) {
- if (filename.endsWith(".mp3")) {
- return "audio/mpeg";
- } else if (filename.endsWith(".m4a")) {
- return "audio/mpeg";
- } else if (filename.endsWith(".ogg")) {
- return "application/ogg";
- } else if (filename.endsWith(".flac")) {
- return "application/x-flac";
- } else if (filename.endsWith(".wma")) {
- return "audio/x-ms-wma";
- }
- return QString::null;
-}
-
-} // namespace
-
void UbuntuOneService::FileListRequestFinished(QNetworkReply* reply) {
reply->deleteLater();
QJson::Parser parser;