Add error handling for mtp and gpod device
This commit is contained in:
@@ -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_);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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) {
|
||||
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user