diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 89dcdc2ab..fe958f91a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 diff --git a/src/core/database.cpp b/src/core/database.cpp index 1ed8fa347..6325d6dd2 100644 --- a/src/core/database.cpp +++ b/src/core/database.cpp @@ -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(QThread::currentThread()))); + const QString connection_id = + QString("%1_thread_%2").arg(connection_id_).arg( + reinterpret_cast(QThread::currentThread())); // Try to find an existing connection for this thread QSqlDatabase db = QSqlDatabase::database(connection_id); diff --git a/src/core/database.h b/src/core/database.h index 49b5ff61b..1833885cb 100644 --- a/src/core/database.h +++ b/src/core/database.h @@ -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_; diff --git a/src/devices/connecteddevice.cpp b/src/devices/connecteddevice.cpp index 2adde5bfc..12bf24d4a 100644 --- a/src/devices/connecteddevice.cpp +++ b/src/devices/connecteddevice.cpp @@ -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 + +ConnectedDevice::ConnectedDevice(DeviceLister* lister, const QString& id, + DeviceManager* manager) + : QObject(manager), + lister_(lister), + unique_id_(id), + manager_(manager), database_(new BackgroundThreadImplementation(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; -} diff --git a/src/devices/connecteddevice.h b/src/devices/connecteddevice.h index 596d3e64d..317e5b4bd 100644 --- a/src/devices/connecteddevice.h +++ b/src/devices/connecteddevice.h @@ -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_; LibraryBackend* backend_; diff --git a/src/devices/devicekitlister.cpp b/src/devices/devicekitlister.cpp index fb61369f7..895285748 100644 --- a/src/devices/devicekitlister.cpp +++ b/src/devices/devicekitlister.cpp @@ -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); } diff --git a/src/devices/devicekitlister.h b/src/devices/devicekitlister.h index a2cf083ab..d92614517 100644 --- a/src/devices/devicekitlister.h +++ b/src/devices/devicekitlister.h @@ -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(); diff --git a/src/devices/devicelister.h b/src/devices/devicelister.h index 62cfe907a..c3770f4ab 100644 --- a/src/devices/devicelister.h +++ b/src/devices/devicelister.h @@ -20,6 +20,7 @@ #include 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); diff --git a/src/devices/devicetest.cpp b/src/devices/devicemanager.cpp similarity index 55% rename from src/devices/devicetest.cpp rename to src/devices/devicemanager.cpp index f0376b2f8..f49aef8cf 100644 --- a/src/devices/devicetest.cpp +++ b/src/devices/devicemanager.cpp @@ -14,15 +14,22 @@ along with Clementine. If not, see . */ -#include "devicetest.h" +#include "connecteddevice.h" +#include "devicemanager.h" #include "devicekitlister.h" -#include - -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(sender()); +void DeviceManager::DeviceAdded(const QString &id) { + DeviceLister* lister = qobject_cast(sender()); qDebug() << "Device added:" << id; for (int i=0 ; iDeviceInfo(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(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(sender()); +void DeviceManager::DeviceChanged(const QString &id) { + DeviceLister* lister = qobject_cast(sender()); qDebug() << "Device changed:" << id; for (int i=0 ; iDeviceInfo(id, i); + qDebug() << i << lister->DeviceInfo(id, i); } } diff --git a/src/devices/devicetest.h b/src/devices/devicemanager.h similarity index 67% rename from src/devices/devicetest.h rename to src/devices/devicemanager.h index f6c4c8f61..e95ecd416 100644 --- a/src/devices/devicetest.h +++ b/src/devices/devicemanager.h @@ -14,27 +14,37 @@ along with Clementine. If not, see . */ -#ifndef DEVICETEST_H -#define DEVICETEST_H +#ifndef DEVICEMANAGER_H +#define DEVICEMANAGER_H #include +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 listers_; + QList devices_; }; -#endif // DEVICETEST_H +#endif // DEVICEMANAGER_H diff --git a/src/devices/filesystemdevice.cpp b/src/devices/filesystemdevice.cpp index 8de9e61f0..8e19bc64e 100644 --- a/src/devices/filesystemdevice.cpp +++ b/src/devices/filesystemdevice.cpp @@ -14,11 +14,50 @@ along with Clementine. If not, see . */ +#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 + +FilesystemDevice::FilesystemDevice( + const QString& mount_point, DeviceLister* lister, const QString& id, + DeviceManager* manager) + : ConnectedDevice(lister, id, manager), + watcher_(new BackgroundThreadImplementation(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__; +} diff --git a/src/devices/filesystemdevice.h b/src/devices/filesystemdevice.h index bd874a786..f8ddff022 100644 --- a/src/devices/filesystemdevice.h +++ b/src/devices/filesystemdevice.h @@ -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* watcher_; }; #endif // FILESYSTEMDEVICE_H diff --git a/src/library/library.cpp b/src/library/library.cpp index a645d8ef4..9ff1dd453 100644 --- a/src/library/library.cpp +++ b/src/library/library.cpp @@ -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))); diff --git a/src/library/librarywatcher.cpp b/src/library/librarywatcher.cpp index 622742ddc..5a93a6930 100644 --- a/src/library/librarywatcher.cpp +++ b/src/library/librarywatcher.cpp @@ -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() { diff --git a/src/library/librarywatcher.h b/src/library/librarywatcher.h index ad2e4185e..af8c81e01 100644 --- a/src/library/librarywatcher.h +++ b/src/library/librarywatcher.h @@ -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_; diff --git a/src/main.cpp b/src/main.cpp index 488721d73..feb8a4241 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -34,8 +34,6 @@ #include "ui/iconloader.h" #include "ui/mainwindow.h" -#include "devices/devicetest.h" // TODO: Remove me - #include #include #include @@ -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()); diff --git a/src/translations/ru.po b/src/translations/ru.po index 8269e65e6..8829ebfcb 100644 --- a/src/translations/ru.po +++ b/src/translations/ru.po @@ -1476,6 +1476,10 @@ msgstr "Обновить коллекцию" msgid "Update the library when Clementine starts" msgstr "Обновить коллекцию при старте Clementine" +#, qt-format +msgid "Updating %1" +msgstr "" + msgid "Updating library" msgstr "Обновление библиотеки" diff --git a/src/translations/translations.pot b/src/translations/translations.pot index 3bded7d20..e60c3795d 100644 --- a/src/translations/translations.pot +++ b/src/translations/translations.pot @@ -1460,6 +1460,10 @@ msgstr "" msgid "Update the library when Clementine starts" msgstr "" +#, qt-format +msgid "Updating %1" +msgstr "" + msgid "Updating library" msgstr "" diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index fceb7316f..124bf087e 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -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), diff --git a/src/ui/mainwindow.h b/src/ui/mainwindow.h index e5f2fe86d..6ca80d244 100644 --- a/src/ui/mainwindow.h +++ b/src/ui/mainwindow.h @@ -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 settings_dialog_; boost::scoped_ptr add_stream_dialog_; boost::scoped_ptr cover_manager_;