Start of work on a GIO/GVFS device backend.
This commit is contained in:
parent
40a2302311
commit
0dcdf36535
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -40,5 +40,6 @@
|
||||
#cmakedefine HAVE_STATIC_SQLITE
|
||||
|
||||
#cmakedefine HAVE_LIBGPOD
|
||||
#cmakedefine HAVE_GIO
|
||||
|
||||
#endif // CONFIG_H_IN
|
||||
|
@ -23,8 +23,9 @@
|
||||
|
||||
#include <QtDebug>
|
||||
|
||||
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),
|
||||
|
@ -18,6 +18,8 @@
|
||||
#define CONNECTEDDEVICE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
#include <QUrl>
|
||||
|
||||
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_; }
|
||||
|
@ -236,23 +236,15 @@ QString DeviceKitLister::FindUniqueIdByPath(const QDBusObjectPath &path) const {
|
||||
return QString();
|
||||
}
|
||||
|
||||
boost::shared_ptr<ConnectedDevice> 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<ConnectedDevice> 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);
|
||||
}
|
||||
|
@ -45,9 +45,7 @@ public:
|
||||
|
||||
QString MakeFriendlyName(const QString &id);
|
||||
|
||||
boost::shared_ptr<ConnectedDevice> Connect(
|
||||
const QString &unique_id, DeviceManager* manager, int database_id,
|
||||
bool first_time);
|
||||
QUrl MakeDeviceUrl(const QString &id);
|
||||
|
||||
protected:
|
||||
void Init();
|
||||
|
@ -18,6 +18,7 @@
|
||||
#define DEVICELISTER_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QUrl>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
@ -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<ConnectedDevice> 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);
|
||||
|
@ -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 <QIcon>
|
||||
#include <QPainter>
|
||||
#include <QUrl>
|
||||
|
||||
const int DeviceManager::kDeviceIconSize = 32;
|
||||
const int DeviceManager::kDeviceIconOverlaySize = 16;
|
||||
@ -99,6 +102,15 @@ DeviceManager::DeviceManager(BackgroundThread<Database>* database,
|
||||
#ifdef Q_WS_X11
|
||||
AddLister(new DeviceKitLister);
|
||||
#endif
|
||||
#ifdef HAVE_GIO
|
||||
AddLister(new GioLister);
|
||||
#endif
|
||||
|
||||
AddDeviceClass<FilesystemDevice>();
|
||||
|
||||
#ifdef HAVE_LIBGPOD
|
||||
AddDeviceClass<GPodDevice>();
|
||||
#endif
|
||||
}
|
||||
|
||||
DeviceManager::~DeviceManager() {
|
||||
@ -262,8 +274,10 @@ boost::shared_ptr<ConnectedDevice> DeviceManager::Connect(int row) {
|
||||
if (info.device_) // Already connected
|
||||
return info.device_;
|
||||
|
||||
boost::shared_ptr<ConnectedDevice> ret;
|
||||
|
||||
if (!info.lister_) // Not physically connected
|
||||
return boost::shared_ptr<ConnectedDevice>();
|
||||
return ret;
|
||||
|
||||
bool first_time = (info.database_id_ == -1);
|
||||
if (first_time) {
|
||||
@ -271,12 +285,33 @@ boost::shared_ptr<ConnectedDevice> 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<ConnectedDevice*>(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<ConnectedDevice> DeviceManager::GetConnectedDevice(int row) const {
|
||||
|
@ -123,6 +123,7 @@ private:
|
||||
};
|
||||
|
||||
void AddLister(DeviceLister* lister);
|
||||
template <typename T> void AddDeviceClass();
|
||||
|
||||
DeviceDatabaseBackend::Device InfoToDatabaseDevice(const DeviceInfo& info) const;
|
||||
|
||||
@ -136,8 +137,20 @@ private:
|
||||
QList<DeviceLister*> listers_;
|
||||
QList<DeviceInfo> devices_;
|
||||
|
||||
QMultiMap<QString, QMetaObject> device_classes_;
|
||||
|
||||
// Map of task ID to device index
|
||||
QMap<int, QPersistentModelIndex> active_tasks_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
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
|
||||
|
@ -24,9 +24,10 @@
|
||||
#include <QtDebug>
|
||||
|
||||
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<LibraryWatcher, LibraryWatcher>(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();
|
||||
}
|
||||
|
@ -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<LibraryWatcher>* watcher_;
|
||||
};
|
||||
|
109
src/devices/giolister.cpp
Normal file
109
src/devices/giolister.cpp
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "giolister.h"
|
||||
|
||||
#include <QStringList>
|
||||
#include <QtDebug>
|
||||
|
||||
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<GMount*>(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<GioLister*>(d)->MountAdded(m);
|
||||
}
|
||||
|
||||
void GioLister::MountChangedCallback(GVolumeMonitor*, GMount* m, gpointer d) {
|
||||
static_cast<GioLister*>(d)->MountChanged(m);
|
||||
}
|
||||
|
||||
void GioLister::MountRemovedCallback(GVolumeMonitor*, GMount* m, gpointer d) {
|
||||
static_cast<GioLister*>(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);
|
||||
}
|
59
src/devices/giolister.h
Normal file
59
src/devices/giolister.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GIOLISTER_H
|
||||
#define GIOLISTER_H
|
||||
|
||||
#include "devicelister.h"
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
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
|
@ -24,13 +24,14 @@
|
||||
#include <gpod/itdb.h>
|
||||
|
||||
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_);
|
||||
|
@ -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_;
|
||||
|
@ -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 "العنوان"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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 "Τίτλος"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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 "Аталуы"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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 "Название"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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 ""
|
||||
|
||||
|
@ -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 "Назва"
|
||||
|
||||
|
@ -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 "标题"
|
||||
|
||||
|
@ -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 ""
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user