From ea6cce70682023ef79893f7b784965e209816887 Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Fri, 19 Jul 2019 19:56:37 +0200 Subject: [PATCH] Fix mtp device support --- src/core/song.cpp | 34 ++++++++++------- src/device/connecteddevice.h | 5 +-- src/device/giolister.cpp | 71 +++++++++++++++++++++++++----------- src/device/gpoddevice.cpp | 10 ++++- src/device/gpodloader.cpp | 2 +- src/device/mtpconnection.cpp | 40 ++++++++++++++++++++ src/device/mtpconnection.h | 10 ++++- src/device/mtpdevice.cpp | 37 +++++++++++++++---- src/device/mtpdevice.h | 8 +++- src/device/mtploader.cpp | 26 ++++++++----- src/device/mtploader.h | 10 +++-- src/device/udisks2lister.cpp | 9 +++-- src/organise/organise.cpp | 8 ++++ src/organise/organise.h | 1 + 14 files changed, 201 insertions(+), 70 deletions(-) diff --git a/src/core/song.cpp b/src/core/song.cpp index aa4f7b80d..1e50b3c84 100644 --- a/src/core/song.cpp +++ b/src/core/song.cpp @@ -1055,6 +1055,7 @@ void Song::ToItdb(Itdb_Track *track) const { void Song::InitFromMTP(const LIBMTP_track_t *track, const QString &host) { d->valid_ = true; + d->source_ = Source_Device; set_title(QString::fromUtf8(track->title)); set_artist(QString::fromUtf8(track->artist)); @@ -1063,7 +1064,7 @@ void Song::InitFromMTP(const LIBMTP_track_t *track, const QString &host) { d->composer_ = QString::fromUtf8(track->composer); d->track_ = track->tracknumber; - d->url_ = QUrl(QString("mtp://%1/%2").arg(host, track->item_id)); + d->url_ = QUrl(QString("mtp://%1/%2").arg(host, QString::number(track->item_id))); d->basefilename_ = QString::number(track->item_id); d->filesize_ = track->filesize; d->mtime_ = track->modificationdate; @@ -1072,7 +1073,7 @@ void Song::InitFromMTP(const LIBMTP_track_t *track, const QString &host) { set_length_nanosec(track->duration * kNsecPerMsec); d->samplerate_ = track->samplerate; - d->bitdepth_ = 0; //track->bitdepth; + d->bitdepth_ = 0; d->bitrate_ = track->bitrate; d->playcount_ = track->usecount; @@ -1087,11 +1088,12 @@ void Song::InitFromMTP(const LIBMTP_track_t *track, const QString &host) { case LIBMTP_FILETYPE_FLAC: d->filetype_ = FileType_OggFlac; break; case LIBMTP_FILETYPE_MP2: d->filetype_ = FileType_MPEG; break; case LIBMTP_FILETYPE_M4A: d->filetype_ = FileType_MP4; break; - default: d->filetype_ = FileType_Unknown; break; + default: + d->filetype_ = FileType_Unknown; + d->valid_ = false; + break; } - d->source_ = Source_Device; - } void Song::ToMTP(LIBMTP_track_t *track) const { @@ -1101,14 +1103,18 @@ void Song::ToMTP(LIBMTP_track_t *track) const { track->storage_id = 0; track->title = strdup(d->title_.toUtf8().constData()); - track->artist = strdup(d->artist_.toUtf8().constData()); + track->artist = strdup(effective_albumartist().toUtf8().constData()); track->album = strdup(d->album_.toUtf8().constData()); track->genre = strdup(d->genre_.toUtf8().constData()); track->date = nullptr; track->tracknumber = d->track_; - track->composer = strdup(d->composer_.toUtf8().constData()); + if (d->composer_.isEmpty()) + track->composer = nullptr; + else + track->composer = strdup(d->composer_.toUtf8().constData()); track->filename = strdup(d->basefilename_.toUtf8().constData()); + track->filesize = d->filesize_; track->modificationdate = d->mtime_; @@ -1123,15 +1129,15 @@ void Song::ToMTP(LIBMTP_track_t *track) const { track->usecount = d->playcount_; switch (d->filetype_) { - case FileType_ASF: track->filetype = LIBMTP_FILETYPE_ASF; break; - case FileType_MP4: track->filetype = LIBMTP_FILETYPE_MP4; break; - case FileType_MPEG: track->filetype = LIBMTP_FILETYPE_MP3; break; + case FileType_ASF: track->filetype = LIBMTP_FILETYPE_ASF; break; + case FileType_MP4: track->filetype = LIBMTP_FILETYPE_MP4; break; + case FileType_MPEG: track->filetype = LIBMTP_FILETYPE_MP3; break; case FileType_FLAC: - case FileType_OggFlac: track->filetype = LIBMTP_FILETYPE_FLAC; break; + case FileType_OggFlac: track->filetype = LIBMTP_FILETYPE_FLAC; break; case FileType_OggSpeex: - case FileType_OggVorbis: track->filetype = LIBMTP_FILETYPE_OGG; break; - case FileType_WAV: track->filetype = LIBMTP_FILETYPE_WAV; break; - default: track->filetype = LIBMTP_FILETYPE_UNDEF_AUDIO; break; + case FileType_OggVorbis: track->filetype = LIBMTP_FILETYPE_OGG; break; + case FileType_WAV: track->filetype = LIBMTP_FILETYPE_WAV; break; + default: track->filetype = LIBMTP_FILETYPE_UNDEF_AUDIO; break; } } diff --git a/src/device/connecteddevice.h b/src/device/connecteddevice.h index 8648afe28..25a7c6472 100644 --- a/src/device/connecteddevice.h +++ b/src/device/connecteddevice.h @@ -40,9 +40,7 @@ class CollectionModel; class DeviceLister; class DeviceManager; -class ConnectedDevice : public QObject, - public virtual MusicStorage, - public std::enable_shared_from_this { +class ConnectedDevice : public QObject, public virtual MusicStorage, public std::enable_shared_from_this { Q_OBJECT public: @@ -50,6 +48,7 @@ class ConnectedDevice : public QObject, ~ConnectedDevice(); virtual bool Init() = 0; + virtual void NewConnection() {} 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 diff --git a/src/device/giolister.cpp b/src/device/giolister.cpp index d2b6a9374..e1df6ea1a 100644 --- a/src/device/giolister.cpp +++ b/src/device/giolister.cpp @@ -47,10 +47,12 @@ using std::placeholders::_3; QString GioLister::DeviceInfo::unique_id() const { + if (!volume_root_uri.isEmpty()) return volume_root_uri; + if (mount) return QString("Gio/%1/%2/%3").arg(mount_uuid, filesystem_type).arg(filesystem_size); - - return QString("Gio/unmounted/%1").arg((qulonglong)volume.get()); + else + return QString("Gio/unmounted/%1").arg((qulonglong)volume.get()); } @@ -191,43 +193,65 @@ QVariantMap GioLister::DeviceHardwareInfo(const QString &id) { QList GioLister::MakeDeviceUrls(const QString &id) { + QString volume_root_uri; QString mount_point; - QString uri; + QString mount_uri; QString unix_device; { QMutexLocker l(&mutex_); + volume_root_uri = devices_[id].volume_root_uri; mount_point = devices_[id].mount_path; - uri = devices_[id].mount_uri; + mount_uri = devices_[id].mount_uri; unix_device = devices_[id].volume_unix_device; } - // gphoto2 gives invalid hostnames with []:, characters in - uri.replace(QRegExp("//\\[usb:(\\d+),(\\d+)\\]"), "//usb-\\1-\\2"); + QStringList uris; + if (!volume_root_uri.isEmpty()) + uris << volume_root_uri; - QUrl url(uri); + if (!mount_uri.isEmpty()) + uris << mount_uri; QList ret; - if (url.isValid()) { - QRegExp device_re("usb/(\\d+)/(\\d+)"); - if (device_re.indexIn(unix_device) >= 0) { - QUrlQuery url_query(url); - url_query.addQueryItem("busnum", device_re.cap(1)); - url_query.addQueryItem("devnum", device_re.cap(2)); - url.setQuery(url_query); - } + for (QString uri : uris) { - // Special case for file:// GIO URIs - we have to check whether they point to an ipod. - if (url.scheme() == "file") { - ret << MakeUrlFromLocalPath(url.path()); + // gphoto2 gives invalid hostnames with []:, characters in + uri.replace(QRegExp("//\\[usb:(\\d+),(\\d+)\\]"), "//usb-\\1-\\2"); + + QUrl url; + + if (uri.contains(QRegExp("..+:.*"))) { + url = QUrl::fromEncoded(uri.toUtf8()); } else { + url = MakeUrlFromLocalPath(uri); + } + + if (url.isValid()) { + + // Special case for file:// GIO URIs - we have to check whether they point to an ipod. + if (url.isLocalFile() && IsIpod(url.path())) { + url.setScheme("ipod"); + } + + QRegExp device_re("usb/(\\d+)/(\\d+)"); + if (device_re.indexIn(unix_device) >= 0) { + QUrlQuery url_query(url); + url_query.addQueryItem("busnum", device_re.cap(1)); + url_query.addQueryItem("devnum", device_re.cap(2)); + url.setQuery(url_query); + } + ret << url; + } } - ret << MakeUrlFromLocalPath(mount_point); + if (!mount_point.isEmpty()) { + ret << MakeUrlFromLocalPath(mount_point); + } return ret; @@ -473,6 +497,7 @@ void GioLister::DeviceInfo::ReadVolumeInfo(GVolume *volume) { } void GioLister::DeviceInfo::ReadDriveInfo(GDrive *drive) { + this->drive.reset_without_add(drive); if (!drive) return; @@ -485,6 +510,7 @@ QString GioLister::FindUniqueIdByMount(GMount *mount) const { if (info.mount == mount) return info.unique_id(); } return QString(); + } QString GioLister::FindUniqueIdByVolume(GVolume *volume) const { @@ -509,7 +535,7 @@ void GioLister::MountUnmountFinished(GObject *object, GAsyncResult *result, gpoi void GioLister::UnmountDevice(const QString &id) { QMutexLocker l(&mutex_); - if (!devices_.contains(id)) return; + if (!devices_.contains(id) || !devices_[id].mount || devices_[id].volume_root_uri.startsWith("mtp://")) return; const DeviceInfo &info = devices_[id]; @@ -537,7 +563,7 @@ void GioLister::UpdateDeviceFreeSpace(const QString &id) { { QMutexLocker l(&mutex_); - if (!devices_.contains(id)) return; + if (!devices_.contains(id) || !devices_[id].mount || devices_[id].volume_root_uri.startsWith("mtp://")) return; DeviceInfo &device_info = devices_[id]; @@ -563,10 +589,11 @@ void GioLister::UpdateDeviceFreeSpace(const QString &id) { bool GioLister::DeviceNeedsMount(const QString &id) { QMutexLocker l(&mutex_); - return devices_.contains(id) && !devices_[id].mount; + return devices_.contains(id) && !devices_[id].mount && !devices_[id].volume_root_uri.startsWith("mtp://"); } int GioLister::MountDevice(const QString &id) { + const int request_id = next_mount_request_id_++; metaObject()->invokeMethod(this, "DoMountDevice", Qt::QueuedConnection, Q_ARG(QString, id), Q_ARG(int, request_id)); return request_id; diff --git a/src/device/gpoddevice.cpp b/src/device/gpoddevice.cpp index 68bcb31b9..d49d37586 100644 --- a/src/device/gpoddevice.cpp +++ b/src/device/gpoddevice.cpp @@ -47,7 +47,7 @@ class DeviceManager; GPodDevice::GPodDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, DeviceManager *manager, Application *app, int database_id, bool first_time) : ConnectedDevice(url, lister, unique_id, manager, app, database_id, first_time), - loader_thread_(new QThread(this)), + loader_thread_(new QThread()), loader_(nullptr), db_(nullptr) {} @@ -68,7 +68,13 @@ bool GPodDevice::Init() { } -GPodDevice::~GPodDevice() {} +GPodDevice::~GPodDevice() { + if (loader_) { + loader_thread_->exit(); + loader_->deleteLater(); + loader_thread_->deleteLater(); + } +} void GPodDevice::ConnectAsync() { diff --git a/src/device/gpodloader.cpp b/src/device/gpodloader.cpp index 6b9431d0e..8b9803022 100644 --- a/src/device/gpodloader.cpp +++ b/src/device/gpodloader.cpp @@ -88,7 +88,7 @@ Itdb_iTunesDB *GPodLoader::TryLoad() { for (GList *tracks = db->tracks; tracks != nullptr; tracks = tracks->next) { Itdb_Track *track = static_cast(tracks->data); - Song song; + Song song(Song::Source_Device); song.InitFromItdb(track, prefix); song.set_directory_id(1); diff --git a/src/device/mtpconnection.cpp b/src/device/mtpconnection.cpp index 05b1a3406..44deb1381 100644 --- a/src/device/mtpconnection.cpp +++ b/src/device/mtpconnection.cpp @@ -2,6 +2,7 @@ * Strawberry Music Player * This file was part of Clementine. * Copyright 2010, David Sansome + * Copyright 2019, Jonas Kvinge * * Strawberry is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -105,3 +106,42 @@ MtpConnection::~MtpConnection() { if (device_) LIBMTP_Release_Device(device_); } +bool MtpConnection::GetSupportedFiletypes(QList *ret) { + + if (!device_) return false; + + uint16_t *list = nullptr; + uint16_t length = 0; + + if (LIBMTP_Get_Supported_Filetypes(device_, &list, &length) || !list || !length) + return false; + + for (int i = 0; i < length; ++i) { + switch (LIBMTP_filetype_t(list[i])) { + case LIBMTP_FILETYPE_WAV: *ret << Song::FileType_WAV; break; + case LIBMTP_FILETYPE_MP2: + case LIBMTP_FILETYPE_MP3: *ret << Song::FileType_MPEG; break; + case LIBMTP_FILETYPE_WMA: *ret << Song::FileType_ASF; break; + case LIBMTP_FILETYPE_MP4: + case LIBMTP_FILETYPE_M4A: + case LIBMTP_FILETYPE_AAC: *ret << Song::FileType_MP4; break; + case LIBMTP_FILETYPE_FLAC: + *ret << Song::FileType_FLAC; + *ret << Song::FileType_OggFlac; + break; + case LIBMTP_FILETYPE_OGG: + *ret << Song::FileType_OggVorbis; + *ret << Song::FileType_OggSpeex; + *ret << Song::FileType_OggFlac; + break; + default: + qLog(Error) << "Unknown MTP file format" << LIBMTP_Get_Filetype_Description(LIBMTP_filetype_t(list[i])); + break; + } + } + + free(list); + return true; + +} + diff --git a/src/device/mtpconnection.h b/src/device/mtpconnection.h index cc6e4883a..5ef90ceda 100644 --- a/src/device/mtpconnection.h +++ b/src/device/mtpconnection.h @@ -2,6 +2,7 @@ * Strawberry Music Player * This file was part of Clementine. * Copyright 2010, David Sansome + * Copyright 2019, Jonas Kvinge * * Strawberry is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,18 +25,23 @@ #include "config.h" #include +#include #include #include +#include #include -class MtpConnection { +#include "core/song.h" + +class MtpConnection : public QObject, public std::enable_shared_from_this { public: MtpConnection(const QUrl &url); ~MtpConnection(); bool is_valid() const { return device_; } LIBMTP_mtpdevice_t *device() const { return device_; } + bool GetSupportedFiletypes(QList *ret); private: Q_DISABLE_COPY(MtpConnection); @@ -43,4 +49,4 @@ private: LIBMTP_mtpdevice_t *device_; }; -#endif // MTPCONNECTION_H +#endif // MTPCONNECTION_H diff --git a/src/device/mtpdevice.cpp b/src/device/mtpdevice.cpp index 8cab6b728..655798b3d 100644 --- a/src/device/mtpdevice.cpp +++ b/src/device/mtpdevice.cpp @@ -2,6 +2,7 @@ * Strawberry Music Player * This file was part of Clementine. * Copyright 2010, David Sansome + * Copyright 2019, Jonas Kvinge * * Strawberry is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -50,7 +51,7 @@ class DeviceManager; bool MtpDevice::sInitialisedLibMTP = false; MtpDevice::MtpDevice(const QUrl &url, DeviceLister *lister, const QString &unique_id, DeviceManager *manager, Application *app, int database_id, bool first_time) - : ConnectedDevice(url, lister, unique_id, manager, app, database_id, first_time), loader_thread_(new QThread(this)), loader_(nullptr) { + : ConnectedDevice(url, lister, unique_id, manager, app, database_id, first_time), loader_thread_(new QThread()), loader_(nullptr) { if (!sInitialisedLibMTP) { LIBMTP_Init(); @@ -59,7 +60,15 @@ MtpDevice::MtpDevice(const QUrl &url, DeviceLister *lister, const QString &uniqu } -MtpDevice::~MtpDevice() {} +MtpDevice::~MtpDevice() { + if (loader_) { + loader_thread_->exit(); + loader_->deleteLater(); + loader_ = nullptr; + db_busy_.unlock(); + loader_thread_->deleteLater(); + } +} bool MtpDevice::Init() { @@ -79,6 +88,12 @@ bool MtpDevice::Init() { } +void MtpDevice::NewConnection() { + + connection_.reset(new MtpConnection(url_)); + +} + void MtpDevice::ConnectAsync() { db_busy_.lock(); @@ -96,7 +111,9 @@ void MtpDevice::LoadFinished(bool success) { } -void MtpDevice::LoaderError(const QString& message) { app_->AddError(message); } +void MtpDevice::LoaderError(const QString& message) { + app_->AddError(message); +} bool MtpDevice::StartCopy(QList *supported_types) { @@ -104,7 +121,8 @@ bool MtpDevice::StartCopy(QList *supported_types) { db_busy_.lock(); // Connect to the device - connection_.reset(new MtpConnection(url_)); + if (!connection_.get() || !connection_->is_valid()) NewConnection(); + if (!connection_.get() || !connection_->is_valid()) return false; // Did the caller want a list of supported types? if (supported_types) { @@ -129,7 +147,7 @@ static int ProgressCallback(uint64_t const sent, uint64_t const total, void cons bool MtpDevice::CopyToStorage(const CopyJob &job) { - if (!connection_->is_valid()) return false; + if (!connection_.get() || !connection_->is_valid()) return false; // Convert metadata LIBMTP_track_t track; @@ -140,9 +158,11 @@ bool MtpDevice::CopyToStorage(const CopyJob &job) { if (ret != 0) return false; // Add it to our CollectionModel - Song metadata_on_device; + Song metadata_on_device(Song::Source_Device); metadata_on_device.InitFromMTP(&track, url_.host()); metadata_on_device.set_directory_id(1); + metadata_on_device.set_artist(metadata_on_device.effective_albumartist()); + metadata_on_device.set_albumartist(""); songs_to_add_ << metadata_on_device; // Remove the original if requested @@ -164,8 +184,6 @@ void MtpDevice::FinishCopy(bool success) { songs_to_add_.clear(); songs_to_remove_.clear(); - connection_.reset(); - db_busy_.unlock(); ConnectedDevice::FinishCopy(success); @@ -176,6 +194,8 @@ void MtpDevice::StartDelete() { StartCopy(nullptr); } bool MtpDevice::DeleteFromStorage(const DeleteJob &job) { + if (!connection_.get() || !connection_->is_valid()) return false; + // Extract the ID from the song's URL QString filename = job.metadata_.url().path(); filename.remove('/'); @@ -201,6 +221,7 @@ bool MtpDevice::GetSupportedFiletypes(QList *ret) { QMutexLocker l(&db_busy_); MtpConnection connection(url_); + if (!connection.is_valid()) { qLog(Warning) << "Error connecting to MTP device, couldn't get list of supported filetypes"; return false; diff --git a/src/device/mtpdevice.h b/src/device/mtpdevice.h index adadbd15d..66be34546 100644 --- a/src/device/mtpdevice.h +++ b/src/device/mtpdevice.h @@ -2,6 +2,7 @@ * Strawberry Music Player * This file was part of Clementine. * Copyright 2010, David Sansome + * Copyright 2019, Jonas Kvinge * * Strawberry is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,6 +41,7 @@ class Application; class DeviceLister; class DeviceManager; +class DeviceConnection; class MtpConnection; class MtpLoader; struct LIBMTP_mtpdevice_struct; @@ -54,6 +56,7 @@ class MtpDevice : public ConnectedDevice { static QStringList url_schemes() { return QStringList() << "mtp" << "gphoto2"; } bool Init(); + void NewConnection(); void ConnectAsync(); bool GetSupportedFiletypes(QList* ret); @@ -68,6 +71,8 @@ class MtpDevice : public ConnectedDevice { bool DeleteFromStorage(const DeleteJob& job); void FinishDelete(bool success); + MtpConnection *connection() { return connection_.get(); } + private slots: void LoadFinished(bool success); void LoaderError(const QString& message); @@ -87,7 +92,8 @@ class MtpDevice : public ConnectedDevice { SongList songs_to_add_; SongList songs_to_remove_; - std::unique_ptr connection_; + std::shared_ptr connection_; + }; #endif // MTPDEVICE_H diff --git a/src/device/mtploader.cpp b/src/device/mtploader.cpp index 56db0ee7b..9e55f70f3 100644 --- a/src/device/mtploader.cpp +++ b/src/device/mtploader.cpp @@ -2,6 +2,7 @@ * Strawberry Music Player * This file was part of Clementine. * Copyright 2010, David Sansome + * Copyright 2019, Jonas Kvinge * * Strawberry is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,17 +28,19 @@ #include "core/taskmanager.h" #include "core/song.h" +#include "core/logging.h" #include "collection/collectionbackend.h" +#include "connecteddevice.h" +#include "mtpdevice.h" #include "mtpconnection.h" #include "mtploader.h" MtpLoader::MtpLoader(const QUrl &url, TaskManager *task_manager, CollectionBackend *backend, std::shared_ptr device) : QObject(nullptr), - device_(device), url_(url), task_manager_(task_manager), backend_(backend), - connection_(nullptr) { + device_(device) { original_thread_ = thread(); } @@ -61,23 +64,28 @@ void MtpLoader::LoadDatabase() { bool MtpLoader::TryLoad() { - MtpConnection dev(url_); - if (!dev.is_valid()) { + MtpDevice *device = dynamic_cast(device_.get()); // FIXME + + if (!device->connection() || !device->connection()->is_valid()) + device->NewConnection(); + + if (!device->connection() || !device->connection()->is_valid()) { emit Error(tr("Error connecting MTP device %1").arg(url_.toString())); return false; } // Load the list of songs on the device SongList songs; - LIBMTP_track_t* tracks = LIBMTP_Get_Tracklisting_With_Callback(dev.device(), nullptr, nullptr); + LIBMTP_track_t* tracks = LIBMTP_Get_Tracklisting_With_Callback(device->connection()->device(), nullptr, nullptr); while (tracks) { LIBMTP_track_t *track = tracks; - Song song; + Song song(Song::Source_Device); song.InitFromMTP(track, url_.host()); - song.set_directory_id(1); - songs << song; - + if (song.is_valid() && !song.artist().isEmpty() && !song.title().isEmpty()) { + song.set_directory_id(1); + songs << song; + } tracks = tracks->next; LIBMTP_destroy_track_t(track); } diff --git a/src/device/mtploader.h b/src/device/mtploader.h index 3f03297c4..6262500f6 100644 --- a/src/device/mtploader.h +++ b/src/device/mtploader.h @@ -2,6 +2,7 @@ * Strawberry Music Player * This file was part of Clementine. * Copyright 2010, David Sansome + * Copyright 2019, Jonas Kvinge * * Strawberry is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,6 +35,7 @@ class TaskManager; class CollectionBackend; class ConnectedDevice; +class MtpDevice; class MtpConnection; class MtpLoader : public QObject { @@ -57,13 +59,13 @@ class MtpLoader : public QObject { bool TryLoad(); private: - std::shared_ptr device_; - QThread *original_thread_; - QUrl url_; TaskManager *task_manager_; CollectionBackend *backend_; - MtpConnection *connection_; + std::shared_ptr device_; + std::shared_ptr connection_; + QThread *original_thread_; + }; #endif // MTPLOADER_H diff --git a/src/device/udisks2lister.cpp b/src/device/udisks2lister.cpp index ccc6e9865..bb52561bd 100644 --- a/src/device/udisks2lister.cpp +++ b/src/device/udisks2lister.cpp @@ -125,10 +125,11 @@ QList Udisks2Lister::MakeDeviceUrls(const QString &id) { QList ret; if (!device_data_.contains(id)) return ret; // Special case for Apple - if(id.contains("iPod")) { - ret << MakeUrlFromLocalPath(device_data_[id].mount_paths.at(0)); - } else { - ret << QUrl::fromLocalFile(device_data_[id].mount_paths.at(0)); + if (id.contains("iPod")) { + ret << MakeUrlFromLocalPath(device_data_[id].mount_paths.at(0)); + } + else { + ret << QUrl::fromLocalFile(device_data_[id].mount_paths.at(0)); } return ret; } diff --git a/src/organise/organise.cpp b/src/organise/organise.cpp index 962746f27..17f1ee4f4 100644 --- a/src/organise/organise.cpp +++ b/src/organise/organise.cpp @@ -79,6 +79,13 @@ Organise::Organise(TaskManager *task_manager, std::shared_ptr dest } +Organise::~Organise() { + if (thread_) { + thread_->quit(); + thread_->deleteLater(); + } +} + void Organise::Start() { if (thread_) return; @@ -95,6 +102,7 @@ void Organise::Start() { moveToThread(thread_); thread_->start(); + } void Organise::ProcessSomeFiles() { diff --git a/src/organise/organise.h b/src/organise/organise.h index 81a3e4176..ddc8e6a3c 100644 --- a/src/organise/organise.h +++ b/src/organise/organise.h @@ -62,6 +62,7 @@ class Organise : public QObject { typedef QList NewSongInfoList; Organise(TaskManager *task_manager, std::shared_ptr destination, const OrganiseFormat &format, bool copy, bool overwrite, bool mark_as_listened, bool albumcover, const NewSongInfoList &songs, bool eject_after); + ~Organise(); static const int kBatchSize; #ifdef HAVE_GSTREAMER