From 948140fab56f593e60b3f623bda5ba1c97f2d6ab Mon Sep 17 00:00:00 2001
From: Valeriy
Date: Wed, 11 May 2016 17:58:12 +0300
Subject: [PATCH 01/66] disconnect GVolumeMonitor signals from GioLister before
destroying it fixes #5369
---
src/core/signalchecker.cpp | 9 ++++-----
src/core/signalchecker.h | 6 +++---
src/devices/giolister.cpp | 18 +++++++++++++-----
src/devices/giolister.h | 2 ++
4 files changed, 22 insertions(+), 13 deletions(-)
diff --git a/src/core/signalchecker.cpp b/src/core/signalchecker.cpp
index 20767f284..2b0505638 100644
--- a/src/core/signalchecker.cpp
+++ b/src/core/signalchecker.cpp
@@ -21,7 +21,7 @@
#include "core/logging.h"
-bool CheckedGConnect(gpointer source, const char* signal, GCallback callback,
+gulong CheckedGConnect(gpointer source, const char* signal, GCallback callback,
gpointer data, const int callback_param_count) {
guint signal_id = 0;
GQuark detail = 0;
@@ -29,7 +29,7 @@ bool CheckedGConnect(gpointer source, const char* signal, GCallback callback,
if (!g_signal_parse_name(signal, G_OBJECT_TYPE(source), &signal_id, &detail,
false)) {
qFatal("Connecting to invalid signal: %s", signal);
- return false;
+ return 0;
}
GSignalQuery query;
@@ -39,9 +39,8 @@ bool CheckedGConnect(gpointer source, const char* signal, GCallback callback,
int signal_params = query.n_params + 2;
if (signal_params != callback_param_count) {
qFatal("Connecting callback to signal with different parameters counts");
- return false;
+ return 0;
}
- g_signal_connect(source, signal, G_CALLBACK(callback), data);
- return true;
+ return g_signal_connect(source, signal, G_CALLBACK(callback), data);
}
diff --git a/src/core/signalchecker.h b/src/core/signalchecker.h
index 75977e6f5..79b6b5364 100644
--- a/src/core/signalchecker.h
+++ b/src/core/signalchecker.h
@@ -25,14 +25,14 @@
#include
// Do not call this directly, use CHECKED_GCONNECT instead.
-bool CheckedGConnect(gpointer source, const char* signal, GCallback callback,
- gpointer data, const int callback_param_count);
+gulong CheckedGConnect(gpointer source, const char* signal, GCallback callback,
+ gpointer data, const int callback_param_count);
#define FUNCTION_ARITY(callback) \
boost::function_types::function_arity::value
#define CHECKED_GCONNECT(source, signal, callback, data) \
CheckedGConnect(source, signal, G_CALLBACK(callback), data, \
- FUNCTION_ARITY(callback));
+ FUNCTION_ARITY(callback))
#endif // CORE_SIGNALCHECKER_H_
diff --git a/src/devices/giolister.cpp b/src/devices/giolister.cpp
index 1979f189c..d48cc4806 100644
--- a/src/devices/giolister.cpp
+++ b/src/devices/giolister.cpp
@@ -94,11 +94,19 @@ void GioLister::Init() {
g_list_free(mounts);
// Connect signals from the monitor
- CHECKED_GCONNECT(monitor_, "volume-added", &VolumeAddedCallback, this);
- CHECKED_GCONNECT(monitor_, "volume-removed", &VolumeRemovedCallback, this);
- CHECKED_GCONNECT(monitor_, "mount-added", &MountAddedCallback, this);
- CHECKED_GCONNECT(monitor_, "mount-changed", &MountChangedCallback, this);
- CHECKED_GCONNECT(monitor_, "mount-removed", &MountRemovedCallback, this);
+ signals_.append(CHECKED_GCONNECT(monitor_, "volume-added", &VolumeAddedCallback, this));
+ signals_.append(CHECKED_GCONNECT(monitor_, "volume-removed", &VolumeRemovedCallback, this));
+ signals_.append(CHECKED_GCONNECT(monitor_, "mount-added", &MountAddedCallback, this));
+ signals_.append(CHECKED_GCONNECT(monitor_, "mount-changed", &MountChangedCallback, this));
+ signals_.append(CHECKED_GCONNECT(monitor_, "mount-removed", &MountRemovedCallback, this));
+}
+
+GioLister::~GioLister()
+{
+ foreach(gulong signal, signals_)
+ {
+ g_signal_handler_disconnect(monitor_, signal);
+ }
}
QStringList GioLister::DeviceUniqueIDs() {
diff --git a/src/devices/giolister.h b/src/devices/giolister.h
index eafa69dc6..c01680bb2 100644
--- a/src/devices/giolister.h
+++ b/src/devices/giolister.h
@@ -36,6 +36,7 @@ class GioLister : public DeviceLister {
public:
GioLister() {}
+ ~GioLister();
int priority() const { return 50; }
@@ -137,6 +138,7 @@ class GioLister : public DeviceLister {
private:
ScopedGObject monitor_;
+ QList signals_;
QMutex mutex_;
QMap devices_;
From 806e689d1d4a10ca4012ccfcc770dd7fe98b0107 Mon Sep 17 00:00:00 2001
From: Valeriy
Date: Wed, 11 May 2016 19:00:30 +0300
Subject: [PATCH 02/66] replace foreach with range-based for
---
src/devices/giolister.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/devices/giolister.cpp b/src/devices/giolister.cpp
index d48cc4806..f1a776bc0 100644
--- a/src/devices/giolister.cpp
+++ b/src/devices/giolister.cpp
@@ -103,7 +103,7 @@ void GioLister::Init() {
GioLister::~GioLister()
{
- foreach(gulong signal, signals_)
+ for (gulong signal : signals_)
{
g_signal_handler_disconnect(monitor_, signal);
}
From bcf29dc6707e55f7b82f244f05ef5fbd2e008f6b Mon Sep 17 00:00:00 2001
From: Mark Furneaux
Date: Sun, 15 May 2016 13:31:00 -0400
Subject: [PATCH 03/66] Fix caps on audio pipeline
Fixes #1747
The pipeline has the caps for the analyzer applied in the wrong place. This results in the audio output being limited to 16 bit regardless of the input file.
This change also cleans up the mono/sample rate caps as well.
---
src/engines/gstenginepipeline.cpp | 45 ++++++++++++++-----------------
1 file changed, 20 insertions(+), 25 deletions(-)
diff --git a/src/engines/gstenginepipeline.cpp b/src/engines/gstenginepipeline.cpp
index 2340fc513..a6e270f4b 100644
--- a/src/engines/gstenginepipeline.cpp
+++ b/src/engines/gstenginepipeline.cpp
@@ -393,13 +393,7 @@ bool GstEnginePipeline::Init() {
}
gst_element_link_many(queue_, audioconvert_, convert_sink, nullptr);
-
- // Link the elements with special caps
- // The scope path through the tee gets 16-bit ints.
- GstCaps* caps16 = gst_caps_new_simple("audio/x-raw", "format", G_TYPE_STRING,
- "S16LE", NULL);
- gst_element_link_filtered(probe_converter, probe_sink, caps16);
- gst_caps_unref(caps16);
+ gst_element_link(probe_converter, probe_sink);
// Link the outputs of tee to the queues on each path.
gst_pad_link(gst_element_get_request_pad(tee, "src_%u"),
@@ -412,31 +406,32 @@ bool GstEnginePipeline::Init() {
gst_element_link_many(rgvolume_, rglimiter_, audioconvert2_, tee, nullptr);
}
- // Link everything else.
- gst_element_link(probe_queue, probe_converter);
+ // Link the analyzer output of the tee and force 16 bit caps
+ GstCaps* caps16 = gst_caps_new_simple("audio/x-raw", "format", G_TYPE_STRING,
+ "S16LE", NULL);
+ gst_element_link_filtered(probe_queue, probe_converter, caps16);
+ gst_caps_unref(caps16);
+
gst_element_link_many(audio_queue, equalizer_preamp_, equalizer_,
stereo_panorama_, volume_, audioscale_, convert,
nullptr);
- // add caps for fixed sample rate and mono, but only if requested
- if (sample_rate_ != GstEngine::kAutoSampleRate && sample_rate_ > 0) {
- GstCaps* caps = gst_caps_new_simple("audio/x-raw", "rate", G_TYPE_INT,
- sample_rate_, nullptr);
- if (mono_playback_) {
- gst_caps_set_simple(caps, "channels", G_TYPE_INT, 1, nullptr);
- }
+ // Ensure that the audio output of the tee does not autonegotiate to 16 bit
+ GstCaps* caps = gst_caps_new_simple("audio/x-raw", "format", G_TYPE_STRING,
+ "F32LE", NULL);
- gst_element_link_filtered(convert, audiosink_, caps);
- gst_caps_unref(caps);
- } else if (mono_playback_) {
- GstCaps* capsmono =
- gst_caps_new_simple("audio/x-raw", "channels", G_TYPE_INT, 1, nullptr);
- gst_element_link_filtered(convert, audiosink_, capsmono);
- gst_caps_unref(capsmono);
- } else {
- gst_element_link(convert, audiosink_);
+ // Add caps for fixed sample rate and mono, but only if requested
+ if (sample_rate_ != GstEngine::kAutoSampleRate && sample_rate_ > 0) {
+ gst_caps_set_simple(caps, "rate", G_TYPE_INT, sample_rate_, nullptr);
}
+ if (mono_playback_) {
+ gst_caps_set_simple(caps, "channels", G_TYPE_INT, 1, nullptr);
+ }
+
+ gst_element_link_filtered(convert, audiosink_, caps);
+ gst_caps_unref(caps);
+
// Add probes and handlers.
gst_pad_add_probe(gst_element_get_static_pad(probe_converter, "src"),
GST_PAD_PROBE_TYPE_BUFFER, HandoffCallback, this, nullptr);
From 0beb6d3c599b22eb926ee7dfee18a0da80559e86 Mon Sep 17 00:00:00 2001
From: John Maguire
Date: Mon, 16 May 2016 18:00:10 +0100
Subject: [PATCH 04/66] Remove support for Amazon Cloud Drive.
---
CMakeLists.txt | 5 -
src/CMakeLists.txt | 15 --
src/engines/gstenginepipeline.cpp | 9 -
src/internet/amazon/amazonclouddrive.cpp | 299 ---------------------
src/internet/amazon/amazonclouddrive.h | 79 ------
src/internet/amazon/amazonsettingspage.cpp | 83 ------
src/internet/amazon/amazonsettingspage.h | 53 ----
src/internet/amazon/amazonsettingspage.ui | 103 -------
src/internet/amazon/amazonurlhandler.cpp | 28 --
src/internet/amazon/amazonurlhandler.h | 40 ---
src/internet/core/internetmodel.cpp | 6 -
src/ui/settingsdialog.cpp | 4 -
12 files changed, 724 deletions(-)
delete mode 100644 src/internet/amazon/amazonclouddrive.cpp
delete mode 100644 src/internet/amazon/amazonclouddrive.h
delete mode 100644 src/internet/amazon/amazonsettingspage.cpp
delete mode 100644 src/internet/amazon/amazonsettingspage.h
delete mode 100644 src/internet/amazon/amazonsettingspage.ui
delete mode 100644 src/internet/amazon/amazonurlhandler.cpp
delete mode 100644 src/internet/amazon/amazonurlhandler.h
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6da158efd..563100425 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -216,11 +216,6 @@ optional_component(SEAFILE ON "Seafile support"
DEPENDS "Taglib 1.8" "TAGLIB_VERSION VERSION_GREATER 1.7.999"
)
-optional_component(AMAZON_CLOUD_DRIVE OFF "Amazon Cloud Drive support"
- DEPENDS "Google sparsehash" SPARSEHASH_INCLUDE_DIRS
- DEPENDS "Taglib 1.8" "TAGLIB_VERSION VERSION_GREATER 1.7.999"
-)
-
optional_component(AUDIOCD ON "Devices: Audio CD support"
DEPENDS "libcdio" CDIO_FOUND
)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4f0832b5b..91ca559f8 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1164,21 +1164,6 @@ optional_source(HAVE_SEAFILE
internet/seafile/seafilesettingspage.ui
)
-# Amazon Cloud Drive support
-optional_source(HAVE_AMAZON_CLOUD_DRIVE
- SOURCES
- internet/amazon/amazonclouddrive.cpp
- internet/amazon/amazonsettingspage.cpp
- internet/amazon/amazonurlhandler.cpp
- HEADERS
- internet/amazon/amazonclouddrive.h
- internet/amazon/amazonsettingspage.h
- internet/amazon/amazonurlhandler.h
- UI
- internet/amazon/amazonsettingspage.ui
-)
-
-
# Pulse audio integration
optional_source(HAVE_LIBPULSE
INCLUDE_DIRECTORIES
diff --git a/src/engines/gstenginepipeline.cpp b/src/engines/gstenginepipeline.cpp
index a6e270f4b..dbf32ee3e 100644
--- a/src/engines/gstenginepipeline.cpp
+++ b/src/engines/gstenginepipeline.cpp
@@ -971,15 +971,6 @@ void GstEnginePipeline::SourceSetupCallback(GstURIDecodeBin* bin,
g_object_set(element, "device",
instance->source_device().toLocal8Bit().constData(), nullptr);
}
- if (g_object_class_find_property(G_OBJECT_GET_CLASS(element),
- "extra-headers") &&
- instance->url().host().contains("amazonaws.com")) {
- GstStructure* headers =
- gst_structure_new("extra-headers", "Authorization", G_TYPE_STRING,
- instance->url().fragment().toAscii().data(), nullptr);
- g_object_set(element, "extra-headers", headers, nullptr);
- gst_structure_free(headers);
- }
if (g_object_class_find_property(G_OBJECT_GET_CLASS(element), "user-agent")) {
QString user_agent =
diff --git a/src/internet/amazon/amazonclouddrive.cpp b/src/internet/amazon/amazonclouddrive.cpp
deleted file mode 100644
index c4b4b8722..000000000
--- a/src/internet/amazon/amazonclouddrive.cpp
+++ /dev/null
@@ -1,299 +0,0 @@
-/* This file is part of Clementine.
- Copyright 2015, John Maguire
-
- 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 .
-*/
-
-#include "internet/amazon/amazonclouddrive.h"
-
-#include
-#include
-
-#include
-#include
-
-#include
-#include
-
-#include "core/application.h"
-#include "core/closure.h"
-#include "core/logging.h"
-#include "core/network.h"
-#include "core/player.h"
-#include "core/timeconstants.h"
-#include "core/waitforsignal.h"
-#include "internet/core/oauthenticator.h"
-#include "internet/amazon/amazonurlhandler.h"
-#include "library/librarybackend.h"
-#include "ui/settingsdialog.h"
-#include "ui/iconloader.h"
-
-using std::chrono::seconds;
-using std::placeholders::_1;
-
-const char* AmazonCloudDrive::kServiceName = "Amazon Cloud Drive";
-const char* AmazonCloudDrive::kSettingsGroup = "AmazonCloudDrive";
-
-namespace {
-static const char* kServiceId = "amazon_cloud_drive";
-static const char* kClientId =
- "amzn1.application-oa2-client.2b1157a7dadc45c3888567882b3a9f05";
-static const char* kClientSecret =
- "acfbf95340cc4c381dd43fb75b5e111882d7fd1b02a02f3013ab124baf8d1655";
-static const char* kOAuthScope = "clouddrive:read";
-static const char* kOAuthEndpoint = "https://www.amazon.com/ap/oa";
-static const char* kOAuthTokenEndpoint = "https://api.amazon.com/auth/o2/token";
-
-static const char* kEndpointEndpoint =
- "https://drive.amazonaws.com/drive/v1/account/endpoint";
-static const char* kChangesEndpoint = "%1/changes";
-static const char* kDownloadEndpoint = "%1/nodes/%2/content";
-} // namespace
-
-AmazonCloudDrive::AmazonCloudDrive(Application* app, InternetModel* parent)
- : CloudFileService(app, parent, kServiceName, kServiceId,
- IconLoader::Load("amazonclouddrive", IconLoader::Provider),
- SettingsDialog::Page_AmazonCloudDrive),
- network_(new NetworkAccessManager(this)) {
- app->player()->RegisterUrlHandler(new AmazonUrlHandler(this, this));
-}
-
-bool AmazonCloudDrive::has_credentials() const {
- QSettings s;
- s.beginGroup(kSettingsGroup);
- return !s.value("refresh_token").toString().isEmpty();
-}
-
-QUrl AmazonCloudDrive::GetStreamingUrlFromSongId(const QUrl& url) {
- EnsureConnected(); // Access token must be up to date.
- QUrl download_url(
- QString(kDownloadEndpoint).arg(content_url_).arg(url.path()));
- download_url.setFragment(QString("Bearer %1").arg(access_token_));
- return download_url;
-}
-
-void AmazonCloudDrive::Connect() {
- OAuthenticator* oauth = new OAuthenticator(
- kClientId, kClientSecret,
- // Amazon forbids arbitrary query parameters so REMOTE_WITH_STATE is
- // required.
- OAuthenticator::RedirectStyle::REMOTE_WITH_STATE, this);
-
- QSettings s;
- s.beginGroup(kSettingsGroup);
- QString refresh_token = s.value("refresh_token").toString();
- if (refresh_token.isEmpty()) {
- oauth->StartAuthorisation(kOAuthEndpoint, kOAuthTokenEndpoint, kOAuthScope);
- } else {
- oauth->RefreshAuthorisation(kOAuthTokenEndpoint, refresh_token);
- }
-
- NewClosure(oauth, SIGNAL(Finished()), this,
- SLOT(ConnectFinished(OAuthenticator*)), oauth);
-}
-
-void AmazonCloudDrive::EnsureConnected() {
- if (access_token_.isEmpty() ||
- QDateTime::currentDateTime().secsTo(expiry_time_) < 60) {
- Connect();
- WaitForSignal(this, SIGNAL(Connected()));
- }
-}
-
-void AmazonCloudDrive::ForgetCredentials() {
- QSettings s;
- s.beginGroup(kSettingsGroup);
- s.remove("");
- access_token_ = QString();
- expiry_time_ = QDateTime();
-}
-
-void AmazonCloudDrive::ConnectFinished(OAuthenticator* oauth) {
- oauth->deleteLater();
-
- QSettings s;
- s.beginGroup(kSettingsGroup);
- s.setValue("refresh_token", oauth->refresh_token());
-
- access_token_ = oauth->access_token();
- expiry_time_ = oauth->expiry_time();
-
- FetchEndpoint();
-}
-
-void AmazonCloudDrive::FetchEndpoint() {
- QUrl url(kEndpointEndpoint);
- QNetworkRequest request(url);
- Get(request, std::bind(&AmazonCloudDrive::FetchEndpointFinished, this, _1));
-}
-
-void AmazonCloudDrive::FetchEndpointFinished(QNetworkReply* reply) {
- reply->deleteLater();
-
- QJson::Parser parser;
- QVariantMap response = parser.parse(reply).toMap();
- content_url_ = response["contentUrl"].toString();
- metadata_url_ = response["metadataUrl"].toString();
- if (content_url_.isEmpty() || metadata_url_.isEmpty()) {
- qLog(Debug) << "Couldn't fetch Amazon endpoint";
- return;
- }
- QSettings s;
- s.beginGroup(kSettingsGroup);
- QString checkpoint = s.value("checkpoint", "").toString();
- RequestChanges(checkpoint);
-
- // We wait until we know the endpoint URLs before emitting Connected();
- emit Connected();
-}
-
-void AmazonCloudDrive::RequestChanges(const QString& checkpoint) {
- EnsureConnected();
- QUrl url(QString(kChangesEndpoint).arg(metadata_url_));
-
- QVariantMap data;
- data["includePurged"] = "true";
- if (!checkpoint.isEmpty()) {
- data["checkpoint"] = checkpoint;
- }
- QJson::Serializer serializer;
- QByteArray json = serializer.serialize(data);
-
- QNetworkRequest request(url);
- Post(request, json,
- std::bind(&AmazonCloudDrive::RequestChangesFinished, this, _1));
-}
-
-void AmazonCloudDrive::Get(QNetworkRequest request,
- std::function done,
- int retries) {
- AddAuthorizationHeader(&request);
- MonitorReply(network_->get(request), done, QByteArray(), retries);
-}
-
-void AmazonCloudDrive::Post(QNetworkRequest request, const QByteArray& data,
- std::function done,
- int retries) {
- AddAuthorizationHeader(&request);
- MonitorReply(network_->post(request, data), done, data, retries);
-}
-
-void AmazonCloudDrive::MonitorReply(QNetworkReply* reply,
- std::function 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);
- seconds delay(qrand() % max_delay_s);
- qLog(Debug) << "Request failed with code:" << code << "- retrying after"
- << delay << "seconds";
- DoAfter([=]() {
- if (post_data.isEmpty()) {
- Get(reply->request(), done, retries + 1);
- } else {
- Post(reply->request(), post_data, done, retries + 1);
- }
- }, delay);
- } else {
- // Request failed permanently.
- done(reply);
- }
- }
- });
-}
-
-void AmazonCloudDrive::RequestChangesFinished(QNetworkReply* reply) {
- reply->deleteLater();
-
- QByteArray data = reply->readAll();
- QBuffer buffer(&data);
- buffer.open(QIODevice::ReadOnly);
-
- QJson::Parser parser;
- QVariantMap response = parser.parse(&buffer).toMap();
-
- QString checkpoint = response["checkpoint"].toString();
- QSettings settings;
- settings.beginGroup(kSettingsGroup);
- settings.setValue("checkpoint", checkpoint);
-
- QVariantList nodes = response["nodes"].toList();
- for (const QVariant& n : nodes) {
- QVariantMap node = n.toMap();
- if (node["kind"].toString() == "FOLDER") {
- // Skip directories.
- continue;
- }
- QUrl url;
- url.setScheme("amazonclouddrive");
- url.setPath(node["id"].toString());
-
- QString status = node["status"].toString();
- if (status == "PURGED") {
- // Remove no longer available files.
- Song song = library_backend_->GetSongByUrl(url);
- if (song.is_valid()) {
- library_backend_->DeleteSongs(SongList() << song);
- }
- continue;
- }
- if (status != "AVAILABLE") {
- // Ignore any other statuses.
- continue;
- }
-
- QVariantMap content_properties = node["contentProperties"].toMap();
- QString mime_type = content_properties["contentType"].toString();
-
- if (ShouldIndexFile(url, mime_type)) {
- QString node_id = node["id"].toString();
- QUrl content_url(
- QString(kDownloadEndpoint).arg(content_url_).arg(node_id));
- QString md5 = content_properties["md5"].toString();
-
- Song song;
- song.set_url(url);
- song.set_etag(md5);
- song.set_mtime(node["modifiedDate"].toDateTime().toTime_t());
- song.set_ctime(node["createdDate"].toDateTime().toTime_t());
- song.set_title(node["name"].toString());
- song.set_filesize(content_properties["size"].toInt());
-
- MaybeAddFileToDatabase(song, mime_type, content_url,
- QString("Bearer %1").arg(access_token_));
- }
- }
-
- // The API potentially returns a second JSON dictionary appended with a
- // newline at the end of the response with {"end": true} indicating that our
- // client is up to date with the latest changes.
- const int last_newline_index = data.lastIndexOf('\n');
- QByteArray last_line = data.mid(last_newline_index);
- QVariantMap end_json = parser.parse(last_line).toMap();
- if (end_json.contains("end") && end_json["end"].toBool()) {
- return;
- } else {
- RequestChanges(checkpoint);
- }
-}
-
-void AmazonCloudDrive::AddAuthorizationHeader(QNetworkRequest* request) {
- request->setRawHeader("Authorization",
- QString("Bearer %1").arg(access_token_).toUtf8());
-}
diff --git a/src/internet/amazon/amazonclouddrive.h b/src/internet/amazon/amazonclouddrive.h
deleted file mode 100644
index da80cc178..000000000
--- a/src/internet/amazon/amazonclouddrive.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* This file is part of Clementine.
- Copyright 2015, John Maguire
-
- 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 .
-*/
-
-#ifndef INTERNET_AMAZON_AMAZON_CLOUD_DRIVE_H_
-#define INTERNET_AMAZON_AMAZON_CLOUD_DRIVE_H_
-
-#include "internet/core/cloudfileservice.h"
-
-#include
-#include
-#include
-
-class NetworkAccessManager;
-class OAuthenticator;
-class QNetworkReply;
-class QNetworkRequest;
-
-class AmazonCloudDrive : public CloudFileService {
- Q_OBJECT
- public:
- AmazonCloudDrive(Application* app, InternetModel* parent);
-
- static const char* kServiceName;
- static const char* kSettingsGroup;
-
- virtual bool has_credentials() const;
-
- QUrl GetStreamingUrlFromSongId(const QUrl& url);
-
- void ForgetCredentials();
-
-signals:
- void Connected();
-
- public slots:
- void Connect();
-
- private:
- void FetchEndpoint();
- void RequestChanges(const QString& checkpoint);
- void AddAuthorizationHeader(QNetworkRequest* request);
- void EnsureConnected();
- void Get(QNetworkRequest, std::function,
- int retries = 0);
- void Post(QNetworkRequest, const QByteArray& data,
- std::function, int retries = 0);
- void MonitorReply(QNetworkReply* reply,
- std::function done,
- const QByteArray& post_data = QByteArray(),
- int retries = 0);
-
- private slots:
- void ConnectFinished(OAuthenticator*);
- void FetchEndpointFinished(QNetworkReply*);
- void RequestChangesFinished(QNetworkReply*);
-
- private:
- NetworkAccessManager* network_;
- QString access_token_;
- QDateTime expiry_time_;
- QString content_url_;
- QString metadata_url_;
-};
-
-#endif // INTERNET_AMAZON_AMAZON_CLOUD_DRIVE_H_
diff --git a/src/internet/amazon/amazonsettingspage.cpp b/src/internet/amazon/amazonsettingspage.cpp
deleted file mode 100644
index 48ec4fd77..000000000
--- a/src/internet/amazon/amazonsettingspage.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/* This file is part of Clementine.
- Copyright 2015, John Maguire
-
- 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 .
-*/
-
-#include "amazonsettingspage.h"
-#include "ui_amazonsettingspage.h"
-
-#include "core/application.h"
-#include "internet/amazon/amazonclouddrive.h"
-#include "internet/core/internetmodel.h"
-#include "ui/settingsdialog.h"
-#include "ui/iconloader.h"
-
-AmazonSettingsPage::AmazonSettingsPage(SettingsDialog* parent)
- : SettingsPage(parent),
- ui_(new Ui::AmazonSettingsPage),
- service_(dialog()->app()->internet_model()->Service()) {
- ui_->setupUi(this);
- setWindowIcon(IconLoader::Load("amazon", IconLoader::Provider));
-
- ui_->login_state->AddCredentialGroup(ui_->login_container);
-
- connect(ui_->login_button, SIGNAL(clicked()), SLOT(LoginClicked()));
- connect(ui_->login_state, SIGNAL(LogoutClicked()), SLOT(LogoutClicked()));
- connect(service_, SIGNAL(Connected()), SLOT(Connected()));
-
- dialog()->installEventFilter(this);
-}
-
-AmazonSettingsPage::~AmazonSettingsPage() { delete ui_; }
-
-void AmazonSettingsPage::Load() {
- QSettings s;
- s.beginGroup(AmazonCloudDrive::kSettingsGroup);
-
- const QString token = s.value("refresh_token").toString();
-
- if (!token.isEmpty()) {
- ui_->login_state->SetLoggedIn(LoginStateWidget::LoggedIn);
- }
-}
-
-void AmazonSettingsPage::Save() {
- QSettings s;
- s.beginGroup(AmazonCloudDrive::kSettingsGroup);
-}
-
-void AmazonSettingsPage::LoginClicked() {
- service_->Connect();
- ui_->login_button->setEnabled(false);
- ui_->login_state->SetLoggedIn(LoginStateWidget::LoginInProgress);
-}
-
-bool AmazonSettingsPage::eventFilter(QObject* object, QEvent* event) {
- if (object == dialog() && event->type() == QEvent::Enter) {
- ui_->login_button->setEnabled(true);
- return false;
- }
-
- return SettingsPage::eventFilter(object, event);
-}
-
-void AmazonSettingsPage::LogoutClicked() {
- service_->ForgetCredentials();
- ui_->login_state->SetLoggedIn(LoginStateWidget::LoggedOut);
-}
-
-void AmazonSettingsPage::Connected() {
- ui_->login_state->SetLoggedIn(LoginStateWidget::LoggedIn);
-}
diff --git a/src/internet/amazon/amazonsettingspage.h b/src/internet/amazon/amazonsettingspage.h
deleted file mode 100644
index 8ff6b303e..000000000
--- a/src/internet/amazon/amazonsettingspage.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* This file is part of Clementine.
- Copyright 2015, John Maguire
-
- 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 .
-*/
-
-#ifndef INTERNET_AMAZON_AMAZONSETTINGSPAGE_H_
-#define INTERNET_AMAZON_AMAZONSETTINGSPAGE_H_
-
-#include "ui/settingspage.h"
-
-#include
-#include
-
-class AmazonCloudDrive;
-class Ui_AmazonSettingsPage;
-
-class AmazonSettingsPage : public SettingsPage {
- Q_OBJECT
-
- public:
- explicit AmazonSettingsPage(SettingsDialog* parent = nullptr);
- ~AmazonSettingsPage();
-
- void Load();
- void Save();
-
- // QObject
- bool eventFilter(QObject* object, QEvent* event);
-
- private slots:
- void LoginClicked();
- void LogoutClicked();
- void Connected();
-
- private:
- Ui_AmazonSettingsPage* ui_;
-
- AmazonCloudDrive* service_;
-};
-
-#endif // INTERNET_AMAZON_AMAZONSETTINGSPAGE_H_
diff --git a/src/internet/amazon/amazonsettingspage.ui b/src/internet/amazon/amazonsettingspage.ui
deleted file mode 100644
index 0b6e6fa52..000000000
--- a/src/internet/amazon/amazonsettingspage.ui
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
- AmazonSettingsPage
-
-
-
- 0
- 0
- 569
- 491
-
-
-
- Amazon Cloud Drive
-
-
- -
-
-
- Clementine can play music that you have uploaded to Amazon Cloud Drive
-
-
- true
-
-
-
- -
-
-
- -
-
-
-
- 28
-
-
- 0
-
-
- 0
-
-
-
-
-
-
-
-
- Login
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
- -
-
-
- Clicking the Login button will open a web browser. You should return to Clementine after you have logged in.
-
-
- true
-
-
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 357
-
-
-
-
-
-
-
-
- LoginStateWidget
- QWidget
- widgets/loginstatewidget.h
- 1
-
-
-
-
diff --git a/src/internet/amazon/amazonurlhandler.cpp b/src/internet/amazon/amazonurlhandler.cpp
deleted file mode 100644
index 42433a3f1..000000000
--- a/src/internet/amazon/amazonurlhandler.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/* This file is part of Clementine.
- Copyright 2015, John Maguire
-
- 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 .
-*/
-
-#include "internet/amazon/amazonurlhandler.h"
-
-#include "internet/amazon/amazonclouddrive.h"
-
-AmazonUrlHandler::AmazonUrlHandler(AmazonCloudDrive* service, QObject* parent)
- : UrlHandler(parent), service_(service) {}
-
-UrlHandler::LoadResult AmazonUrlHandler::StartLoading(const QUrl& url) {
- return LoadResult(url, LoadResult::TrackAvailable,
- service_->GetStreamingUrlFromSongId(url));
-}
diff --git a/src/internet/amazon/amazonurlhandler.h b/src/internet/amazon/amazonurlhandler.h
deleted file mode 100644
index 513d963c1..000000000
--- a/src/internet/amazon/amazonurlhandler.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* This file is part of Clementine.
- Copyright 2015, John Maguire
-
- 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 .
-*/
-
-#ifndef INTERNET_AMAZON_AMAZONURLHANDLER_H_
-#define INTERNET_AMAZON_AMAZONURLHANDLER_H_
-
-#include "core/urlhandler.h"
-#include "ui/iconloader.h"
-
-class AmazonCloudDrive;
-
-class AmazonUrlHandler : public UrlHandler {
- Q_OBJECT
- public:
- explicit AmazonUrlHandler(
- AmazonCloudDrive* service, QObject* parent = nullptr);
-
- QString scheme() const { return "amazonclouddrive"; }
- QIcon icon() const { return IconLoader::Load("amazonclouddrive", IconLoader::Provider); }
- LoadResult StartLoading(const QUrl& url);
-
- private:
- AmazonCloudDrive* service_;
-};
-
-#endif // INTERNET_AMAZON_AMAZONURLHANDLER_H_
diff --git a/src/internet/core/internetmodel.cpp b/src/internet/core/internetmodel.cpp
index e0f50d2c1..d3c8d6eb8 100644
--- a/src/internet/core/internetmodel.cpp
+++ b/src/internet/core/internetmodel.cpp
@@ -64,9 +64,6 @@
#ifdef HAVE_SEAFILE
#include "internet/seafile/seafileservice.h"
#endif
-#ifdef HAVE_AMAZON_CLOUD_DRIVE
-#include "internet/amazon/amazonclouddrive.h"
-#endif
using smart_playlists::Generator;
using smart_playlists::GeneratorMimeData;
@@ -119,9 +116,6 @@ InternetModel::InternetModel(Application* app, QObject* parent)
#ifdef HAVE_VK
AddService(new VkService(app, this));
#endif
-#ifdef HAVE_AMAZON_CLOUD_DRIVE
- AddService(new AmazonCloudDrive(app, this));
-#endif
invisibleRootItem()->sortChildren(0, Qt::AscendingOrder);
UpdateServices();
diff --git a/src/ui/settingsdialog.cpp b/src/ui/settingsdialog.cpp
index 2cb7e1b7b..dac9b64af 100644
--- a/src/ui/settingsdialog.cpp
+++ b/src/ui/settingsdialog.cpp
@@ -83,10 +83,6 @@
#include "internet/seafile/seafilesettingspage.h"
#endif
-#ifdef HAVE_AMAZON_CLOUD_DRIVE
-#include "internet/amazon/amazonsettingspage.h"
-#endif
-
#include
#include
#include
From cbc7092ed90a5bbf681afd7391cb06d4f2c4ae1e Mon Sep 17 00:00:00 2001
From: Valeriy
Date: Tue, 17 May 2016 14:47:02 +0300
Subject: [PATCH 05/66] fix code style
---
src/devices/giolister.cpp | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/src/devices/giolister.cpp b/src/devices/giolister.cpp
index f1a776bc0..aa3bddb34 100644
--- a/src/devices/giolister.cpp
+++ b/src/devices/giolister.cpp
@@ -101,10 +101,8 @@ void GioLister::Init() {
signals_.append(CHECKED_GCONNECT(monitor_, "mount-removed", &MountRemovedCallback, this));
}
-GioLister::~GioLister()
-{
- for (gulong signal : signals_)
- {
+GioLister::~GioLister() {
+ for (gulong signal : signals_) {
g_signal_handler_disconnect(monitor_, signal);
}
}
From d4e932db9a4e768737803afb331c1dd1acd3c9fe Mon Sep 17 00:00:00 2001
From: Valeriy
Date: Tue, 17 May 2016 22:56:16 +0300
Subject: [PATCH 06/66] udisks2 support for devicemanager (refs #3264)
---
CMakeLists.txt | 4 +
src/CMakeLists.txt | 28 ++
src/config.h.in | 1 +
src/core/metatypes.cpp | 3 +
src/dbus/metatypes.h | 8 +-
.../org.freedesktop.DBus.ObjectManager.xml | 19 ++
src/dbus/org.freedesktop.UDisks2.Block.xml | 9 +
src/dbus/org.freedesktop.UDisks2.Drive.xml | 17 ++
.../org.freedesktop.UDisks2.Filesystem.xml | 18 ++
src/devices/devicemanager.cpp | 9 +
src/devices/udisks2lister.cpp | 286 ++++++++++++++++++
src/devices/udisks2lister.h | 77 +++++
12 files changed, 478 insertions(+), 1 deletion(-)
create mode 100644 src/dbus/org.freedesktop.DBus.ObjectManager.xml
create mode 100644 src/dbus/org.freedesktop.UDisks2.Block.xml
create mode 100644 src/dbus/org.freedesktop.UDisks2.Drive.xml
create mode 100644 src/dbus/org.freedesktop.UDisks2.Filesystem.xml
create mode 100644 src/devices/udisks2lister.cpp
create mode 100644 src/devices/udisks2lister.h
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6da158efd..4bc74eb24 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -254,6 +254,10 @@ optional_component(DEVICEKIT ON "Devices: DeviceKit backend"
DEPENDS "D-Bus support" HAVE_DBUS
)
+optional_component(UDISKS2 ON "Devices: UDisks2 backend"
+ DEPENDS "D-Bus support" HAVE_DBUS
+)
+
optional_component(SPOTIFY_BLOB ON "Spotify support: non-GPL binary helper"
DEPENDS "protobuf" PROTOBUF_FOUND PROTOBUF_PROTOC_EXECUTABLE
DEPENDS "libspotify" SPOTIFY_FOUND
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4f0832b5b..ca6625abf 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -964,6 +964,29 @@ if(HAVE_DBUS)
dbus/udisksdevice)
endif(HAVE_DEVICEKIT)
+ if(HAVE_UDISKS2)
+ set_source_files_properties(dbus/org.freedesktop.DBus.ObjectManager.xml
+ PROPERTIES NO_NAMESPACE dbus/objectmanager INCLUDE dbus/metatypes.h)
+ set_source_files_properties(dbus/org.freedesktop.UDisks2.Filesystem.xml
+ PROPERTIES NO_NAMESPACE dbus/udisks2filesystem INCLUDE dbus/metatypes.h)
+ set_source_files_properties(dbus/org.freedesktop.UDisks2.Block.xml
+ PROPERTIES NO_NAMESPACE dbus/udisks2block INCLUDE dbus/metatypes.h)
+ set_source_files_properties(dbus/org.freedesktop.UDisks2.Drive.xml
+ PROPERTIES NO_NAMESPACE dbus/udisks2drive INCLUDE dbus/metatypes.h)
+ qt4_add_dbus_interface(SOURCES
+ dbus/org.freedesktop.DBus.ObjectManager.xml
+ dbus/objectmanager)
+ qt4_add_dbus_interface(SOURCES
+ dbus/org.freedesktop.UDisks2.Filesystem.xml
+ dbus/udisks2filesystem)
+ qt4_add_dbus_interface(SOURCES
+ dbus/org.freedesktop.UDisks2.Block.xml
+ dbus/udisks2block)
+ qt4_add_dbus_interface(SOURCES
+ dbus/org.freedesktop.UDisks2.Drive.xml
+ dbus/udisks2drive)
+ endif(HAVE_UDISKS2)
+
# Wiimotedev interface classes
if(ENABLE_WIIMOTEDEV)
qt4_add_dbus_interface(SOURCES
@@ -999,6 +1022,11 @@ optional_source(HAVE_DEVICEKIT
HEADERS devices/devicekitlister.h
)
+optional_source(HAVE_UDISKS2
+ SOURCES devices/udisks2lister.cpp
+ HEADERS devices/udisks2lister.h
+)
+
# Libgpod device backend
optional_source(HAVE_LIBGPOD
INCLUDE_DIRECTORIES ${LIBGPOD_INCLUDE_DIRS}
diff --git a/src/config.h.in b/src/config.h.in
index f22fe9bc8..2bd31b705 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -41,6 +41,7 @@
#cmakedefine HAVE_SKYDRIVE
#cmakedefine HAVE_SPARKLE
#cmakedefine HAVE_SPOTIFY_DOWNLOADER
+#cmakedefine HAVE_UDISKS2
#cmakedefine HAVE_VK
#cmakedefine HAVE_WIIMOTEDEV
#cmakedefine TAGLIB_HAS_OPUS
diff --git a/src/core/metatypes.cpp b/src/core/metatypes.cpp
index 62e246012..00b3553d9 100644
--- a/src/core/metatypes.cpp
+++ b/src/core/metatypes.cpp
@@ -125,5 +125,8 @@ void RegisterMetaTypes() {
qDBusRegisterMetaType();
qDBusRegisterMetaType();
qDBusRegisterMetaType();
+
+ qDBusRegisterMetaType();
+ qDBusRegisterMetaType();
#endif
}
diff --git a/src/dbus/metatypes.h b/src/dbus/metatypes.h
index 4e0024574..83bc5e615 100644
--- a/src/dbus/metatypes.h
+++ b/src/dbus/metatypes.h
@@ -20,6 +20,12 @@
#include
-Q_DECLARE_METATYPE(QList);
+Q_DECLARE_METATYPE(QList)
+
+typedef QMap InterfacesAndProperties;
+typedef QMap ManagedObjectList;
+
+Q_DECLARE_METATYPE(InterfacesAndProperties)
+Q_DECLARE_METATYPE(ManagedObjectList)
#endif // DBUS_METATYPES_H_
diff --git a/src/dbus/org.freedesktop.DBus.ObjectManager.xml b/src/dbus/org.freedesktop.DBus.ObjectManager.xml
new file mode 100644
index 000000000..efc389dd2
--- /dev/null
+++ b/src/dbus/org.freedesktop.DBus.ObjectManager.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/dbus/org.freedesktop.UDisks2.Block.xml b/src/dbus/org.freedesktop.UDisks2.Block.xml
new file mode 100644
index 000000000..f0e3a06c4
--- /dev/null
+++ b/src/dbus/org.freedesktop.UDisks2.Block.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/dbus/org.freedesktop.UDisks2.Drive.xml b/src/dbus/org.freedesktop.UDisks2.Drive.xml
new file mode 100644
index 000000000..5312b2250
--- /dev/null
+++ b/src/dbus/org.freedesktop.UDisks2.Drive.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/dbus/org.freedesktop.UDisks2.Filesystem.xml b/src/dbus/org.freedesktop.UDisks2.Filesystem.xml
new file mode 100644
index 000000000..1781919ab
--- /dev/null
+++ b/src/dbus/org.freedesktop.UDisks2.Filesystem.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/devices/devicemanager.cpp b/src/devices/devicemanager.cpp
index 6396b56cb..32ba33657 100644
--- a/src/devices/devicemanager.cpp
+++ b/src/devices/devicemanager.cpp
@@ -59,6 +59,9 @@
#ifdef HAVE_LIBMTP
#include "mtpdevice.h"
#endif
+#ifdef HAVE_UDISKS2
+#include "udisks2lister.h"
+#endif
using std::bind;
@@ -191,6 +194,9 @@ DeviceManager::DeviceManager(Application* app, QObject* parent)
#ifdef HAVE_DEVICEKIT
AddLister(new DeviceKitLister);
#endif
+#ifdef HAVE_UDISKS2
+ AddLister(new Udisks2Lister);
+#endif
#ifdef HAVE_GIO
AddLister(new GioLister);
#endif
@@ -228,7 +234,10 @@ void DeviceManager::LoadAllDevices() {
for (const DeviceDatabaseBackend::Device& device : devices) {
DeviceInfo info;
info.InitFromDb(device);
+
+ beginInsertRows(QModelIndex(), devices_.count(), devices_.count());
devices_ << info;
+ endInsertRows();
}
}
diff --git a/src/devices/udisks2lister.cpp b/src/devices/udisks2lister.cpp
new file mode 100644
index 000000000..99251468a
--- /dev/null
+++ b/src/devices/udisks2lister.cpp
@@ -0,0 +1,286 @@
+#include "udisks2lister.h"
+
+#include
+
+#include "core/logging.h"
+#include "core/utilities.h"
+
+#include "dbus/udisks2filesystem.h"
+#include "dbus/udisks2block.h"
+#include "dbus/udisks2drive.h"
+
+const QString Udisks2Lister::udisks2service_ = "org.freedesktop.UDisks2";
+
+Udisks2Lister::Udisks2Lister() {
+
+}
+
+Udisks2Lister::~Udisks2Lister() {
+ qLog(Debug) << __PRETTY_FUNCTION__;
+}
+
+QStringList Udisks2Lister::DeviceUniqueIDs() {
+ QReadLocker locker(&device_data_lock_);
+ return device_data_.keys();
+}
+
+QVariantList Udisks2Lister::DeviceIcons(const QString &id) {
+ return QVariantList();
+}
+
+QString Udisks2Lister::DeviceManufacturer(const QString &id) {
+ QReadLocker locker(&device_data_lock_);
+ if (!device_data_.contains(id))
+ return "";
+ return device_data_[id].vendor;
+}
+
+QString Udisks2Lister::DeviceModel(const QString &id) {
+ QReadLocker locker(&device_data_lock_);
+ if (!device_data_.contains(id))
+ return "";
+ return device_data_[id].model;
+}
+
+quint64 Udisks2Lister::DeviceCapacity(const QString &id) {
+ QReadLocker locker(&device_data_lock_);
+ if (!device_data_.contains(id))
+ return 0;
+ return device_data_[id].capacity;
+}
+
+quint64 Udisks2Lister::DeviceFreeSpace(const QString &id) {
+ QReadLocker locker(&device_data_lock_);
+ if (!device_data_.contains(id))
+ return 0;
+ return device_data_[id].free_space;
+}
+
+QVariantMap Udisks2Lister::DeviceHardwareInfo(const QString &id) {
+ QReadLocker locker(&device_data_lock_);
+ if (!device_data_.contains(id))
+ return QVariantMap();
+
+ QVariantMap result;
+
+ const auto &data = device_data_[id];
+ result[QT_TR_NOOP("DBus path")] = data.dbus_path;
+ result[QT_TR_NOOP("Serial number")] = data.serial;
+ result[QT_TR_NOOP("Mount points")] = data.mount_paths.join(", ");
+ result[QT_TR_NOOP("Parition label")] = data.label;
+ result[QT_TR_NOOP("UUID")] = data.uuid;
+
+ return result;
+}
+
+QString Udisks2Lister::MakeFriendlyName(const QString &id) {
+ QReadLocker locker(&device_data_lock_);
+ if (!device_data_.contains(id))
+ return "";
+ return device_data_[id].friendly_name;
+}
+
+QList Udisks2Lister::MakeDeviceUrls(const QString &id) {
+ QReadLocker locker(&device_data_lock_);
+ if (!device_data_.contains(id))
+ return QList();
+ return QList() << QUrl::fromLocalFile(device_data_[id].mount_paths.at(0));
+}
+
+void Udisks2Lister::UnmountDevice(const QString &id) {
+ QReadLocker locker(&device_data_lock_);
+ if (!device_data_.contains(id))
+ return;
+
+ OrgFreedesktopUDisks2FilesystemInterface filesystem(
+ udisks2service_,
+ device_data_[id].dbus_path,
+ QDBusConnection::systemBus());
+
+ if (filesystem.isValid())
+ {
+ auto umountResult = filesystem.Unmount(QVariantMap());
+ umountResult.waitForFinished();
+
+ OrgFreedesktopUDisks2DriveInterface drive(
+ udisks2service_,
+ device_data_[id].dbus_drive_path,
+ QDBusConnection::systemBus());
+
+ if (drive.isValid())
+ {
+ auto ejectResult = drive.Eject(QVariantMap());
+ ejectResult.waitForFinished();
+ }
+ }
+}
+
+void Udisks2Lister::UpdateDeviceFreeSpace(const QString &id) {
+ QWriteLocker locker(&device_data_lock_);
+ device_data_[id].free_space = Utilities::FileSystemFreeSpace(device_data_[id].mount_paths.at(0));
+
+ emit DeviceChanged(id);
+}
+
+void Udisks2Lister::Init() {
+ udisks2_interface_.reset(new OrgFreedesktopDBusObjectManagerInterface(
+ udisks2service_,
+ "/org/freedesktop/UDisks2",
+ QDBusConnection::systemBus()));
+
+ QDBusPendingReply reply = udisks2_interface_->GetManagedObjects();
+ reply.waitForFinished();
+
+ if (!reply.isValid()) {
+ qLog(Warning) << "Error enumerating udisks2 devices:"
+ << reply.error().name() << reply.error().message();
+ udisks2_interface_.reset();
+ return;
+ }
+
+ for (const QDBusObjectPath &path : reply.value().keys()) {
+ auto partitionData = ReadPartitionData(path, false);
+
+ if (!partitionData.dbus_path.isEmpty())
+ {
+ QWriteLocker locker(&device_data_lock_);
+ device_data_[partitionData.unique_id()] = partitionData;
+ }
+ }
+
+ for (const auto &id : device_data_.keys()) {
+ emit DeviceAdded(id);
+ }
+
+ connect(udisks2_interface_.get(), SIGNAL(InterfacesAdded(QDBusObjectPath, InterfacesAndProperties)),
+ SLOT(DBusInterfaceAdded(QDBusObjectPath, InterfacesAndProperties)));
+ connect(udisks2_interface_.get(), SIGNAL(InterfacesRemoved(QDBusObjectPath, QStringList)),
+ SLOT(DBusInterfaceRemoved(QDBusObjectPath, QStringList)));
+}
+
+void Udisks2Lister::DBusInterfaceAdded(const QDBusObjectPath &path,
+ const InterfacesAndProperties &interfaces) {
+ // FIXME handle unmount jobs too
+ for (auto interface = interfaces.constBegin(); interface != interfaces.constEnd(); ++interface)
+ {
+ if (interface.key() != "org.freedesktop.UDisks2.Job"
+ || interface.value()["Operation"] != "filesystem-mount")
+ continue;
+
+ const QDBusArgument &objects = interface.value()["Objects"].value();
+
+ QList mountedParititons;
+ objects.beginArray();
+ while (!objects.atEnd()) {
+ QDBusObjectPath extractedPath;
+ objects >> extractedPath;
+ mountedParititons.push_back(extractedPath);
+ }
+ objects.endArray();
+
+ qLog(Debug) << "Udisks2 something mounted: " << mountedParititons.at(0).path();
+
+ {
+ QMutexLocker locker(&jobs_lock_);
+ mounting_jobs_[path.path()] = mountedParititons;
+ }
+ }
+}
+
+void Udisks2Lister::DBusInterfaceRemoved(const QDBusObjectPath &path, const QStringList &ifaces) {
+ if (!isPendingJob(path))
+ RemoveDevice(path);
+}
+
+bool Udisks2Lister::isPendingJob(const QDBusObjectPath &path)
+{
+ // should be actually done with a succcess signal from job, I guess, but it makes it kinda complicated
+ QMutexLocker locker(&jobs_lock_);
+
+ if (!mounting_jobs_.contains(path.path()))
+ return false;
+
+ const auto &mountpaths = mounting_jobs_[path.path()];
+ for (const auto &partition : mountpaths) {
+ auto data = ReadPartitionData(partition, true);
+ if (!data.dbus_path.isEmpty()) {
+ QWriteLocker locker(&device_data_lock_);
+ device_data_[data.unique_id()] = data;
+ DeviceAdded(data.unique_id());
+ }
+ }
+ mounting_jobs_.remove(path.path());
+ return true;
+}
+
+void Udisks2Lister::RemoveDevice(const QDBusObjectPath &path)
+{
+ QWriteLocker locker(&device_data_lock_);
+ QString id;
+ for (const auto &data : device_data_) {
+ if (data.dbus_path == path.path())
+ id = data.unique_id();
+ }
+
+ if (id.isEmpty())
+ return;
+
+ device_data_.remove(id);
+ DeviceRemoved(id);
+}
+
+Udisks2Lister::PartitionData Udisks2Lister::ReadPartitionData(const QDBusObjectPath &path,
+ bool beingMounted) {
+ PartitionData result;
+ OrgFreedesktopUDisks2FilesystemInterface filesystem(
+ udisks2service_,
+ path.path(),
+ QDBusConnection::systemBus());
+ OrgFreedesktopUDisks2BlockInterface block(
+ udisks2service_,
+ path.path(),
+ QDBusConnection::systemBus());
+
+ if (filesystem.isValid()
+ && block.isValid()
+ && (beingMounted || !filesystem.mountPoints().empty())) {
+
+ OrgFreedesktopUDisks2DriveInterface drive(
+ udisks2service_,
+ block.drive().path(),
+ QDBusConnection::systemBus());
+
+ if (drive.isValid()
+ && drive.mediaRemovable()) {
+ result.dbus_path = path.path();
+ result.dbus_drive_path = block.drive().path();
+
+ result.serial = drive.serial();
+ result.vendor = drive.vendor();
+ result.model = drive.model();
+
+ result.label = block.idLabel();
+ result.uuid = block.idUUID();
+ result.capacity = drive.size();
+
+ if (!result.label.isEmpty())
+ result.friendly_name = result.label;
+ else
+ result.friendly_name = result.model + " " + result.uuid;
+
+ for (const auto &path : filesystem.mountPoints())
+ result.mount_paths.push_back(path);
+
+ result.free_space = Utilities::FileSystemFreeSpace(result.mount_paths.at(0));
+ }
+ }
+
+ return result;
+}
+
+QString Udisks2Lister::PartitionData::unique_id() const {
+ return QString("Udisks2/%1/%2/%3/%4/%5")
+ .arg(serial, vendor, model)
+ .arg(capacity)
+ .arg(uuid);
+}
diff --git a/src/devices/udisks2lister.h b/src/devices/udisks2lister.h
new file mode 100644
index 000000000..639db404b
--- /dev/null
+++ b/src/devices/udisks2lister.h
@@ -0,0 +1,77 @@
+#pragma once
+
+#include
+
+#include "devicelister.h"
+
+#include "dbus/objectmanager.h"
+
+class Udisks2Lister : public DeviceLister {
+ Q_OBJECT
+
+public:
+ Udisks2Lister();
+ ~Udisks2Lister();
+
+ QStringList DeviceUniqueIDs();
+ QVariantList DeviceIcons(const QString &id);
+ QString DeviceManufacturer(const QString &id);
+ QString DeviceModel(const QString &id);
+ quint64 DeviceCapacity(const QString &id);
+ quint64 DeviceFreeSpace(const QString &id);
+ QVariantMap DeviceHardwareInfo(const QString &id);
+
+ QString MakeFriendlyName(const QString &id);
+ QList MakeDeviceUrls(const QString &id);
+
+ void UnmountDevice(const QString &id);
+
+public slots:
+ void UpdateDeviceFreeSpace(const QString &id);
+
+protected:
+ void Init();
+
+private slots:
+ void DBusInterfaceAdded(const QDBusObjectPath &path, const InterfacesAndProperties &ifaces);
+ void DBusInterfaceRemoved(const QDBusObjectPath &path, const QStringList &ifaces);
+
+private:
+ bool isPendingJob(const QDBusObjectPath &path);
+ void RemoveDevice(const QDBusObjectPath &path);
+
+ QMutex jobs_lock_;
+ QMap> mounting_jobs_;
+
+private:
+ class PartitionData {
+ public:
+ QString unique_id() const;
+
+ QString dbus_path;
+ QString friendly_name;
+
+ // Device
+ QString serial;
+ QString vendor;
+ QString model;
+ quint64 capacity = 0;
+ QString dbus_drive_path;
+
+ // Paritition
+ QString label;
+ QString uuid;
+ quint64 free_space = 0;
+ QStringList mount_paths;
+ };
+
+ PartitionData ReadPartitionData(const QDBusObjectPath &path, bool beingMounted);
+
+ QReadWriteLock device_data_lock_;
+ QMap device_data_;
+
+private:
+ std::unique_ptr udisks2_interface_;
+
+ static const QString udisks2service_;
+};
From 4c3eb6135deb35b5d9cc3a5129d241d38725d787 Mon Sep 17 00:00:00 2001
From: Clementine Buildbot
Date: Wed, 18 May 2016 15:00:50 +0000
Subject: [PATCH 07/66] Automatic merge of translations from Transifex
(https://www.transifex.com/projects/p/clementine/resource/clementineplayer)
---
src/translations/br.po | 16 +-
src/translations/ca.po | 20 +-
src/translations/de.po | 8 +-
src/translations/el.po | 4 +-
src/translations/eo.po | 6 +-
src/translations/es.po | 14 +-
src/translations/ko.po | 32 +-
src/translations/pl.po | 7 +-
src/translations/sk.po | 2 +-
src/translations/tr_TR.po | 2719 +++++++++++++++++++------------------
10 files changed, 1420 insertions(+), 1408 deletions(-)
diff --git a/src/translations/br.po b/src/translations/br.po
index f876645ff..1a961b294 100644
--- a/src/translations/br.po
+++ b/src/translations/br.po
@@ -13,7 +13,7 @@
msgid ""
msgstr ""
"Project-Id-Version: Clementine Music Player\n"
-"PO-Revision-Date: 2016-04-21 09:37+0000\n"
+"PO-Revision-Date: 2016-05-17 15:01+0000\n"
"Last-Translator: Gwenn M \n"
"Language-Team: Breton (http://www.transifex.com/davidsansome/clementine/language/br/)\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -1288,7 +1288,7 @@ msgstr "Klikit war Ok ur wech kennasket Clementine d'ho kont last.fm."
#: library/libraryview.cpp:359
msgid "Click here to add some music"
-msgstr "Klikit aze evit krouiñ ho levraoueg sonerezh"
+msgstr "Klikit evit ouzhpennañ sonerezh"
#: playlist/playlisttabbar.cpp:298
msgid ""
@@ -2960,7 +2960,7 @@ msgstr "Sonaoueg"
#: ../bin/src/ui_groupbydialog.h:121
msgid "Library advanced grouping"
-msgstr "Strolladur ar sonaoueg kemplesoc'h"
+msgstr "Strolladur ar sonaoueg kempleshoc'h"
#: ui/mainwindow.cpp:2522
msgid "Library rescan notice"
@@ -2968,7 +2968,7 @@ msgstr "Kemenn hizivadur ar sonaoueg"
#: smartplaylists/querywizardplugin.cpp:79
msgid "Library search"
-msgstr "Enklask ar sonaoueg"
+msgstr "Klask er sonaoueg"
#: ../bin/src/ui_querysortpage.h:140
msgid "Limits"
@@ -3248,7 +3248,7 @@ msgstr "Patrom"
#: ../bin/src/ui_librarysettingspage.h:191
msgid "Monitor the library for changes"
-msgstr "Evezhiañ cheñchamantoù ar sonaoueg"
+msgstr "Evezhiañ kemmadurioù ar sonaoueg"
#: ../bin/src/ui_playbacksettingspage.h:370
msgid "Mono playback"
@@ -3294,7 +3294,7 @@ msgstr "Dindan"
#: ui/mainwindow.cpp:695 widgets/fileviewlist.cpp:42
msgid "Move to library..."
-msgstr "Dilec'hiañ davit ar sonaoueg..."
+msgstr "Dilec'hiañ davet ar sonaoueg..."
#: ../bin/src/ui_globalsearchsettingspage.h:144
#: ../bin/src/ui_queuemanager.h:126 ../bin/src/ui_songinfosettingspage.h:160
@@ -5678,7 +5678,7 @@ msgstr "Kennasket oc'h."
#: ../bin/src/ui_groupbydialog.h:122
msgid "You can change the way the songs in the library are organised."
-msgstr "Tu zo deoc'h kemman an doare ma vo renket an tonioù er sonaoueg."
+msgstr "Gallout a rit kemmañ an doare ma vo renket an tonioù er sonaoueg."
#: internet/magnatune/magnatunesettingspage.cpp:59
msgid ""
@@ -5751,7 +5751,7 @@ msgstr "Hoc'h aotreoù arveriad evit Magnatune a zo direizh."
#: library/libraryview.cpp:353
msgid "Your library is empty!"
-msgstr "Ho sonaoueg a zo goullo !"
+msgstr "Goullo eo ho sonaoueg!"
#: globalsearch/savedradiosearchprovider.cpp:26
#: internet/internetradio/savedradio.cpp:53
diff --git a/src/translations/ca.po b/src/translations/ca.po
index 58912914c..1e900e34e 100644
--- a/src/translations/ca.po
+++ b/src/translations/ca.po
@@ -3,11 +3,11 @@
# This file is distributed under the same license as the Clementine package.
#
# Translators:
-# Adolfo Jayme-Barrientos, 2014-2015
-# Adolfo Jayme-Barrientos, 2012-2013
-# Adolfo Jayme-Barrientos, 2015-2016
-# Adolfo Jayme-Barrientos, 2013
-# Adolfo Jayme-Barrientos, 2014
+# Fitoschido, 2014-2015
+# Fitoschido, 2012-2013
+# Fitoschido, 2015-2016
+# Fitoschido, 2013
+# Fitoschido, 2014
# FIRST AUTHOR , 2010
# Juanjo, 2016
# davidsansome , 2013
@@ -15,7 +15,7 @@
msgid ""
msgstr ""
"Project-Id-Version: Clementine Music Player\n"
-"PO-Revision-Date: 2016-04-20 22:41+0000\n"
+"PO-Revision-Date: 2016-04-27 09:20+0000\n"
"Last-Translator: Juanjo\n"
"Language-Team: Catalan (http://www.transifex.com/davidsansome/clementine/language/ca/)\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -1061,7 +1061,7 @@ msgstr "S’està creant l’índex de Seafile…"
#: ../bin/src/ui_globalsearchview.h:210
msgid "But these sources are disabled:"
-msgstr "Però aquests orígens estan desactivats:"
+msgstr "Els següents orígens estan desactivats:"
#: ../bin/src/ui_wiimotesettingspage.h:182
msgid "Buttons"
@@ -1282,7 +1282,7 @@ msgstr "El Clementine no ha trobat resultats per a aquest fitxer"
#: ../bin/src/ui_globalsearchview.h:209
msgid "Clementine will find music in:"
-msgstr "El Clementine trobarà música a:"
+msgstr "El Clementine buscarà a:"
#: internet/lastfm/lastfmsettingspage.cpp:78
msgid "Click Ok once you authenticated Clementine in your last.fm account."
@@ -2071,7 +2071,7 @@ msgstr "Introduïu un nom per aquesta llista de reproducció"
#: ../bin/src/ui_globalsearchview.h:208
msgid ""
"Enter search terms above to find music on your computer and on the internet"
-msgstr "Escrigueu termes de cerca per trobar música al vostre ordinador i a la Internet"
+msgstr "Escriviu els termes de cerca per buscar música"
#: ../bin/src/ui_itunessearchpage.h:73
msgid "Enter search terms below to find podcasts in the iTunes Store"
@@ -5546,7 +5546,7 @@ msgstr "Quan la llista sigui buida..."
#: ../bin/src/ui_globalsearchview.h:211
msgid "Why not try..."
-msgstr "Perquè no proveu..."
+msgstr "Podeu provar..."
#: ../bin/src/ui_transcoderoptionsspeex.h:228
msgid "Wide band (WB)"
diff --git a/src/translations/de.po b/src/translations/de.po
index 5ddb27289..f8d555fbd 100644
--- a/src/translations/de.po
+++ b/src/translations/de.po
@@ -3,6 +3,7 @@
# This file is distributed under the same license as the Clementine package.
#
# Translators:
+# AG_Caesar , 2016
# Andreas Demmelbauer, 2014
# Andreas Demmelbauer, 2014
# Ankorath , 2013
@@ -38,6 +39,7 @@
# Martin Herkt , 2011
# Martin Herkt , 2010
# Mohamed Sakhri, 2013
+# Mohamed Sakhri, 2013
# Mosley , 2011
# Paul E. <>, 2012
# Peter B. , 2014-2016
@@ -58,8 +60,8 @@
msgid ""
msgstr ""
"Project-Id-Version: Clementine Music Player\n"
-"PO-Revision-Date: 2016-04-21 16:08+0000\n"
-"Last-Translator: AG_Caesar \n"
+"PO-Revision-Date: 2016-05-11 14:37+0000\n"
+"Last-Translator: Stefan Hartgen \n"
"Language-Team: German (http://www.transifex.com/davidsansome/clementine/language/de/)\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -1006,7 +1008,7 @@ msgstr "Deckkraft:"
#: core/database.cpp:648
msgid "Backing up database"
-msgstr "Die Datenbank wird gesuchert"
+msgstr "Die Datenbank wird gesichert"
#: ../bin/src/ui_equalizer.h:172
msgid "Balance"
diff --git a/src/translations/el.po b/src/translations/el.po
index 642b4ee76..9d0d9db72 100644
--- a/src/translations/el.po
+++ b/src/translations/el.po
@@ -19,7 +19,7 @@
msgid ""
msgstr ""
"Project-Id-Version: Clementine Music Player\n"
-"PO-Revision-Date: 2016-04-22 17:00+0000\n"
+"PO-Revision-Date: 2016-05-15 12:53+0000\n"
"Last-Translator: Dimitrios Glentadakis \n"
"Language-Team: Greek (http://www.transifex.com/davidsansome/clementine/language/el/)\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -89,7 +89,7 @@ msgstr "%1 άλμπουμ"
#: widgets/equalizerslider.cpp:43
#, qt-format
msgid "%1 dB"
-msgstr ""
+msgstr "%1 dB"
#: core/utilities.cpp:120
#, qt-format
diff --git a/src/translations/eo.po b/src/translations/eo.po
index 3454beb8b..e2a41e0a0 100644
--- a/src/translations/eo.po
+++ b/src/translations/eo.po
@@ -3,9 +3,9 @@
# This file is distributed under the same license as the Clementine package.
#
# Translators:
-# Adolfo Jayme-Barrientos, 2014
-# Adolfo Jayme-Barrientos, 2015-2016
-# Adolfo Jayme-Barrientos, 2014
+# Fitoschido, 2014
+# Fitoschido, 2015-2016
+# Fitoschido, 2014
# FIRST AUTHOR , 2010
msgid ""
msgstr ""
diff --git a/src/translations/es.po b/src/translations/es.po
index 9588d5762..6af2e2d6a 100644
--- a/src/translations/es.po
+++ b/src/translations/es.po
@@ -4,12 +4,12 @@
#
# Translators:
# Coroccotta , 2012
-# Adolfo Jayme-Barrientos, 2014
-# Adolfo Jayme-Barrientos, 2012-2013
-# Adolfo Jayme-Barrientos, 2016
-# Adolfo Jayme-Barrientos, 2015-2016
-# Adolfo Jayme-Barrientos, 2013
-# Adolfo Jayme-Barrientos, 2014
+# Fitoschido, 2014
+# Fitoschido, 2012-2013
+# Fitoschido, 2016
+# Fitoschido, 2015-2016
+# Fitoschido, 2013
+# Fitoschido, 2014
# Adrián José Prado Castro , 2013
# Adrián Ramirez Escalante , 2012
# Andrés Manglano , 2014
@@ -37,7 +37,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Clementine Music Player\n"
"PO-Revision-Date: 2016-04-21 17:58+0000\n"
-"Last-Translator: Adolfo Jayme-Barrientos\n"
+"Last-Translator: Fitoschido\n"
"Language-Team: Spanish (http://www.transifex.com/davidsansome/clementine/language/es/)\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
diff --git a/src/translations/ko.po b/src/translations/ko.po
index 082f78c40..11969b3e0 100644
--- a/src/translations/ko.po
+++ b/src/translations/ko.po
@@ -20,8 +20,8 @@
msgid ""
msgstr ""
"Project-Id-Version: Clementine Music Player\n"
-"PO-Revision-Date: 2016-04-20 12:23+0000\n"
-"Last-Translator: Clementine Buildbot \n"
+"PO-Revision-Date: 2016-05-15 10:59+0000\n"
+"Last-Translator: 박정규(Jung-Kyu Park) \n"
"Language-Team: Korean (http://www.transifex.com/davidsansome/clementine/language/ko/)\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -2298,7 +2298,7 @@ msgstr "빠른"
#: internet/soundcloud/soundcloudservice.cpp:141
msgid "Favorites"
-msgstr ""
+msgstr "즐겨찾기"
#: library/library.cpp:88
msgid "Favourite tracks"
@@ -2318,7 +2318,7 @@ msgstr "가져오기 완료"
#: internet/subsonic/subsonicdynamicplaylist.cpp:88
msgid "Fetching Playlist Items"
-msgstr ""
+msgstr "재생 목록 가져오기"
#: internet/subsonic/subsonicservice.cpp:282
msgid "Fetching Subsonic library"
@@ -2468,7 +2468,7 @@ msgstr "프레임/"
#: internet/subsonic/subsonicservice.cpp:106
msgid "Frequently Played"
-msgstr ""
+msgstr "자주 재생되는 곡"
#: moodbar/moodbarrenderer.cpp:173
msgid "Frozen"
@@ -2590,11 +2590,11 @@ msgstr "그룹화"
#: library/libraryfilterwidget.cpp:207
msgid "Grouping Name"
-msgstr ""
+msgstr "그룹화할 이름"
#: library/libraryfilterwidget.cpp:207
msgid "Grouping name:"
-msgstr ""
+msgstr "그룹화할 이름:"
#: internet/podcasts/podcasturlloader.cpp:206
msgid "HTML page did not contain any RSS feeds"
@@ -2787,7 +2787,7 @@ msgstr "인터넷 서비스"
#: widgets/osd.cpp:323 ../bin/src/ui_playlistsequence.h:115
msgid "Intro tracks"
-msgstr ""
+msgstr "인트로 트랙"
#: internet/lastfm/lastfmservice.cpp:261
msgid "Invalid API key"
@@ -2925,11 +2925,11 @@ msgstr "Last.fm"
#: internet/lastfm/lastfmsettingspage.cpp:77
msgid "Last.fm authentication"
-msgstr ""
+msgstr "Last.fm 인증"
#: internet/lastfm/lastfmsettingspage.cpp:70
msgid "Last.fm authentication failed"
-msgstr ""
+msgstr "Last.fm 인증 실패"
#: internet/lastfm/lastfmservice.cpp:268
msgid "Last.fm is currently busy, please try again in a few minutes"
@@ -3180,7 +3180,7 @@ msgstr "잘못된 응답"
#: ../bin/src/ui_libraryfilterwidget.h:102
msgid "Manage saved groupings"
-msgstr ""
+msgstr "저장한 그룹 관리"
#: ../bin/src/ui_networkproxysettingspage.h:159
msgid "Manual proxy configuration"
@@ -3397,7 +3397,7 @@ msgstr "새로운 음악을 자동으로 추가함"
#: internet/subsonic/subsonicservice.cpp:100
msgid "Newest"
-msgstr ""
+msgstr "최신 목록"
#: library/library.cpp:92
msgid "Newest tracks"
@@ -3670,16 +3670,16 @@ msgstr "원본 태그"
#: ui/organisedialog.cpp:73 ../bin/src/ui_groupbydialog.h:135
#: ../bin/src/ui_groupbydialog.h:154 ../bin/src/ui_groupbydialog.h:173
msgid "Original year"
-msgstr ""
+msgstr "원 년"
#: library/savedgroupingmanager.cpp:98 ../bin/src/ui_groupbydialog.h:137
#: ../bin/src/ui_groupbydialog.h:156 ../bin/src/ui_groupbydialog.h:175
msgid "Original year - Album"
-msgstr ""
+msgstr "원 년 - 앨범"
#: library/library.cpp:118
msgid "Original year tag support"
-msgstr ""
+msgstr "원 년 태그 지원"
#: core/commandlineoptions.cpp:173
msgid "Other options"
@@ -3901,7 +3901,7 @@ msgstr "%1에 사용하기 위한 키조합을 누르세요..."
#: ../bin/src/ui_behavioursettingspage.h:331
msgid "Pressing \"Previous\" in player will..."
-msgstr ""
+msgstr "\"이전 트랙\"을 누르면..."
#: ../bin/src/ui_notificationssettingspage.h:457
msgid "Pretty OSD options"
diff --git a/src/translations/pl.po b/src/translations/pl.po
index 7805e7c24..f17a15abd 100644
--- a/src/translations/pl.po
+++ b/src/translations/pl.po
@@ -5,6 +5,7 @@
# Translators:
# Adrian Grzemski , 2015
# burtek , 2013
+# Caspar Cedro , 2016
# Daniel Krawczyk , 2014
# Daniel Krawczyk , 2014
# jan , 2014
@@ -21,8 +22,8 @@
msgid ""
msgstr ""
"Project-Id-Version: Clementine Music Player\n"
-"PO-Revision-Date: 2016-04-20 12:23+0000\n"
-"Last-Translator: Clementine Buildbot \n"
+"PO-Revision-Date: 2016-04-26 17:01+0000\n"
+"Last-Translator: Caspar Cedro \n"
"Language-Team: Polish (http://www.transifex.com/davidsansome/clementine/language/pl/)\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -2299,7 +2300,7 @@ msgstr "Szybki"
#: internet/soundcloud/soundcloudservice.cpp:141
msgid "Favorites"
-msgstr ""
+msgstr "Ulubione"
#: library/library.cpp:88
msgid "Favourite tracks"
diff --git a/src/translations/sk.po b/src/translations/sk.po
index 0f293385f..d109d9ae4 100644
--- a/src/translations/sk.po
+++ b/src/translations/sk.po
@@ -7,7 +7,7 @@
# bs_ , 2013
# Ján Ďanovský , 2011-2016
# Levi Taule , 2015
-# Michal Polovka , 2012
+# Michal Ján Mária Polovka , 2012
# MiroslavR , 2015
msgid ""
msgstr ""
diff --git a/src/translations/tr_TR.po b/src/translations/tr_TR.po
index 06cb5f963..b7740b199 100644
--- a/src/translations/tr_TR.po
+++ b/src/translations/tr_TR.po
@@ -6,22 +6,31 @@
# Ahmet Sezgin Duran , 2013
# Mustafa YILMAZ , 2013
# arnaudbienner , 2011
+# Demiray Muhterem , 2016
# devingregory , 2012
# devingregory , 2012
+# Ege Öz , 2013
+# Emre FIRAT , 2013
# Emre FIRAT , 2013
# Erhan BURHAN <>, 2012
# H. İbrahim Güngör , 2011
# H. İbrahim Güngör , 2010
# İbrahim Güngör , 2011
+# Hüsamettin Ertürk , 2016
+# İbrahim Güngör , 2011
# Irfan YAZICI , 2011
# Kadir Celep , 2012
+# Kadir Celep , 2012
# Ege Öz , 2013
# mutlucan96 , 2013
# Muhammet Kara , 2012
+# Muhammet Kara , 2012,2015
# Murat Ikilik <>, 2012
# Murat Sahin , 2012
+# Mustafa YILMAZ , 2013
# Necdet Yücel , 2012
# Faruk Uzun , 2012
+# seckin Yılmaz , 2015
# Volkan Gezer , 2013
# Volkan Gezer , 2014
# yusufbesir1 , 2012
@@ -29,8 +38,8 @@
msgid ""
msgstr ""
"Project-Id-Version: Clementine Music Player\n"
-"PO-Revision-Date: 2016-04-20 12:23+0000\n"
-"Last-Translator: Clementine Buildbot \n"
+"PO-Revision-Date: 2016-05-16 16:29+0000\n"
+"Last-Translator: Hüsamettin Ertürk \n"
"Language-Team: Turkish (Turkey) (http://www.transifex.com/davidsansome/clementine/language/tr_TR/)\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -44,11 +53,11 @@ msgid ""
"You can favorite playlists by clicking the star icon next to a playlist name\n"
"\n"
"Favorited playlists will be saved here"
-msgstr ""
+msgstr "\n\nÇalma listelerini bir çalma listesi adının anındaki yıldız simgesi ile beğenilenlere ekleyebilirsiniz\n\nBeğenilen çalma listeleri buraya kaydedilecek"
#: ../bin/src/ui_podcastsettingspage.h:270
msgid " days"
-msgstr ""
+msgstr " günler"
#: ../bin/src/ui_transcoderoptionsaac.h:129
#: ../bin/src/ui_transcoderoptionsmp3.h:194
@@ -60,277 +69,277 @@ msgstr ""
#: ../bin/src/ui_transcoderoptionsvorbis.h:210
#: ../bin/src/ui_transcoderoptionswma.h:79
msgid " kbps"
-msgstr ""
+msgstr " kbps"
#: ../bin/src/ui_playbacksettingspage.h:347
#: ../bin/src/ui_playbacksettingspage.h:350
#: ../bin/src/ui_playbacksettingspage.h:364
msgid " ms"
-msgstr ""
+msgstr " ms"
#: ../bin/src/ui_songinfosettingspage.h:156
msgid " pt"
-msgstr ""
+msgstr " pt"
#: ../bin/src/ui_behavioursettingspage.h:359
msgid " s"
-msgstr ""
+msgstr " s"
#: ../bin/src/ui_notificationssettingspage.h:444
#: ../bin/src/ui_visualisationselector.h:115
msgid " seconds"
-msgstr ""
+msgstr " saniye"
#: ../bin/src/ui_querysortpage.h:143
msgid " songs"
-msgstr ""
+msgstr " şarkılar"
#: internet/vk/vkservice.cpp:149
#, qt-format
msgid "%1 (%2 songs)"
-msgstr ""
+msgstr "%1 (%2 şarkı)"
#: widgets/osd.cpp:195
#, qt-format
msgid "%1 albums"
-msgstr ""
+msgstr "%1 albüm"
#: widgets/equalizerslider.cpp:29 widgets/equalizerslider.cpp:31
#: widgets/equalizerslider.cpp:43
#, qt-format
msgid "%1 dB"
-msgstr ""
+msgstr "%1 dB"
#: core/utilities.cpp:120
#, qt-format
msgid "%1 days"
-msgstr ""
+msgstr "%1 gün"
#: core/utilities.cpp:139
#, qt-format
msgid "%1 days ago"
-msgstr ""
+msgstr "%1 gün önce"
#: internet/podcasts/gpoddersync.cpp:84
#, qt-format
msgid "%1 on %2"
-msgstr ""
+msgstr "%2 üzerinde %1"
#: playlistparsers/playlistparser.cpp:76
#, qt-format
msgid "%1 playlists (%2)"
-msgstr ""
+msgstr "%1 çalma listesi (%2)"
#: playlist/playlistmanager.cpp:403
#, qt-format
msgid "%1 selected of"
-msgstr ""
+msgstr "%1 seçili"
#: devices/deviceview.cpp:125
#, qt-format
msgid "%1 song"
-msgstr ""
+msgstr "%1 şarkı"
#: devices/deviceview.cpp:127
#, qt-format
msgid "%1 songs"
-msgstr ""
+msgstr "%1 şarkı"
#: smartplaylists/searchpreview.cpp:123
#, qt-format
msgid "%1 songs found"
-msgstr ""
+msgstr "%1 şarkı bulundu"
#: smartplaylists/searchpreview.cpp:119
#, qt-format
msgid "%1 songs found (showing %2)"
-msgstr ""
+msgstr "%1 şarkı bulundu (%2 tanesi gösteriliyor)"
#: playlist/playlistmanager.cpp:409
#, qt-format
msgid "%1 tracks"
-msgstr ""
+msgstr "%1 parça"
#: ui/albumcovermanager.cpp:469
#, qt-format
msgid "%1 transferred"
-msgstr ""
+msgstr "%1 aktarıldı"
#: widgets/osd.cpp:243 widgets/osd.cpp:249 widgets/osd.cpp:255
#: widgets/osd.cpp:261 widgets/osd.cpp:267 widgets/osd.cpp:274
#, qt-format
msgid "%1: Wiimotedev module"
-msgstr ""
+msgstr "%1: Wiimotedev modülü"
#: songinfo/lastfmtrackinfoprovider.cpp:95
#, qt-format
msgid "%L1 other listeners"
-msgstr ""
+msgstr "%L1 başka dinleyici"
#: songinfo/lastfmtrackinfoprovider.cpp:92
#, qt-format
msgid "%L1 total plays"
-msgstr ""
+msgstr "%L1 toplam çalma"
#: ../bin/src/ui_notificationssettingspage.h:432
msgid "%filename%"
-msgstr ""
+msgstr "%filename%"
#: transcoder/transcodedialog.cpp:214
#, c-format, qt-plural-format
msgctxt ""
msgid "%n failed"
-msgstr ""
+msgstr "%n başarısız"
#: transcoder/transcodedialog.cpp:209
#, c-format, qt-plural-format
msgctxt ""
msgid "%n finished"
-msgstr ""
+msgstr "%n tamamlandı"
#: transcoder/transcodedialog.cpp:203
#, c-format, qt-plural-format
msgctxt ""
msgid "%n remaining"
-msgstr ""
+msgstr "%n kaldı"
#: playlist/playlistheader.cpp:45
msgid "&Align text"
-msgstr ""
+msgstr "&Metni hizala"
#: playlist/playlistheader.cpp:48
msgid "&Center"
-msgstr ""
+msgstr "&Ortala"
#: ../bin/src/ui_globalshortcutssettingspage.h:177
msgid "&Custom"
-msgstr ""
+msgstr "&Özel"
#: ../bin/src/ui_mainwindow.h:718
msgid "&Extras"
-msgstr ""
+msgstr "Ekler"
#: ../bin/src/ui_mainwindow.h:717
msgid "&Help"
-msgstr ""
+msgstr "&Yardım"
#: playlist/playlistheader.cpp:81
#, qt-format
msgid "&Hide %1"
-msgstr ""
+msgstr "&Gizle %1"
#: playlist/playlistheader.cpp:33
msgid "&Hide..."
-msgstr ""
+msgstr "&Gizle..."
#: playlist/playlistheader.cpp:47
msgid "&Left"
-msgstr ""
+msgstr "&Sol"
#: playlist/playlistheader.cpp:36
msgid "&Lock Rating"
-msgstr ""
+msgstr "Reyting &Kilitle"
#: ../bin/src/ui_mainwindow.h:715
msgid "&Music"
-msgstr ""
+msgstr "Müzik"
#: ../bin/src/ui_globalshortcutssettingspage.h:175
msgid "&None"
-msgstr ""
+msgstr "&Hiçbiri"
#: ../bin/src/ui_mainwindow.h:716
msgid "&Playlist"
-msgstr ""
+msgstr "Çalma Listesi"
#: ../bin/src/ui_mainwindow.h:662
msgid "&Quit"
-msgstr ""
+msgstr "&Çık"
#: ../bin/src/ui_mainwindow.h:687
msgid "&Repeat mode"
-msgstr ""
+msgstr "Tekrar kipi"
#: playlist/playlistheader.cpp:49
msgid "&Right"
-msgstr ""
+msgstr "&Sağ"
#: ../bin/src/ui_mainwindow.h:686
msgid "&Shuffle mode"
-msgstr ""
+msgstr "Rastgele kipi"
#: playlist/playlistheader.cpp:34
msgid "&Stretch columns to fit window"
-msgstr ""
+msgstr "&Sütunları pencereye sığacak şekilde ayarla"
#: ../bin/src/ui_mainwindow.h:719
msgid "&Tools"
-msgstr ""
+msgstr "&Araçlar"
#: ui/edittagdialog.cpp:50
msgid "(different across multiple songs)"
-msgstr ""
+msgstr "(her şarkı için farklı)"
#: internet/spotify/spotifyservice.cpp:469
msgid ", by "
-msgstr ""
+msgstr ", "
#: ui/about.cpp:84
msgid "...and all the Amarok contributors"
-msgstr ""
+msgstr "...ve tüm Amarok katkıcılarına"
#: ../bin/src/ui_albumcovermanager.h:222 ../bin/src/ui_albumcovermanager.h:223
msgid "0"
-msgstr ""
+msgstr "0"
#: ../bin/src/ui_trackslider.h:69 ../bin/src/ui_trackslider.h:73
msgid "0:00:00"
-msgstr ""
+msgstr "0:00:00"
#: ../bin/src/ui_appearancesettingspage.h:288
msgid "0px"
-msgstr ""
+msgstr "0px"
#: core/utilities.cpp:120
msgid "1 day"
-msgstr ""
+msgstr "1 gün"
#: playlist/playlistmanager.cpp:409
msgid "1 track"
-msgstr ""
+msgstr "1 parça"
#: ../bin/src/ui_magnatunedownloaddialog.h:139
#: ../bin/src/ui_magnatunesettingspage.h:173
msgid "128k MP3"
-msgstr ""
+msgstr "128k MP3"
#: ../bin/src/ui_playbacksettingspage.h:378
msgid "192,000Hz"
-msgstr ""
+msgstr "192,000Hz"
#: ../bin/src/ui_appearancesettingspage.h:290
msgid "40%"
-msgstr ""
+msgstr "40%"
#: ../bin/src/ui_playbacksettingspage.h:375
msgid "44,100Hz"
-msgstr ""
+msgstr "44,100Hz"
#: ../bin/src/ui_playbacksettingspage.h:376
msgid "48,000Hz"
-msgstr ""
+msgstr "48,000Hz"
#: library/library.cpp:64
msgid "50 random tracks"
-msgstr ""
+msgstr "50 rastgele parça"
#: ../bin/src/ui_playbacksettingspage.h:377
msgid "96,000Hz"
-msgstr ""
+msgstr "96,000Hz"
#: ../bin/src/ui_digitallyimportedsettingspage.h:164
msgid "Upgrade to Premium now"
-msgstr ""
+msgstr "Şimdi Premium üyeliğine geçin"
#: ../bin/src/ui_librarysettingspage.h:194
msgid ""
@@ -340,7 +349,7 @@ msgid ""
"directly into the file each time they changed.
Please note it might "
"not work for every format and, as there is no standard for doing so, other "
"music players might not be able to read them.