From 0dcdf36535c5ebd410a4ec48e4acfe4c358a6eab Mon Sep 17 00:00:00 2001 From: David Sansome Date: Sat, 17 Jul 2010 14:22:07 +0000 Subject: [PATCH] Start of work on a GIO/GVFS device backend. --- CMakeLists.txt | 1 + src/CMakeLists.txt | 9 +++ src/config.h.in | 1 + src/devices/connecteddevice.cpp | 5 +- src/devices/connecteddevice.h | 7 +- src/devices/devicekitlister.cpp | 16 ++--- src/devices/devicekitlister.h | 4 +- src/devices/devicelister.h | 7 +- src/devices/devicemanager.cpp | 49 ++++++++++++-- src/devices/devicemanager.h | 13 ++++ src/devices/filesystemdevice.cpp | 9 +-- src/devices/filesystemdevice.h | 9 ++- src/devices/giolister.cpp | 109 ++++++++++++++++++++++++++++++ src/devices/giolister.h | 59 ++++++++++++++++ src/devices/gpoddevice.cpp | 11 +-- src/devices/gpoddevice.h | 9 ++- src/translations/ar.po | 4 ++ src/translations/cs.po | 4 ++ src/translations/da.po | 4 ++ src/translations/de.po | 4 ++ src/translations/el.po | 4 ++ src/translations/en_CA.po | 4 ++ src/translations/en_GB.po | 4 ++ src/translations/es.po | 4 ++ src/translations/fi.po | 4 ++ src/translations/fr.po | 4 ++ src/translations/gl.po | 4 ++ src/translations/it.po | 4 ++ src/translations/kk.po | 4 ++ src/translations/nb.po | 4 ++ src/translations/oc.po | 4 ++ src/translations/pl.po | 4 ++ src/translations/pt.po | 4 ++ src/translations/pt_BR.po | 4 ++ src/translations/ro.po | 4 ++ src/translations/ru.po | 4 ++ src/translations/sk.po | 4 ++ src/translations/sv.po | 4 ++ src/translations/tr.po | 4 ++ src/translations/translations.pot | 4 ++ src/translations/uk.po | 4 ++ src/translations/zh_CN.po | 4 ++ src/translations/zh_TW.po | 4 ++ 43 files changed, 380 insertions(+), 46 deletions(-) create mode 100644 src/devices/giolister.cpp create mode 100644 src/devices/giolister.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b23de7aec..a70696b25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,6 +54,7 @@ else(WIN32) pkg_check_modules(LIBXML libxml-2.0) pkg_check_modules(GOBJECT gobject-2.0) pkg_check_modules(LIBGPOD libgpod-1.0) + pkg_check_modules(GIO gio-2.0) endif(WIN32) find_library(LASTFM_LIBRARIES lastfm) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2415372b1..14c8f273d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -470,6 +470,15 @@ if(LIBGPOD_FOUND) list(APPEND HEADERS devices/gpoddevice.h devices/gpodloader.h) endif(LIBGPOD_FOUND) +# GIO device backend +if(GIO_FOUND) + set(HAVE_GIO ON) + include_directories(${GIO_INCLUDE_DIRS}) + + list(APPEND SOURCES devices/giolister.cpp) + list(APPEND HEADERS devices/giolister.h) +endif(GIO_FOUND) + # Mac specific startup stuff if(APPLE) list(APPEND SOURCES core/mac_startup.mm) diff --git a/src/config.h.in b/src/config.h.in index 874c9440d..d7627b2b5 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -40,5 +40,6 @@ #cmakedefine HAVE_STATIC_SQLITE #cmakedefine HAVE_LIBGPOD +#cmakedefine HAVE_GIO #endif // CONFIG_H_IN diff --git a/src/devices/connecteddevice.cpp b/src/devices/connecteddevice.cpp index eb245328c..a76587db7 100644 --- a/src/devices/connecteddevice.cpp +++ b/src/devices/connecteddevice.cpp @@ -23,8 +23,9 @@ #include -ConnectedDevice::ConnectedDevice(DeviceLister* lister, const QString& unique_id, - DeviceManager* manager, int database_id) +ConnectedDevice::ConnectedDevice(const QUrl&, DeviceLister* lister, + const QString& unique_id, DeviceManager* manager, + int database_id, bool) : QObject(manager), lister_(lister), unique_id_(unique_id), diff --git a/src/devices/connecteddevice.h b/src/devices/connecteddevice.h index aa8db0ac9..329afc5bc 100644 --- a/src/devices/connecteddevice.h +++ b/src/devices/connecteddevice.h @@ -18,6 +18,8 @@ #define CONNECTEDDEVICE_H #include +#include +#include class Database; class DeviceLister; @@ -29,8 +31,9 @@ class ConnectedDevice : public QObject { Q_OBJECT public: - ConnectedDevice(DeviceLister* lister, const QString& unique_id, - DeviceManager* manager, int database_id); + ConnectedDevice(const QUrl& url, DeviceLister* lister, + const QString& unique_id, DeviceManager* manager, + int database_id, bool first_time); ~ConnectedDevice(); DeviceLister* lister() const { return lister_; } diff --git a/src/devices/devicekitlister.cpp b/src/devices/devicekitlister.cpp index f3a9708ac..2da5d6a4d 100644 --- a/src/devices/devicekitlister.cpp +++ b/src/devices/devicekitlister.cpp @@ -236,23 +236,15 @@ QString DeviceKitLister::FindUniqueIdByPath(const QDBusObjectPath &path) const { return QString(); } -boost::shared_ptr DeviceKitLister::Connect( - const QString &unique_id, DeviceManager* manager, int database_id, - bool first_time) { +QUrl DeviceKitLister::MakeDeviceUrl(const QString& id) { QString mount_point = LockAndGetDeviceInfo( - unique_id, &DeviceData::device_mount_paths)[0]; - - boost::shared_ptr ret; + id, &DeviceData::device_mount_paths)[0]; #ifdef HAVE_LIBGPOD if (QFile::exists(mount_point + "/iTunes_Control")) { - ret.reset(new GPodDevice( - mount_point, this, unique_id, manager, database_id, first_time)); - return ret; + return QUrl("ipod://" + mount_point); } #endif - ret.reset(new FilesystemDevice( - mount_point, this, unique_id, manager, database_id, first_time)); - return ret; + return QUrl::fromLocalFile(mount_point); } diff --git a/src/devices/devicekitlister.h b/src/devices/devicekitlister.h index a03bac18d..7b6d44bca 100644 --- a/src/devices/devicekitlister.h +++ b/src/devices/devicekitlister.h @@ -45,9 +45,7 @@ public: QString MakeFriendlyName(const QString &id); - boost::shared_ptr Connect( - const QString &unique_id, DeviceManager* manager, int database_id, - bool first_time); + QUrl MakeDeviceUrl(const QString &id); protected: void Init(); diff --git a/src/devices/devicelister.h b/src/devices/devicelister.h index cc99ac59b..c40eab2fd 100644 --- a/src/devices/devicelister.h +++ b/src/devices/devicelister.h @@ -18,6 +18,7 @@ #define DEVICELISTER_H #include +#include #include @@ -46,11 +47,7 @@ public: virtual QString MakeFriendlyName(const QString& id) = 0; - // Create a new ConnectedDevice instance for the given device. Must be - // thread-safe. - virtual boost::shared_ptr Connect( - const QString& unique_id, DeviceManager* manager, int database_id, - bool first_time) = 0; + virtual QUrl MakeDeviceUrl(const QString& id) = 0; signals: void DeviceAdded(const QString& id); diff --git a/src/devices/devicemanager.cpp b/src/devices/devicemanager.cpp index 00feb11c3..8cfa2ebd9 100644 --- a/src/devices/devicemanager.cpp +++ b/src/devices/devicemanager.cpp @@ -15,16 +15,19 @@ */ #include "config.h" -#include "connecteddevice.h" #include "devicedatabasebackend.h" #include "devicemanager.h" #include "devicekitlister.h" +#include "filesystemdevice.h" +#include "giolister.h" +#include "gpoddevice.h" #include "core/taskmanager.h" #include "core/utilities.h" #include "ui/iconloader.h" #include #include +#include const int DeviceManager::kDeviceIconSize = 32; const int DeviceManager::kDeviceIconOverlaySize = 16; @@ -99,6 +102,15 @@ DeviceManager::DeviceManager(BackgroundThread* database, #ifdef Q_WS_X11 AddLister(new DeviceKitLister); #endif +#ifdef HAVE_GIO + AddLister(new GioLister); +#endif + + AddDeviceClass(); + +#ifdef HAVE_LIBGPOD + AddDeviceClass(); +#endif } DeviceManager::~DeviceManager() { @@ -262,8 +274,10 @@ boost::shared_ptr DeviceManager::Connect(int row) { if (info.device_) // Already connected return info.device_; + boost::shared_ptr ret; + if (!info.lister_) // Not physically connected - return boost::shared_ptr(); + return ret; bool first_time = (info.database_id_ == -1); if (first_time) { @@ -271,12 +285,33 @@ boost::shared_ptr DeviceManager::Connect(int row) { info.database_id_ = backend_->AddDevice(info.SaveToDb()); } - info.device_ = info.lister_->Connect( - info.unique_id_, this, info.database_id_, first_time); - connect(info.device_.get(), SIGNAL(TaskStarted(int)), SLOT(DeviceTaskStarted(int))); - connect(info.device_.get(), SIGNAL(Error(QString)), SIGNAL(Error(QString))); + // Get the device URL + QUrl url = info.lister_->MakeDeviceUrl(info.unique_id_); + if (url.isEmpty()) + return ret; - return info.device_; + // Find a device class for this URL's scheme + if (!device_classes_.contains(url.scheme())) { + emit Error(tr("This type of device is not supported: %1").arg(url.toString())); + return ret; + } + + QMetaObject meta_object = device_classes_.value(url.scheme()); + QObject* instance = meta_object.newInstance( + Q_ARG(QUrl, url), Q_ARG(DeviceLister*, info.lister_), + Q_ARG(QString, info.unique_id_), Q_ARG(DeviceManager*, this), + Q_ARG(int, info.database_id_), Q_ARG(bool, first_time)); + ret.reset(static_cast(instance)); + + if (!ret) { + qWarning() << "Could not create device for" << url.toString(); + } else { + info.device_ = ret; + connect(info.device_.get(), SIGNAL(TaskStarted(int)), SLOT(DeviceTaskStarted(int))); + connect(info.device_.get(), SIGNAL(Error(QString)), SIGNAL(Error(QString))); + } + + return ret; } boost::shared_ptr DeviceManager::GetConnectedDevice(int row) const { diff --git a/src/devices/devicemanager.h b/src/devices/devicemanager.h index f14fe1a75..6569ff9cb 100644 --- a/src/devices/devicemanager.h +++ b/src/devices/devicemanager.h @@ -123,6 +123,7 @@ private: }; void AddLister(DeviceLister* lister); + template void AddDeviceClass(); DeviceDatabaseBackend::Device InfoToDatabaseDevice(const DeviceInfo& info) const; @@ -136,8 +137,20 @@ private: QList listers_; QList devices_; + QMultiMap device_classes_; + // Map of task ID to device index QMap active_tasks_; }; +template +void DeviceManager::AddDeviceClass() { + QStringList schemes = T::url_schemes(); + QMetaObject obj = T::staticMetaObject; + + foreach (const QString& scheme, schemes) { + device_classes_.insert(scheme, obj); + } +} + #endif // DEVICEMANAGER_H diff --git a/src/devices/filesystemdevice.cpp b/src/devices/filesystemdevice.cpp index d57923029..a55ac0267 100644 --- a/src/devices/filesystemdevice.cpp +++ b/src/devices/filesystemdevice.cpp @@ -24,9 +24,10 @@ #include FilesystemDevice::FilesystemDevice( - const QString& mount_point, DeviceLister* lister, const QString& unique_id, - DeviceManager* manager, int database_id, bool first_time) - : ConnectedDevice(lister, unique_id, manager, database_id), + const QUrl& url, DeviceLister* lister, + const QString& unique_id, DeviceManager* manager, + int database_id, bool first_time) + : ConnectedDevice(url, lister, unique_id, manager, database_id, first_time), watcher_(new BackgroundThreadImplementation(this)) { // Create the library watcher @@ -57,7 +58,7 @@ FilesystemDevice::FilesystemDevice( backend_, SLOT(UpdateCompilations())); connect(watcher, SIGNAL(ScanStarted(int)), SIGNAL(TaskStarted(int))); - InitBackendDirectory(mount_point, first_time); + InitBackendDirectory(url.toLocalFile(), first_time); model_->Init(); } diff --git a/src/devices/filesystemdevice.h b/src/devices/filesystemdevice.h index 2dfde1a26..ba2868a1c 100644 --- a/src/devices/filesystemdevice.h +++ b/src/devices/filesystemdevice.h @@ -27,11 +27,14 @@ class FilesystemDevice : public ConnectedDevice { Q_OBJECT public: - FilesystemDevice(const QString& mount_point, DeviceLister* lister, - const QString& unique_id, DeviceManager* manager, - int database_id, bool first_time); + Q_INVOKABLE FilesystemDevice( + const QUrl& url, DeviceLister* lister, + const QString& unique_id, DeviceManager* manager, + int database_id, bool first_time); ~FilesystemDevice(); + static QStringList url_schemes() { return QStringList() << "file"; } + private: BackgroundThread* watcher_; }; diff --git a/src/devices/giolister.cpp b/src/devices/giolister.cpp new file mode 100644 index 000000000..07db0999d --- /dev/null +++ b/src/devices/giolister.cpp @@ -0,0 +1,109 @@ +/* This file is part of Clementine. + + 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 "giolister.h" + +#include +#include + +GioLister::GioLister() + : monitor_(NULL) +{ +} + +void GioLister::Init() { + monitor_ = g_volume_monitor_get(); + + // Get things that are already mounted + GList* mounts = g_volume_monitor_get_mounts(monitor_); + for (; mounts ; mounts=mounts->next) { + GMount* mount = static_cast(mounts->data); + + MountAdded(mount); + g_object_unref(mount); + } + g_list_free(mounts); + + // Connect signals from the monitor + g_signal_connect(monitor_, "mount-added", G_CALLBACK(MountAddedCallback), this); + g_signal_connect(monitor_, "mount-changed", G_CALLBACK(MountChangedCallback), this); + g_signal_connect(monitor_, "mount-removed", G_CALLBACK(MountRemovedCallback), this); +} + +GioLister::~GioLister() { + if (monitor_) + g_object_unref(monitor_); +} + +QStringList GioLister::DeviceUniqueIDs() { + return QStringList(); +} + +QString GioLister::DeviceIcon(const QString &id) { + return QString(); +} + +QString GioLister::DeviceManufacturer(const QString &id) { + return QString(); +} + +QString GioLister::DeviceModel(const QString &id) { + return QString(); +} + +quint64 GioLister::DeviceCapacity(const QString &id) { + return 0; +} + +quint64 GioLister::DeviceFreeSpace(const QString &id) { + return 0; // TODO +} + +QString GioLister::MakeFriendlyName(const QString &id) { + return QString(); +} + +QVariantMap GioLister::DeviceHardwareInfo(const QString &id) { + return QVariantMap(); +} + +QUrl GioLister::MakeDeviceUrl(const QString &id) { + return QUrl(); +} + +void GioLister::MountAddedCallback(GVolumeMonitor*, GMount* m, gpointer d) { + static_cast(d)->MountAdded(m); +} + +void GioLister::MountChangedCallback(GVolumeMonitor*, GMount* m, gpointer d) { + static_cast(d)->MountChanged(m); +} + +void GioLister::MountRemovedCallback(GVolumeMonitor*, GMount* m, gpointer d) { + static_cast(d)->MountRemoved(m); +} + +void GioLister::MountAdded(GMount *mount) { + qDebug() << "mount added" << g_mount_get_name(mount); +} + +void GioLister::MountChanged(GMount *mount) { + qDebug() << "mount changed" << g_mount_get_name(mount); +} + +void GioLister::MountRemoved(GMount *mount) { + qDebug() << "mount removed" << g_mount_get_name(mount); +} diff --git a/src/devices/giolister.h b/src/devices/giolister.h new file mode 100644 index 000000000..8818e906a --- /dev/null +++ b/src/devices/giolister.h @@ -0,0 +1,59 @@ +/* This file is part of Clementine. + + 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 GIOLISTER_H +#define GIOLISTER_H + +#include "devicelister.h" + +#include + +class GioLister : public DeviceLister { + Q_OBJECT + +public: + GioLister(); + ~GioLister(); + + QStringList DeviceUniqueIDs(); + QString DeviceIcon(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); + + QUrl MakeDeviceUrl(const QString &id); + +protected: + void Init(); + +private: + void MountAdded(GMount* mount); + void MountChanged(GMount* mount); + void MountRemoved(GMount* mount); + + static void MountAddedCallback(GVolumeMonitor*, GMount*, gpointer); + static void MountChangedCallback(GVolumeMonitor*, GMount*, gpointer); + static void MountRemovedCallback(GVolumeMonitor*, GMount*, gpointer); + +private: + GVolumeMonitor* monitor_; +}; + +#endif // GIOLISTER_H diff --git a/src/devices/gpoddevice.cpp b/src/devices/gpoddevice.cpp index f598d6928..ea02c53c4 100644 --- a/src/devices/gpoddevice.cpp +++ b/src/devices/gpoddevice.cpp @@ -24,13 +24,14 @@ #include GPodDevice::GPodDevice( - const QString& mount_point, DeviceLister* lister, const QString& unique_id, - DeviceManager* manager, int database_id, bool first_time) - : ConnectedDevice(lister, unique_id, manager, database_id), + const QUrl& url, DeviceLister* lister, + const QString& unique_id, DeviceManager* manager, + int database_id, bool first_time) + : ConnectedDevice(url, lister, unique_id, manager, database_id, first_time), loader_thread_(new QThread(this)), - loader_(new GPodLoader(mount_point, manager->task_manager(), backend_)) + loader_(new GPodLoader(url.toLocalFile(), manager->task_manager(), backend_)) { - InitBackendDirectory(mount_point, first_time); + InitBackendDirectory(url.toLocalFile(), first_time); model_->Init(); loader_->moveToThread(loader_thread_); diff --git a/src/devices/gpoddevice.h b/src/devices/gpoddevice.h index c9f1dc365..d4d7a06ff 100644 --- a/src/devices/gpoddevice.h +++ b/src/devices/gpoddevice.h @@ -25,11 +25,14 @@ class GPodDevice : public ConnectedDevice { Q_OBJECT public: - GPodDevice(const QString& mount_point, DeviceLister* lister, - const QString& unique_id, DeviceManager* manager, - int database_id, bool first_time); + Q_INVOKABLE GPodDevice( + const QUrl& url, DeviceLister* lister, + const QString& unique_id, DeviceManager* manager, + int database_id, bool first_time); ~GPodDevice(); + static QStringList url_schemes() { return QStringList() << "ipod"; } + private: QThread* loader_thread_; GPodLoader* loader_; diff --git a/src/translations/ar.po b/src/translations/ar.po index ed6ec4da1..aa860dcd0 100644 --- a/src/translations/ar.po +++ b/src/translations/ar.po @@ -1530,6 +1530,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "العنوان" diff --git a/src/translations/cs.po b/src/translations/cs.po index 5167be33a..b036b644f 100644 --- a/src/translations/cs.po +++ b/src/translations/cs.po @@ -1534,6 +1534,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "Tento proud je pouze pro předplatitele" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Titulek" diff --git a/src/translations/da.po b/src/translations/da.po index 8655a7971..b0cdcf986 100644 --- a/src/translations/da.po +++ b/src/translations/da.po @@ -1537,6 +1537,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "Denne stream er kun for betalende abonnenter" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Titel" diff --git a/src/translations/de.po b/src/translations/de.po index 3a9a67116..875556f68 100644 --- a/src/translations/de.po +++ b/src/translations/de.po @@ -1538,6 +1538,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "Nur für zahlende Kunden" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Titel" diff --git a/src/translations/el.po b/src/translations/el.po index 5b4b366d8..09b68aa7e 100644 --- a/src/translations/el.po +++ b/src/translations/el.po @@ -1546,6 +1546,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "Η ροή (stream) αυτή είναι μόνο για συνδρομητές" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Τίτλος" diff --git a/src/translations/en_CA.po b/src/translations/en_CA.po index afb2d45e6..96fad61fe 100644 --- a/src/translations/en_CA.po +++ b/src/translations/en_CA.po @@ -1535,6 +1535,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "This stream is for paid subscribers only" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Title" diff --git a/src/translations/en_GB.po b/src/translations/en_GB.po index da71c6bcf..45aae9d63 100644 --- a/src/translations/en_GB.po +++ b/src/translations/en_GB.po @@ -1532,6 +1532,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "This stream is for paid subscribers only" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Title" diff --git a/src/translations/es.po b/src/translations/es.po index e60bbde89..913843b08 100644 --- a/src/translations/es.po +++ b/src/translations/es.po @@ -1544,6 +1544,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "Este flujo es solo para Suscriptores de Paga" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Título" diff --git a/src/translations/fi.po b/src/translations/fi.po index 3966d0b17..e08bf4d6f 100644 --- a/src/translations/fi.po +++ b/src/translations/fi.po @@ -1532,6 +1532,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Kappale" diff --git a/src/translations/fr.po b/src/translations/fr.po index ea3e24283..3771729ca 100644 --- a/src/translations/fr.po +++ b/src/translations/fr.po @@ -1540,6 +1540,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "Ce flux n'est accessible qu'aux abonnés ayant payé" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Titre" diff --git a/src/translations/gl.po b/src/translations/gl.po index d2c647531..19b026728 100644 --- a/src/translations/gl.po +++ b/src/translations/gl.po @@ -1532,6 +1532,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "Esta stream é só para asinantes" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Título" diff --git a/src/translations/it.po b/src/translations/it.po index 58d03d4a2..17af9a79f 100644 --- a/src/translations/it.po +++ b/src/translations/it.po @@ -1545,6 +1545,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "Questo flusso è riservato ai soli abbonati" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Titolo" diff --git a/src/translations/kk.po b/src/translations/kk.po index c97529ff8..d6489d617 100644 --- a/src/translations/kk.po +++ b/src/translations/kk.po @@ -1532,6 +1532,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Аталуы" diff --git a/src/translations/nb.po b/src/translations/nb.po index 4b76ab6cb..216d83d70 100644 --- a/src/translations/nb.po +++ b/src/translations/nb.po @@ -1534,6 +1534,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "Denne tjenesten er kun for betalende kunder" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Tittel" diff --git a/src/translations/oc.po b/src/translations/oc.po index 04162244c..51eb4ebe1 100644 --- a/src/translations/oc.po +++ b/src/translations/oc.po @@ -1530,6 +1530,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Títol" diff --git a/src/translations/pl.po b/src/translations/pl.po index 95bbd2bdf..279c07f47 100644 --- a/src/translations/pl.po +++ b/src/translations/pl.po @@ -1532,6 +1532,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "Strumień wyłacznie dla płatnych subskrybentów" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Nazwa" diff --git a/src/translations/pt.po b/src/translations/pt.po index 7a8d535d7..f932bb6c2 100644 --- a/src/translations/pt.po +++ b/src/translations/pt.po @@ -1542,6 +1542,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "Esta emissão é apenas para assinantes" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Título" diff --git a/src/translations/pt_BR.po b/src/translations/pt_BR.po index 7d37d437c..9a4f1b09c 100644 --- a/src/translations/pt_BR.po +++ b/src/translations/pt_BR.po @@ -1543,6 +1543,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "Este canal é apenas para assinantes" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Tí­tulo" diff --git a/src/translations/ro.po b/src/translations/ro.po index 3a669f943..ba95caa50 100644 --- a/src/translations/ro.po +++ b/src/translations/ro.po @@ -1531,6 +1531,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Titlu" diff --git a/src/translations/ru.po b/src/translations/ru.po index 4c07e33af..624e932cd 100644 --- a/src/translations/ru.po +++ b/src/translations/ru.po @@ -1537,6 +1537,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "Этот поток только для платных подписчиков" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Название" diff --git a/src/translations/sk.po b/src/translations/sk.po index 591d0c23b..6b5524d10 100644 --- a/src/translations/sk.po +++ b/src/translations/sk.po @@ -1541,6 +1541,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "Tento stream je len pre platiacich odoberateľov" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Názov" diff --git a/src/translations/sv.po b/src/translations/sv.po index 1bee338c4..f8e2d15a1 100644 --- a/src/translations/sv.po +++ b/src/translations/sv.po @@ -1537,6 +1537,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "Den här strömmen är endast för betalande abonnenter" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Titel" diff --git a/src/translations/tr.po b/src/translations/tr.po index 380bf37cd..77ad0b189 100644 --- a/src/translations/tr.po +++ b/src/translations/tr.po @@ -1532,6 +1532,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Başlık" diff --git a/src/translations/translations.pot b/src/translations/translations.pot index 93b0c1cf6..d38b46d89 100644 --- a/src/translations/translations.pot +++ b/src/translations/translations.pot @@ -1520,6 +1520,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "" diff --git a/src/translations/uk.po b/src/translations/uk.po index a3d8c095b..fe857494e 100644 --- a/src/translations/uk.po +++ b/src/translations/uk.po @@ -1541,6 +1541,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "Цей потік лише для платних передплатників" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "Назва" diff --git a/src/translations/zh_CN.po b/src/translations/zh_CN.po index 416c88e25..0af97d3ce 100644 --- a/src/translations/zh_CN.po +++ b/src/translations/zh_CN.po @@ -1530,6 +1530,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr "标题" diff --git a/src/translations/zh_TW.po b/src/translations/zh_TW.po index a636cf03a..8e086869a 100644 --- a/src/translations/zh_TW.po +++ b/src/translations/zh_TW.po @@ -1530,6 +1530,10 @@ msgstr "" msgid "This stream is for paid subscribers only" msgstr "" +#, qt-format +msgid "This type of device is not supported: %1" +msgstr "" + msgid "Title" msgstr ""