mirror of
https://github.com/clementine-player/Clementine
synced 2025-01-29 02:29:56 +01:00
Add a DeviceManager which holds all the listers and connected devices. Make FilesystemDevices use their own LibraryWatcher.
This commit is contained in:
parent
28ea240eb8
commit
2deca7fd61
@ -55,7 +55,7 @@ set(SOURCES
|
||||
devices/connecteddevice.cpp
|
||||
devices/devicekitlister.cpp
|
||||
devices/devicelister.cpp
|
||||
devices/devicetest.cpp
|
||||
devices/devicemanager.cpp
|
||||
devices/filesystemdevice.cpp
|
||||
|
||||
engines/enginebase.cpp
|
||||
@ -177,7 +177,7 @@ set(HEADERS
|
||||
devices/connecteddevice.h
|
||||
devices/devicekitlister.h
|
||||
devices/devicelister.h
|
||||
devices/devicetest.h
|
||||
devices/devicemanager.h
|
||||
devices/filesystemdevice.h
|
||||
|
||||
engines/enginebase.h
|
||||
|
@ -29,6 +29,9 @@
|
||||
const char* Database::kDatabaseFilename = "clementine.db";
|
||||
const int Database::kSchemaVersion = 13;
|
||||
|
||||
int Database::sNextConnectionId = 1;
|
||||
QMutex Database::sNextConnectionIdMutex;
|
||||
|
||||
Database::Token::Token(const QString& token, int start, int end)
|
||||
: token(token),
|
||||
start_offset(start),
|
||||
@ -320,6 +323,11 @@ Database::Database(QObject* parent, const QString& database_name)
|
||||
injected_database_name_(database_name),
|
||||
query_hash_(0)
|
||||
{
|
||||
{
|
||||
QMutexLocker l(&sNextConnectionIdMutex);
|
||||
connection_id_ = sNextConnectionId ++;
|
||||
}
|
||||
|
||||
directory_ = QDir::toNativeSeparators(
|
||||
QDir::homePath() + "/.config/" + QCoreApplication::organizationName());
|
||||
|
||||
@ -337,8 +345,9 @@ QSqlDatabase Database::Connect() {
|
||||
}
|
||||
}
|
||||
|
||||
const QString connection_id("thread_" + QString::number(
|
||||
reinterpret_cast<quint64>(QThread::currentThread())));
|
||||
const QString connection_id =
|
||||
QString("%1_thread_%2").arg(connection_id_).arg(
|
||||
reinterpret_cast<quint64>(QThread::currentThread()));
|
||||
|
||||
// Try to find an existing connection for this thread
|
||||
QSqlDatabase db = QSqlDatabase::database(connection_id);
|
||||
|
@ -60,6 +60,13 @@ class Database : public QObject {
|
||||
QMutex connect_mutex_;
|
||||
QMutex mutex_;
|
||||
|
||||
// This ID makes the QSqlDatabase name unique to the object as well as the
|
||||
// thread
|
||||
int connection_id_;
|
||||
|
||||
static QMutex sNextConnectionIdMutex;
|
||||
static int sNextConnectionId;
|
||||
|
||||
// Used by tests
|
||||
QString injected_database_name_;
|
||||
|
||||
|
@ -15,18 +15,25 @@
|
||||
*/
|
||||
|
||||
#include "connecteddevice.h"
|
||||
#include "devicemanager.h"
|
||||
#include "core/database.h"
|
||||
#include "library/library.h"
|
||||
#include "library/librarybackend.h"
|
||||
#include "library/librarymodel.h"
|
||||
|
||||
ConnectedDevice::ConnectedDevice(QObject *parent)
|
||||
: QObject(parent),
|
||||
lister_(NULL),
|
||||
#include <QtDebug>
|
||||
|
||||
ConnectedDevice::ConnectedDevice(DeviceLister* lister, const QString& id,
|
||||
DeviceManager* manager)
|
||||
: QObject(manager),
|
||||
lister_(lister),
|
||||
unique_id_(id),
|
||||
manager_(manager),
|
||||
database_(new BackgroundThreadImplementation<Database, MemoryDatabase>(this)),
|
||||
backend_(NULL),
|
||||
model_(NULL)
|
||||
{
|
||||
qDebug() << __PRETTY_FUNCTION__;
|
||||
// Wait for the database thread to start
|
||||
database_->Start(true);
|
||||
|
||||
@ -39,8 +46,3 @@ ConnectedDevice::ConnectedDevice(QObject *parent)
|
||||
// Create the model
|
||||
model_ = new LibraryModel(backend_, this);
|
||||
}
|
||||
|
||||
void ConnectedDevice::set_lister(DeviceLister *lister, const QString &id) {
|
||||
lister_ = lister;
|
||||
unique_id_ = id;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
class Database;
|
||||
class DeviceLister;
|
||||
class DeviceManager;
|
||||
class LibraryBackend;
|
||||
class LibraryModel;
|
||||
|
||||
@ -30,9 +31,8 @@ class ConnectedDevice : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ConnectedDevice(QObject *parent = 0);
|
||||
ConnectedDevice(DeviceLister* lister, const QString& id, DeviceManager* manager);
|
||||
|
||||
void set_lister(DeviceLister* lister, const QString& id);
|
||||
DeviceLister* lister() const { return lister_; }
|
||||
QString unique_id() const { return unique_id_; }
|
||||
|
||||
@ -41,6 +41,7 @@ public:
|
||||
protected:
|
||||
DeviceLister* lister_;
|
||||
QString unique_id_;
|
||||
DeviceManager* manager_;
|
||||
|
||||
BackgroundThread<Database>* database_;
|
||||
LibraryBackend* backend_;
|
||||
|
@ -217,6 +217,8 @@ QString DeviceKitLister::FindUniqueIdByPath(const QDBusObjectPath &path) const {
|
||||
return QString();
|
||||
}
|
||||
|
||||
ConnectedDevice* DeviceKitLister::Connect(const QString &id, QObject *parent) {
|
||||
return new FilesystemDevice(DeviceInfo(id, Field_MountPath).toString(), parent);
|
||||
ConnectedDevice* DeviceKitLister::Connect(const QString &id, DeviceManager* manager) {
|
||||
return new FilesystemDevice(
|
||||
DeviceInfo(id, Field_MountPath).toString(),
|
||||
this, id, manager);
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ public:
|
||||
QStringList DeviceUniqueIDs();
|
||||
QVariant DeviceInfo(const QString& id, int field);
|
||||
|
||||
ConnectedDevice* Connect(const QString &id, QObject *parent);
|
||||
ConnectedDevice* Connect(const QString &id, DeviceManager* manager);
|
||||
|
||||
protected:
|
||||
void Init();
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
class ConnectedDevice;
|
||||
class DeviceManager;
|
||||
|
||||
class DeviceLister : public QObject {
|
||||
Q_OBJECT
|
||||
@ -49,7 +50,7 @@ public:
|
||||
|
||||
// Create a new ConnectedDevice instance for the given device. Must be
|
||||
// thread-safe.
|
||||
virtual ConnectedDevice* Connect(const QString& id, QObject* parent) = 0;
|
||||
virtual ConnectedDevice* Connect(const QString& id, DeviceManager* manager) = 0;
|
||||
|
||||
signals:
|
||||
void DeviceAdded(const QString& id);
|
||||
|
@ -14,15 +14,22 @@
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "devicetest.h"
|
||||
#include "connecteddevice.h"
|
||||
#include "devicemanager.h"
|
||||
#include "devicekitlister.h"
|
||||
|
||||
#include <QtDebug>
|
||||
|
||||
DeviceTest::DeviceTest(QObject *parent)
|
||||
: QObject(parent)
|
||||
DeviceManager::DeviceManager(TaskManager* task_manager, QObject *parent)
|
||||
: QObject(parent),
|
||||
task_manager_(task_manager)
|
||||
{
|
||||
DeviceLister* lister = new DeviceKitLister;
|
||||
AddLister(new DeviceKitLister);
|
||||
}
|
||||
|
||||
DeviceManager::~DeviceManager() {
|
||||
qDeleteAll(listers_);
|
||||
}
|
||||
|
||||
void DeviceManager::AddLister(DeviceLister *lister) {
|
||||
listers_ << lister;
|
||||
connect(lister, SIGNAL(DeviceAdded(QString)), SLOT(DeviceAdded(QString)));
|
||||
connect(lister, SIGNAL(DeviceRemoved(QString)), SLOT(DeviceRemoved(QString)));
|
||||
@ -31,28 +38,36 @@ DeviceTest::DeviceTest(QObject *parent)
|
||||
lister->Start();
|
||||
}
|
||||
|
||||
DeviceTest::~DeviceTest() {
|
||||
qDeleteAll(listers_);
|
||||
}
|
||||
|
||||
void DeviceTest::DeviceAdded(const QString &id) {
|
||||
DeviceLister* engine = qobject_cast<DeviceLister*>(sender());
|
||||
void DeviceManager::DeviceAdded(const QString &id) {
|
||||
DeviceLister* lister = qobject_cast<DeviceLister*>(sender());
|
||||
|
||||
qDebug() << "Device added:" << id;
|
||||
for (int i=0 ; i<DeviceKitLister::LastField ; ++i) {
|
||||
qDebug() << i << engine->DeviceInfo(id, i);
|
||||
qDebug() << i << lister->DeviceInfo(id, i);
|
||||
}
|
||||
|
||||
ConnectedDevice* device = lister->Connect(id, this);
|
||||
devices_ << device;
|
||||
}
|
||||
|
||||
void DeviceManager::DeviceRemoved(const QString &id) {
|
||||
DeviceLister* lister = qobject_cast<DeviceLister*>(sender());
|
||||
|
||||
qDebug() << "Device removed:" << id;
|
||||
foreach (ConnectedDevice* device, devices_) {
|
||||
if (device->lister() == lister && device->unique_id() == id) {
|
||||
delete device;
|
||||
devices_.removeAll(device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceTest::DeviceRemoved(const QString &id) {
|
||||
qDebug() << "Device removed:" << id;
|
||||
}
|
||||
|
||||
void DeviceTest::DeviceChanged(const QString &id) {
|
||||
DeviceLister* engine = qobject_cast<DeviceLister*>(sender());
|
||||
void DeviceManager::DeviceChanged(const QString &id) {
|
||||
DeviceLister* lister = qobject_cast<DeviceLister*>(sender());
|
||||
|
||||
qDebug() << "Device changed:" << id;
|
||||
for (int i=0 ; i<DeviceKitLister::LastField ; ++i) {
|
||||
qDebug() << i << engine->DeviceInfo(id, i);
|
||||
qDebug() << i << lister->DeviceInfo(id, i);
|
||||
}
|
||||
}
|
@ -14,27 +14,37 @@
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DEVICETEST_H
|
||||
#define DEVICETEST_H
|
||||
#ifndef DEVICEMANAGER_H
|
||||
#define DEVICEMANAGER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class ConnectedDevice;
|
||||
class DeviceLister;
|
||||
class TaskManager;
|
||||
|
||||
class DeviceTest : public QObject {
|
||||
class DeviceManager : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DeviceTest(QObject* parent = 0);
|
||||
~DeviceTest();
|
||||
DeviceManager(TaskManager* task_manager, QObject* parent = 0);
|
||||
~DeviceManager();
|
||||
|
||||
public slots:
|
||||
TaskManager* task_manager() const { return task_manager_; }
|
||||
|
||||
private slots:
|
||||
void DeviceAdded(const QString& id);
|
||||
void DeviceRemoved(const QString& id);
|
||||
void DeviceChanged(const QString& id);
|
||||
|
||||
private:
|
||||
void AddLister(DeviceLister* lister);
|
||||
|
||||
private:
|
||||
TaskManager* task_manager_;
|
||||
|
||||
QList<DeviceLister*> listers_;
|
||||
QList<ConnectedDevice*> devices_;
|
||||
};
|
||||
|
||||
#endif // DEVICETEST_H
|
||||
#endif // DEVICEMANAGER_H
|
@ -14,11 +14,50 @@
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "devicelister.h"
|
||||
#include "devicemanager.h"
|
||||
#include "filesystemdevice.h"
|
||||
#include "library/librarybackend.h"
|
||||
#include "library/librarywatcher.h"
|
||||
|
||||
FilesystemDevice::FilesystemDevice(const QString& mount_point, QObject* parent)
|
||||
: ConnectedDevice(parent)
|
||||
#include <QtDebug>
|
||||
|
||||
FilesystemDevice::FilesystemDevice(
|
||||
const QString& mount_point, DeviceLister* lister, const QString& id,
|
||||
DeviceManager* manager)
|
||||
: ConnectedDevice(lister, id, manager),
|
||||
watcher_(new BackgroundThreadImplementation<LibraryWatcher, LibraryWatcher>(this))
|
||||
{
|
||||
// Create the library watcher
|
||||
watcher_->Start(true);
|
||||
watcher_->Worker()->set_device_name(lister_->DeviceInfo(
|
||||
unique_id_, DeviceLister::Field_FriendlyName).toString());
|
||||
watcher_->Worker()->set_backend(backend_);
|
||||
watcher_->Worker()->set_task_manager(manager_->task_manager());
|
||||
|
||||
// To make the connections below less verbose
|
||||
LibraryWatcher* watcher = watcher_->Worker().get();
|
||||
|
||||
connect(backend_, SIGNAL(DirectoryDiscovered(Directory,SubdirectoryList)),
|
||||
watcher, SLOT(AddDirectory(Directory,SubdirectoryList)));
|
||||
connect(backend_, SIGNAL(DirectoryDeleted(Directory)),
|
||||
watcher, SLOT(RemoveDirectory(Directory)));
|
||||
connect(watcher, SIGNAL(NewOrUpdatedSongs(SongList)),
|
||||
backend_, SLOT(AddOrUpdateSongs(SongList)));
|
||||
connect(watcher, SIGNAL(SongsMTimeUpdated(SongList)),
|
||||
backend_, SLOT(UpdateMTimesOnly(SongList)));
|
||||
connect(watcher, SIGNAL(SongsDeleted(SongList)),
|
||||
backend_, SLOT(DeleteSongs(SongList)));
|
||||
connect(watcher, SIGNAL(SubdirsDiscovered(SubdirectoryList)),
|
||||
backend_, SLOT(AddOrUpdateSubdirs(SubdirectoryList)));
|
||||
connect(watcher, SIGNAL(SubdirsMTimeUpdated(SubdirectoryList)),
|
||||
backend_, SLOT(AddOrUpdateSubdirs(SubdirectoryList)));
|
||||
connect(watcher, SIGNAL(CompilationsNeedUpdating()),
|
||||
backend_, SLOT(UpdateCompilations()));
|
||||
|
||||
backend_->AddDirectory(mount_point);
|
||||
}
|
||||
|
||||
FilesystemDevice::~FilesystemDevice() {
|
||||
qDebug() << __PRETTY_FUNCTION__;
|
||||
}
|
||||
|
@ -19,11 +19,19 @@
|
||||
|
||||
#include "connecteddevice.h"
|
||||
|
||||
class DeviceManager;
|
||||
class LibraryWatcher;
|
||||
|
||||
class FilesystemDevice : public ConnectedDevice {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FilesystemDevice(const QString& mount_point, QObject* parent = 0);
|
||||
FilesystemDevice(const QString& mount_point, DeviceLister* lister,
|
||||
const QString& id, DeviceManager* manager);
|
||||
~FilesystemDevice();
|
||||
|
||||
private:
|
||||
BackgroundThread<LibraryWatcher>* watcher_;
|
||||
};
|
||||
|
||||
#endif // FILESYSTEMDEVICE_H
|
||||
|
@ -61,8 +61,8 @@ void Library::StartThreads() {
|
||||
void Library::WatcherInitialised() {
|
||||
LibraryWatcher* watcher = watcher_->Worker().get();
|
||||
|
||||
watcher->SetBackend(backend_);
|
||||
watcher->SetTaskManager(task_manager_);
|
||||
watcher->set_backend(backend_);
|
||||
watcher->set_task_manager(task_manager_);
|
||||
|
||||
connect(backend_, SIGNAL(DirectoryDiscovered(Directory,SubdirectoryList)),
|
||||
watcher, SLOT(AddDirectory(Directory,SubdirectoryList)));
|
||||
|
@ -67,7 +67,13 @@ LibraryWatcher::ScanTransaction::ScanTransaction(LibraryWatcher* watcher,
|
||||
cached_songs_dirty_(true),
|
||||
known_subdirs_dirty_(true)
|
||||
{
|
||||
task_id_ = watcher_->task_manager_->StartTask(tr("Updating library"));
|
||||
QString description;
|
||||
if (watcher_->device_name_.isEmpty())
|
||||
description = tr("Updating library");
|
||||
else
|
||||
description = tr("Updating %1").arg(watcher_->device_name_);
|
||||
|
||||
task_id_ = watcher_->task_manager_->StartTask(description);
|
||||
}
|
||||
|
||||
LibraryWatcher::ScanTransaction::~ScanTransaction() {
|
||||
|
@ -38,8 +38,10 @@ class LibraryWatcher : public QObject {
|
||||
|
||||
static const char* kSettingsGroup;
|
||||
|
||||
void SetBackend(LibraryBackend* backend) { backend_ = backend; }
|
||||
void SetTaskManager(TaskManager* task_manager) { task_manager_ = task_manager; }
|
||||
void set_backend(LibraryBackend* backend) { backend_ = backend; }
|
||||
void set_task_manager(TaskManager* task_manager) { task_manager_ = task_manager; }
|
||||
void set_device_name(const QString& device_name) { device_name_ = device_name; }
|
||||
|
||||
void IncrementalScanAsync();
|
||||
void SetRescanPausedAsync(bool pause);
|
||||
|
||||
@ -135,6 +137,7 @@ class LibraryWatcher : public QObject {
|
||||
|
||||
LibraryBackend* backend_;
|
||||
TaskManager* task_manager_;
|
||||
QString device_name_;
|
||||
bool stop_requested_;
|
||||
bool scan_on_startup_;
|
||||
|
||||
|
@ -34,8 +34,6 @@
|
||||
#include "ui/iconloader.h"
|
||||
#include "ui/mainwindow.h"
|
||||
|
||||
#include "devices/devicetest.h" // TODO: Remove me
|
||||
|
||||
#include <QtSingleApplication>
|
||||
#include <QtDebug>
|
||||
#include <QLibraryInfo>
|
||||
@ -166,8 +164,6 @@ int main(int argc, char *argv[]) {
|
||||
MPRIS mpris;
|
||||
#endif
|
||||
|
||||
DeviceTest device_test; // TODO: Remove me (and the header)
|
||||
|
||||
// Window
|
||||
MainWindow w(&network, options.engine());
|
||||
|
||||
|
@ -1476,6 +1476,10 @@ msgstr "Обновить коллекцию"
|
||||
msgid "Update the library when Clementine starts"
|
||||
msgstr "Обновить коллекцию при старте Clementine"
|
||||
|
||||
#, qt-format
|
||||
msgid "Updating %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Updating library"
|
||||
msgstr "Обновление библиотеки"
|
||||
|
||||
|
@ -1460,6 +1460,10 @@ msgstr ""
|
||||
msgid "Update the library when Clementine starts"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "Updating %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Updating library"
|
||||
msgstr ""
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "core/songloader.h"
|
||||
#include "core/stylesheetloader.h"
|
||||
#include "core/taskmanager.h"
|
||||
#include "devices/devicemanager.h"
|
||||
#include "engines/enginebase.h"
|
||||
#include "library/groupbydialog.h"
|
||||
#include "library/libraryconfig.h"
|
||||
@ -117,6 +118,7 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg
|
||||
player_(NULL),
|
||||
library_(NULL),
|
||||
global_shortcuts_(new GlobalShortcuts(this)),
|
||||
devices_(new DeviceManager(task_manager_, this)),
|
||||
settings_dialog_(NULL),
|
||||
add_stream_dialog_(new AddStreamDialog),
|
||||
cover_manager_(NULL),
|
||||
|
@ -34,6 +34,7 @@ class AddStreamDialog;
|
||||
class AlbumCoverManager;
|
||||
class CommandlineOptions;
|
||||
class Database;
|
||||
class DeviceManager;
|
||||
class EditTagDialog;
|
||||
class Equalizer;
|
||||
class ErrorDialog;
|
||||
@ -184,6 +185,8 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
||||
Library* library_;
|
||||
GlobalShortcuts* global_shortcuts_;
|
||||
|
||||
DeviceManager* devices_;
|
||||
|
||||
boost::scoped_ptr<SettingsDialog> settings_dialog_;
|
||||
boost::scoped_ptr<AddStreamDialog> add_stream_dialog_;
|
||||
boost::scoped_ptr<AlbumCoverManager> cover_manager_;
|
||||
|
Loading…
x
Reference in New Issue
Block a user