Add error handling for mtp and gpod device

This commit is contained in:
Jonas Kvinge
2019-01-21 18:58:54 +01:00
parent ad5e366aad
commit 41e2a75675
12 changed files with 93 additions and 45 deletions

View File

@@ -99,6 +99,8 @@ void ConnectedDevice::InitBackendDirectory(const QString &mount_point, bool firs
}
void ConnectedDevice::ConnectAsync() { emit ConnectFinished(unique_id_, true); }
void ConnectedDevice::Eject() {
DeviceInfo *info = manager_->FindDeviceById(unique_id_);

View File

@@ -50,6 +50,7 @@ class ConnectedDevice : public QObject,
~ConnectedDevice();
virtual bool Init() = 0;
virtual void ConnectAsync();
// For some devices (e.g. CD devices) we don't have callbacks to be notified when something change:
// we can call this method to refresh device's state
virtual void Refresh() {}
@@ -71,6 +72,7 @@ class ConnectedDevice : public QObject,
signals:
void TaskStarted(int id);
void SongCountUpdated(int count);
void ConnectFinished(const QString& id, bool success);
protected:
void InitBackendDirectory(const QString &mount_point, bool first_time, bool rewrite_path = true);

View File

@@ -548,12 +548,29 @@ std::shared_ptr<ConnectedDevice> DeviceManager::Connect(DeviceInfo *info) {
connect(info->device_.get(), SIGNAL(TaskStarted(int)), SLOT(DeviceTaskStarted(int)));
connect(info->device_.get(), SIGNAL(SongCountUpdated(int)), SLOT(DeviceSongCountUpdated(int)));
emit DeviceConnected(idx);
connect(info->device_.get(), SIGNAL(ConnectFinished(const QString&, bool)), SLOT(DeviceConnectFinished(const QString&, bool)));
ret->ConnectAsync();
return ret;
}
void DeviceManager::DeviceConnectFinished(const QString &id, bool success) {
DeviceInfo *info = FindDeviceById(id);
if (!info) return;
QModelIndex idx = ItemToIndex(info);
if (!idx.isValid()) return;
if (success) {
emit DeviceConnected(idx);
}
else {
info->device_.reset();
}
}
DeviceInfo *DeviceManager::GetDevice(QModelIndex idx) const {
DeviceInfo *info = IndexToItem(idx);

View File

@@ -125,6 +125,7 @@ class DeviceManager : public SimpleTreeModel<DeviceInfo> {
void TasksChanged();
void DeviceSongCountUpdated(int count);
void LoadAllDevices();
void DeviceConnectFinished(const QString &id, bool success);
protected:
void LazyPopulate(DeviceInfo *item) { LazyPopulate(item, true); }

View File

@@ -59,11 +59,10 @@ bool GPodDevice::Init() {
loader_ = new GPodLoader(url_.path(), app_->task_manager(), backend_, shared_from_this());
loader_->moveToThread(loader_thread_);
connect(loader_, SIGNAL(Error(QString)), SIGNAL(Error(QString)));
connect(loader_, SIGNAL(Error(QString)), SLOT(LoaderError(QString)));
connect(loader_, SIGNAL(TaskStarted(int)), SIGNAL(TaskStarted(int)));
connect(loader_, SIGNAL(LoadFinished(Itdb_iTunesDB*)), SLOT(LoadFinished(Itdb_iTunesDB*)));
connect(loader_, SIGNAL(LoadFinished(Itdb_iTunesDB*, bool)), SLOT(LoadFinished(Itdb_iTunesDB*, bool)));
connect(loader_thread_, SIGNAL(started()), loader_, SLOT(LoadDatabase()));
loader_thread_->start();
return true;
@@ -71,7 +70,13 @@ bool GPodDevice::Init() {
GPodDevice::~GPodDevice() {}
void GPodDevice::LoadFinished(Itdb_iTunesDB *db) {
void GPodDevice::ConnectAsync() {
loader_thread_->start();
}
void GPodDevice::LoadFinished(Itdb_iTunesDB *db, bool success) {
QMutexLocker l(&db_mutex_);
db_ = db;
@@ -87,8 +92,12 @@ void GPodDevice::LoadFinished(Itdb_iTunesDB *db) {
loader_->deleteLater();
loader_ = nullptr;
emit ConnectFinished(unique_id_, success);
}
void GPodDevice::LoaderError(const QString &message) { app_->AddError(message); }
bool GPodDevice::StartCopy(QList<Song::FileType> *supported_filetypes) {
{

View File

@@ -46,19 +46,19 @@ class GPodLoader;
class GPodDevice : public ConnectedDevice, public virtual MusicStorage {
Q_OBJECT
signals:
void Error(const QString &message);
public:
Q_INVOKABLE GPodDevice(
const QUrl &url, DeviceLister *lister,
const QString &unique_id, DeviceManager *manager,
const QString &unique_id,
DeviceManager *manager,
Application *app,
int database_id, bool first_time);
int database_id,
bool first_time);
~GPodDevice();
bool Init();
void ConnectAsync();
static QStringList url_schemes() { return QStringList() << "ipod"; }
@@ -73,7 +73,8 @@ class GPodDevice : public ConnectedDevice, public virtual MusicStorage {
void FinishDelete(bool success);
protected slots:
void LoadFinished(Itdb_iTunesDB *db);
void LoadFinished(Itdb_iTunesDB *db, bool success);
void LoaderError(const QString& message);
protected:
Itdb_Track *AddTrackToITunesDb(const Song &metadata);

View File

@@ -52,6 +52,17 @@ void GPodLoader::LoadDatabase() {
int task_id = task_manager_->StartTask(tr("Loading iPod database"));
emit TaskStarted(task_id);
Itdb_iTunesDB *db = TryLoad();
moveToThread(original_thread_);
task_manager_->SetTaskFinished(task_id);
emit LoadFinished(db, db);
}
Itdb_iTunesDB *GPodLoader::TryLoad() {
// Load the iTunes database
GError *error = nullptr;
Itdb_iTunesDB *db = itdb_parse(QDir::toNativeSeparators(mount_point_).toLocal8Bit(), &error);
@@ -62,12 +73,12 @@ void GPodLoader::LoadDatabase() {
qLog(Error) << "loading database failed:" << error->message;
emit Error(QString::fromUtf8(error->message));
g_error_free(error);
} else {
}
else {
emit Error(tr("An error occurred loading the iTunes database"));
}
task_manager_->SetTaskFinished(task_id);
return;
return db;
}
// Convert all the tracks from libgpod structs into Song classes
@@ -91,10 +102,6 @@ void GPodLoader::LoadDatabase() {
// Add the songs we've just loaded
backend_->AddOrUpdateSongs(songs);
moveToThread(original_thread_);
task_manager_->SetTaskFinished(task_id);
emit LoadFinished(db);
return db;
}

View File

@@ -52,7 +52,10 @@ class GPodLoader : public QObject {
signals:
void Error(const QString &message);
void TaskStarted(int task_id);
void LoadFinished(Itdb_iTunesDB *db);
void LoadFinished(Itdb_iTunesDB *db, bool success);
private:
Itdb_iTunesDB *TryLoad();
private:
std::shared_ptr<ConnectedDevice> device_;

View File

@@ -64,36 +64,39 @@ MtpDevice::~MtpDevice() {}
bool MtpDevice::Init() {
InitBackendDirectory("/", first_time_, false);
model_->Init();
loader_ = new MtpLoader(url_, app_->task_manager(), backend_, shared_from_this());
if (!loader_->Init()) {
delete loader_;
loader_ = nullptr;
return false;
}
model_->Init();
loader_->moveToThread(loader_thread_);
connect(loader_, SIGNAL(Error(QString)), SIGNAL(Error(QString)));
connect(loader_, SIGNAL(Error(QString)), SLOT(LoaderError(QString)));
connect(loader_, SIGNAL(TaskStarted(int)), SIGNAL(TaskStarted(int)));
connect(loader_, SIGNAL(LoadFinished()), SLOT(LoadFinished()));
connect(loader_, SIGNAL(LoadFinished(bool)), SLOT(LoadFinished(bool)));
connect(loader_thread_, SIGNAL(started()), loader_, SLOT(LoadDatabase()));
db_busy_.lock();
loader_thread_->start();
return true;
}
void MtpDevice::LoadFinished() {
void MtpDevice::ConnectAsync() {
db_busy_.lock();
loader_thread_->start();
}
void MtpDevice::LoadFinished(bool success) {
loader_->deleteLater();
loader_ = nullptr;
db_busy_.unlock();
emit ConnectFinished(unique_id_, success);
}
void MtpDevice::LoaderError(const QString& message) { app_->AddError(message); }
bool MtpDevice::StartCopy(QList<Song::FileType> *supported_types) {
// Ensure only one "organise files" can be active at any one time

View File

@@ -54,6 +54,7 @@ class MtpDevice : public ConnectedDevice {
static QStringList url_schemes() { return QStringList() << "mtp" << "gphoto2"; }
bool Init();
void ConnectAsync();
bool GetSupportedFiletypes(QList<Song::FileType>* ret);
int GetFreeSpace();
@@ -68,7 +69,8 @@ class MtpDevice : public ConnectedDevice {
void FinishDelete(bool success);
private slots:
void LoadFinished();
void LoadFinished(bool success);
void LoaderError(const QString& message);
private:
bool GetSupportedFiletypes(QList<Song::FileType> *ret, LIBMTP_mtpdevice_struct *device);

View File

@@ -40,34 +40,35 @@ MtpLoader::MtpLoader(const QUrl &url, TaskManager *task_manager, CollectionBacke
original_thread_ = thread();
}
MtpLoader::~MtpLoader() {
delete connection_;
}
MtpLoader::~MtpLoader() {}
bool MtpLoader::Init() {
connection_ = new MtpConnection(url_);
return connection_->is_valid();
}
bool MtpLoader::Init() { return true; }
void MtpLoader::LoadDatabase() {
int task_id = task_manager_->StartTask(tr("Loading MTP device"));
emit TaskStarted(task_id);
TryLoad();
bool success = TryLoad();
moveToThread(original_thread_);
task_manager_->SetTaskFinished(task_id);
emit LoadFinished();
emit LoadFinished(success);
}
bool MtpLoader::TryLoad() {
MtpConnection dev(url_);
if (!dev.is_valid()) {
emit Error(tr("Error connecting MTP device"));
return false;
}
// Load the list of songs on the device
SongList songs;
LIBMTP_track_t* tracks = LIBMTP_Get_Tracklisting_With_Callback(connection_->device(), nullptr, nullptr);
LIBMTP_track_t* tracks = LIBMTP_Get_Tracklisting_With_Callback(dev.device(), nullptr, nullptr);
while (tracks) {
LIBMTP_track_t *track = tracks;

View File

@@ -51,7 +51,7 @@ class MtpLoader : public QObject {
signals:
void Error(const QString &message);
void TaskStarted(int task_id);
void LoadFinished();
void LoadFinished(bool success);
private:
bool TryLoad();