Destroy the gpodloader, only load the itunes database once, ensure only one Organiser thread can write to the ipod at once, make Organiser threads wait for the device to be loaded before they start writing.

This commit is contained in:
David Sansome 2010-07-24 17:41:18 +00:00
parent 1d5cef0f0d
commit bc97872bc4
4 changed files with 42 additions and 23 deletions

View File

@ -30,7 +30,7 @@ GPodDevice::GPodDevice(
: ConnectedDevice(url, lister, unique_id, manager, database_id, first_time),
loader_thread_(new QThread(this)),
loader_(new GPodLoader(url.path(), manager->task_manager(), backend_)),
active_copy_db_(NULL)
db_(NULL)
{
InitBackendDirectory(url.path(), first_time);
model_->Init();
@ -39,35 +39,40 @@ GPodDevice::GPodDevice(
connect(loader_, SIGNAL(Error(QString)), SIGNAL(Error(QString)));
connect(loader_, SIGNAL(TaskStarted(int)), SIGNAL(TaskStarted(int)));
connect(loader_, SIGNAL(LoadFinished(Itdb_iTunesDB*)), SLOT(LoadFinished(Itdb_iTunesDB*)));
connect(loader_thread_, SIGNAL(started()), loader_, SLOT(LoadDatabase()));
loader_thread_->start();
// TODO: loader cleanup
}
GPodDevice::~GPodDevice() {
}
void GPodDevice::LoadFinished(Itdb_iTunesDB* db) {
QMutexLocker l(&db_mutex_);
db_ = db;
db_wait_cond_.wakeAll();
loader_->deleteLater();
loader_ = NULL;
}
void GPodDevice::StartCopy() {
active_copy_mutex_.lock();
// Load the iTunes database
GError* error = NULL;
active_copy_db_ = itdb_parse(url_.path().toLocal8Bit(), &error);
// Check for errors
if (!active_copy_db_) {
qDebug() << "GPodDevice error:" << error->message;
emit Error(QString::fromUtf8(error->message));
g_error_free(error);
{
// Wait for the database to be loaded
QMutexLocker l(&db_mutex_);
if (!db_)
db_wait_cond_.wait(&db_mutex_);
}
// Ensure only one "organise files" can be active at any one time
copy_in_progress_.lock();
}
bool GPodDevice::CopyToStorage(
const QString& source, const QString&,
const Song& metadata, bool, bool remove_original)
{
if (!active_copy_db_)
return false;
Q_ASSERT(db_);
// Create the track
Itdb_Track* track = itdb_track_new();
@ -75,8 +80,8 @@ bool GPodDevice::CopyToStorage(
// Add it to the DB and the master playlist
// The DB takes ownership of the track
itdb_track_add(active_copy_db_, track, -1);
Itdb_Playlist* mpl = itdb_playlist_mpl(active_copy_db_);
itdb_track_add(db_, track, -1);
Itdb_Playlist* mpl = itdb_playlist_mpl(db_);
itdb_playlist_add_track(mpl, track, -1);
// Copy the file
@ -97,13 +102,13 @@ bool GPodDevice::CopyToStorage(
void GPodDevice::FinishCopy() {
GError* error = NULL;
itdb_write(active_copy_db_, &error);
itdb_write(db_, &error);
if (error) {
qDebug() << "GPodDevice error:" << error->message;
emit Error(QString::fromUtf8(error->message));
g_error_free(error);
}
active_copy_mutex_.unlock();
copy_in_progress_.unlock();
}

View File

@ -21,6 +21,7 @@
#include "core/musicstorage.h"
#include <QMutex>
#include <QWaitCondition>
class GPodLoader;
@ -43,12 +44,18 @@ public:
const Song &metadata, bool overwrite, bool remove_original);
void FinishCopy();
private slots:
void LoadFinished(Itdb_iTunesDB* db);
private:
QThread* loader_thread_;
GPodLoader* loader_;
QMutex active_copy_mutex_;
Itdb_iTunesDB* active_copy_db_;
QWaitCondition db_wait_cond_;
QMutex db_mutex_;
Itdb_iTunesDB* db_;
QMutex copy_in_progress_;
};
#endif // GPODDEVICE_H

View File

@ -30,6 +30,7 @@ GPodLoader::GPodLoader(const QString& mount_point, TaskManager* task_manager,
task_manager_(task_manager),
backend_(backend)
{
original_thread_ = thread();
}
void GPodLoader::LoadDatabase() {
@ -67,7 +68,8 @@ void GPodLoader::LoadDatabase() {
// Add the songs we've just loaded
backend_->AddOrUpdateSongs(songs);
// Cleanup
itdb_free(db);
moveToThread(original_thread_);
task_manager_->SetTaskFinished(task_id);
emit LoadFinished(db);
}

View File

@ -21,6 +21,8 @@
#include <boost/shared_ptr.hpp>
#include <gpod/itdb.h>
class LibraryBackend;
class TaskManager;
@ -37,8 +39,11 @@ public slots:
signals:
void Error(const QString& message);
void TaskStarted(int task_id);
void LoadFinished(Itdb_iTunesDB* db);
private:
QThread* original_thread_;
QString mount_point_;
TaskManager* task_manager_;
LibraryBackend* backend_;