Test whether we can still talk to afc before freeing the lockdownd client (fixes usbmuxd errors once and for all), report afc copy errors, keep track of files that failed to copy to a device, don't attempt to write the itunesdb if there were errors during copying.
This commit is contained in:
parent
9d2a4783ff
commit
b27238a480
|
@ -76,7 +76,7 @@ void DeleteFiles::ProcessSomeFiles() {
|
||||||
if (progress_ >= songs_.count()) {
|
if (progress_ >= songs_.count()) {
|
||||||
task_manager_->SetTaskProgress(task_id_, progress_, songs_.count());
|
task_manager_->SetTaskProgress(task_id_, progress_, songs_.count());
|
||||||
|
|
||||||
storage_->FinishCopy();
|
storage_->FinishCopy(songs_with_errors_.isEmpty());
|
||||||
|
|
||||||
task_manager_->SetTaskFinished(task_id_);
|
task_manager_->SetTaskFinished(task_id_);
|
||||||
|
|
||||||
|
@ -96,7 +96,11 @@ void DeleteFiles::ProcessSomeFiles() {
|
||||||
for ( ; progress_<n ; ++progress_) {
|
for ( ; progress_<n ; ++progress_) {
|
||||||
task_manager_->SetTaskProgress(task_id_, progress_, songs_.count());
|
task_manager_->SetTaskProgress(task_id_, progress_, songs_.count());
|
||||||
|
|
||||||
storage_->DeleteFromStorage(songs_.at(progress_));
|
const Song& song = songs_[progress_];
|
||||||
|
|
||||||
|
if (!storage_->DeleteFromStorage(song)) {
|
||||||
|
songs_with_errors_ << song;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QTimer::singleShot(0, this, SLOT(ProcessSomeFiles()));
|
QTimer::singleShot(0, this, SLOT(ProcessSomeFiles()));
|
||||||
|
|
|
@ -53,6 +53,8 @@ private:
|
||||||
|
|
||||||
int task_id_;
|
int task_id_;
|
||||||
int progress_;
|
int progress_;
|
||||||
|
|
||||||
|
SongList songs_with_errors_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DELETEFILES_H
|
#endif // DELETEFILES_H
|
||||||
|
|
|
@ -40,11 +40,11 @@ public:
|
||||||
virtual bool CopyToStorage(const QString& source, const QString& destination,
|
virtual bool CopyToStorage(const QString& source, const QString& destination,
|
||||||
const Song& metadata, bool overwrite,
|
const Song& metadata, bool overwrite,
|
||||||
bool remove_original) = 0;
|
bool remove_original) = 0;
|
||||||
virtual void FinishCopy() {}
|
virtual void FinishCopy(bool success) {}
|
||||||
|
|
||||||
virtual void StartDelete() {}
|
virtual void StartDelete() {}
|
||||||
virtual bool DeleteFromStorage(const Song& metadata) = 0;
|
virtual bool DeleteFromStorage(const Song& metadata) = 0;
|
||||||
virtual void FinishDelete() {}
|
virtual void FinishDelete(bool success) {}
|
||||||
|
|
||||||
virtual void Eject() {}
|
virtual void Eject() {}
|
||||||
};
|
};
|
||||||
|
|
|
@ -68,7 +68,7 @@ void Organise::ProcessSomeFiles() {
|
||||||
if (progress_ >= files_.count()) {
|
if (progress_ >= files_.count()) {
|
||||||
task_manager_->SetTaskProgress(task_id_, progress_, files_.count());
|
task_manager_->SetTaskProgress(task_id_, progress_, files_.count());
|
||||||
|
|
||||||
destination_->FinishCopy();
|
destination_->FinishCopy(files_with_errors_.isEmpty());
|
||||||
if (eject_after_)
|
if (eject_after_)
|
||||||
destination_->Eject();
|
destination_->Eject();
|
||||||
|
|
||||||
|
@ -110,8 +110,10 @@ void Organise::ProcessSomeFiles() {
|
||||||
if (!song.is_valid())
|
if (!song.is_valid())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
destination_->CopyToStorage(filename, format_.GetFilenameForSong(song),
|
if (!destination_->CopyToStorage(filename, format_.GetFilenameForSong(song),
|
||||||
song, overwrite_, !copy_);
|
song, overwrite_, !copy_)) {
|
||||||
|
files_with_errors_ << filename;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QTimer::singleShot(0, this, SLOT(ProcessSomeFiles()));
|
QTimer::singleShot(0, this, SLOT(ProcessSomeFiles()));
|
||||||
|
|
|
@ -58,6 +58,8 @@ private:
|
||||||
|
|
||||||
int task_id_;
|
int task_id_;
|
||||||
int progress_;
|
int progress_;
|
||||||
|
|
||||||
|
QStringList files_with_errors_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ORGANISE_H
|
#endif // ORGANISE_H
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QIODevice>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QTemporaryFile>
|
#include <QTemporaryFile>
|
||||||
|
|
||||||
|
@ -135,4 +136,44 @@ void RemoveRecursive(const QString& path) {
|
||||||
dir.rmdir(path);
|
dir.rmdir(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Copy(QIODevice* source, QIODevice* destination) {
|
||||||
|
if (!source->open(QIODevice::ReadOnly))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!destination->open(QIODevice::WriteOnly))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const qint64 bytes = source->size();
|
||||||
|
char* data = new char[bytes];
|
||||||
|
qint64 pos = 0;
|
||||||
|
|
||||||
|
forever {
|
||||||
|
const qint64 bytes_read = source->read(data + pos, bytes - pos);
|
||||||
|
if (bytes_read == -1) {
|
||||||
|
delete[] data;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += bytes_read;
|
||||||
|
if (bytes_read == 0 || pos == bytes)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = 0;
|
||||||
|
forever {
|
||||||
|
const qint64 bytes_written = destination->write(data + pos, bytes - pos);
|
||||||
|
if (bytes_written == -1) {
|
||||||
|
delete[] data;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += bytes_written;
|
||||||
|
if (bytes_written == 0 || pos == bytes)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] data;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
|
class QIODevice;
|
||||||
|
|
||||||
namespace Utilities {
|
namespace Utilities {
|
||||||
QString PrettyTime(int seconds);
|
QString PrettyTime(int seconds);
|
||||||
QString PrettySize(quint64 bytes);
|
QString PrettySize(quint64 bytes);
|
||||||
|
@ -29,6 +31,7 @@ namespace Utilities {
|
||||||
|
|
||||||
QString MakeTempDir();
|
QString MakeTempDir();
|
||||||
void RemoveRecursive(const QString& path);
|
void RemoveRecursive(const QString& path);
|
||||||
|
bool Copy(QIODevice* source, QIODevice* destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // UTILITIES_H
|
#endif // UTILITIES_H
|
||||||
|
|
|
@ -94,9 +94,8 @@ bool AfcDevice::CopyToStorage(
|
||||||
{
|
{
|
||||||
QFile source_file(source);
|
QFile source_file(source);
|
||||||
AfcFile dest_file(&connection, dest);
|
AfcFile dest_file(&connection, dest);
|
||||||
source_file.open(QIODevice::ReadOnly);
|
if (!Utilities::Copy(&source_file, &dest_file))
|
||||||
dest_file.open(QIODevice::WriteOnly);
|
return false;
|
||||||
dest_file.write(source_file.readAll());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
track->transferred = 1;
|
track->transferred = 1;
|
||||||
|
@ -111,12 +110,10 @@ bool AfcDevice::CopyToStorage(
|
||||||
else
|
else
|
||||||
track->filetype_marker |= suffix[i].toAscii();
|
track->filetype_marker |= suffix[i].toAscii();
|
||||||
}
|
}
|
||||||
qDebug() << track->filetype_marker;
|
|
||||||
|
|
||||||
// Set the filename
|
// Set the filename
|
||||||
track->ipod_path = strdup(dest.toUtf8().constData());
|
track->ipod_path = strdup(dest.toUtf8().constData());
|
||||||
itdb_filename_fs2ipod(track->ipod_path);
|
itdb_filename_fs2ipod(track->ipod_path);
|
||||||
qDebug() << track->ipod_path;
|
|
||||||
|
|
||||||
AddTrackToModel(track, "afc://" + url_.host());
|
AddTrackToModel(track, "afc://" + url_.host());
|
||||||
|
|
||||||
|
@ -128,11 +125,11 @@ bool AfcDevice::CopyToStorage(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AfcDevice::FinishCopy() {
|
void AfcDevice::FinishCopy(bool success) {
|
||||||
// Temporarily unset the GUID so libgpod doesn't lock the device for syncing
|
// Temporarily unset the GUID so libgpod doesn't lock the device for syncing
|
||||||
itdb_device_set_sysinfo(db_->device, "FirewireGuid", NULL);
|
itdb_device_set_sysinfo(db_->device, "FirewireGuid", NULL);
|
||||||
|
|
||||||
GPodDevice::FinishCopy();
|
GPodDevice::FinishCopy(success);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AfcDevice::FinaliseDatabase() {
|
void AfcDevice::FinaliseDatabase() {
|
||||||
|
|
|
@ -42,7 +42,7 @@ public:
|
||||||
|
|
||||||
bool CopyToStorage(const QString &source, const QString &destination,
|
bool CopyToStorage(const QString &source, const QString &destination,
|
||||||
const Song &metadata, bool overwrite, bool remove_original);
|
const Song &metadata, bool overwrite, bool remove_original);
|
||||||
void FinishCopy();
|
void FinishCopy(bool success);
|
||||||
|
|
||||||
bool DeleteFromStorage(const Song &metadata);
|
bool DeleteFromStorage(const Song &metadata);
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "afctransfer.h"
|
#include "afctransfer.h"
|
||||||
#include "imobiledeviceconnection.h"
|
#include "imobiledeviceconnection.h"
|
||||||
#include "core/taskmanager.h"
|
#include "core/taskmanager.h"
|
||||||
|
#include "core/utilities.h"
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
|
@ -117,52 +118,12 @@ bool AfcTransfer::CopyFileFromDevice(iMobileDeviceConnection *c, const QString &
|
||||||
QFile dest(local_filename);
|
QFile dest(local_filename);
|
||||||
AfcFile source(c, path);
|
AfcFile source(c, path);
|
||||||
|
|
||||||
return Copy(&source, &dest);
|
return Utilities::Copy(&source, &dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AfcTransfer::CopyFileToDevice(iMobileDeviceConnection *c, const QString &path) {
|
bool AfcTransfer::CopyFileToDevice(iMobileDeviceConnection *c, const QString &path) {
|
||||||
QFile source(local_destination_ + path);
|
QFile source(local_destination_ + path);
|
||||||
AfcFile dest(c, path);
|
AfcFile dest(c, path);
|
||||||
|
|
||||||
return Copy(&source, &dest);
|
return Utilities::Copy(&source, &dest);
|
||||||
}
|
|
||||||
|
|
||||||
bool AfcTransfer::Copy(QIODevice* source, QIODevice* destination) {
|
|
||||||
if (!source->open(QIODevice::ReadOnly))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!destination->open(QIODevice::WriteOnly))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const qint64 bytes = source->size();
|
|
||||||
char* data = new char[bytes];
|
|
||||||
qint64 pos = 0;
|
|
||||||
|
|
||||||
forever {
|
|
||||||
const qint64 bytes_read = source->read(data + pos, bytes - pos);
|
|
||||||
if (bytes_read == -1) {
|
|
||||||
delete[] data;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos += bytes_read;
|
|
||||||
if (bytes_read == 0 || pos == bytes)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = 0;
|
|
||||||
forever {
|
|
||||||
const qint64 bytes_written = destination->write(data + pos, bytes - pos);
|
|
||||||
if (bytes_written == -1) {
|
|
||||||
delete[] data;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos += bytes_written;
|
|
||||||
if (bytes_written == 0 || pos == bytes)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] data;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,8 +51,6 @@ private:
|
||||||
bool CopyFileFromDevice(iMobileDeviceConnection* c, const QString& path);
|
bool CopyFileFromDevice(iMobileDeviceConnection* c, const QString& path);
|
||||||
bool CopyFileToDevice(iMobileDeviceConnection* c, const QString& path);
|
bool CopyFileToDevice(iMobileDeviceConnection* c, const QString& path);
|
||||||
|
|
||||||
static bool Copy(QIODevice* source, QIODevice* destination);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::shared_ptr<ConnectedDevice> device_;
|
boost::shared_ptr<ConnectedDevice> device_;
|
||||||
QThread* original_thread_;
|
QThread* original_thread_;
|
||||||
|
|
|
@ -129,22 +129,24 @@ bool GPodDevice::CopyToStorage(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPodDevice::FinishCopy() {
|
void GPodDevice::FinishCopy(bool success) {
|
||||||
// Write the itunes database
|
if (success) {
|
||||||
GError* error = NULL;
|
// Write the itunes database
|
||||||
itdb_write(db_, &error);
|
GError* error = NULL;
|
||||||
if (error) {
|
itdb_write(db_, &error);
|
||||||
qDebug() << "GPodDevice error:" << error->message;
|
if (error) {
|
||||||
emit Error(QString::fromUtf8(error->message));
|
qDebug() << "GPodDevice error:" << error->message;
|
||||||
g_error_free(error);
|
emit Error(QString::fromUtf8(error->message));
|
||||||
} else {
|
g_error_free(error);
|
||||||
FinaliseDatabase();
|
} else {
|
||||||
|
FinaliseDatabase();
|
||||||
|
|
||||||
// Update the library model
|
// Update the library model
|
||||||
if (!songs_to_add_.isEmpty())
|
if (!songs_to_add_.isEmpty())
|
||||||
backend_->AddOrUpdateSongs(songs_to_add_);
|
backend_->AddOrUpdateSongs(songs_to_add_);
|
||||||
if (!songs_to_remove_.isEmpty())
|
if (!songs_to_remove_.isEmpty())
|
||||||
backend_->DeleteSongs(songs_to_remove_);
|
backend_->DeleteSongs(songs_to_remove_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
songs_to_add_.clear();
|
songs_to_add_.clear();
|
||||||
|
@ -197,7 +199,7 @@ bool GPodDevice::DeleteFromStorage(const Song& metadata) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPodDevice::FinishDelete() {
|
void GPodDevice::FinishDelete(bool success) {
|
||||||
FinishCopy();
|
FinishCopy(success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,11 +44,11 @@ public:
|
||||||
void StartCopy();
|
void StartCopy();
|
||||||
bool CopyToStorage(const QString &source, const QString &destination,
|
bool CopyToStorage(const QString &source, const QString &destination,
|
||||||
const Song &metadata, bool overwrite, bool remove_original);
|
const Song &metadata, bool overwrite, bool remove_original);
|
||||||
void FinishCopy();
|
void FinishCopy(bool success);
|
||||||
|
|
||||||
void StartDelete();
|
void StartDelete();
|
||||||
bool DeleteFromStorage(const Song& metadata);
|
bool DeleteFromStorage(const Song& metadata);
|
||||||
void FinishDelete();
|
void FinishDelete(bool success);
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void LoadFinished(Itdb_iTunesDB* db);
|
void LoadFinished(Itdb_iTunesDB* db);
|
||||||
|
|
|
@ -52,8 +52,18 @@ iMobileDeviceConnection::iMobileDeviceConnection(const QString& uuid)
|
||||||
|
|
||||||
iMobileDeviceConnection::~iMobileDeviceConnection() {
|
iMobileDeviceConnection::~iMobileDeviceConnection() {
|
||||||
if (afc_) {
|
if (afc_) {
|
||||||
|
// Do a test to see if we can still talk to the device. If not, it's
|
||||||
|
// probably not safe to free the lockdownd client.
|
||||||
|
char* model = NULL;
|
||||||
|
afc_error_t err = afc_get_device_info_key(afc_, "Model", &model);
|
||||||
|
free(model);
|
||||||
|
|
||||||
|
if (err != AFC_E_SUCCESS)
|
||||||
|
broken_ = true;
|
||||||
|
|
||||||
afc_client_free(afc_);
|
afc_client_free(afc_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lockdown_ && !broken_) {
|
if (lockdown_ && !broken_) {
|
||||||
lockdownd_client_free(lockdown_);
|
lockdownd_client_free(lockdown_);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue