From ac3345c65c052aa8d7be4f1ee5afd3e750c0fb45 Mon Sep 17 00:00:00 2001 From: "craig.p.drummond" Date: Wed, 30 Jan 2013 19:16:03 +0000 Subject: [PATCH] Better thread termination --- devices/device.h | 1 + devices/fsdevice.cpp | 9 ++++++++- devices/fsdevice.h | 1 + devices/mtpdevice.cpp | 29 ++++++++++++++++++----------- devices/mtpdevice.h | 1 + gui/mainwindow.cpp | 4 ++++ http/httpserver.cpp | 1 - models/devicesmodel.cpp | 19 ++++++++++++++----- models/devicesmodel.h | 1 + models/musiclibraryitemroot.cpp | 13 ++++++++++--- models/musiclibraryitemroot.h | 1 + models/onlineservicesmodel.cpp | 17 +++++++++++++---- models/onlineservicesmodel.h | 1 + mpd/mpdconnection.cpp | 1 - online/onlinedevice.h | 1 + online/onlineservice.cpp | 10 ++++++---- 16 files changed, 80 insertions(+), 30 deletions(-) diff --git a/devices/device.h b/devices/device.h index 9a7e6f4a8..d73d2aa92 100644 --- a/devices/device.h +++ b/devices/device.h @@ -120,6 +120,7 @@ public: virtual bool isConnected() const=0; virtual void rescan(bool full=true)=0; + virtual void stop()=0; virtual void connectionStateChanged() { } virtual void toggle() { } virtual bool isRefreshing() const=0; diff --git a/devices/fsdevice.cpp b/devices/fsdevice.cpp index fa3530c41..90570a1d6 100644 --- a/devices/fsdevice.cpp +++ b/devices/fsdevice.cpp @@ -322,6 +322,13 @@ bool FsDevice::readCache() return false; } +void FsDevice::stop() +{ + if (0!=scanner) { + scanner->stop(); + } +} + void FsDevice::addSong(const Song &s, bool overwrite, bool copyCover) { jobAbortRequested=false; @@ -609,8 +616,8 @@ void FsDevice::stopScanner(bool showStatus) if (scanner) { disconnect(scanner, SIGNAL(finished()), this, SLOT(libraryUpdated())); disconnect(scanner, SIGNAL(songCount(int)), this, SLOT(songCount(int))); - scanner->deleteLater(); scanner->stop(); + scanner->deleteLater(); scanner=0; if (showStatus) { setStatusMessage(QString()); diff --git a/devices/fsdevice.h b/devices/fsdevice.h index e26982e73..4977a37a5 100644 --- a/devices/fsdevice.h +++ b/devices/fsdevice.h @@ -94,6 +94,7 @@ public: virtual ~FsDevice(); void rescan(bool full=true); + void stop(); bool isRefreshing() const { return 0!=scanner; } QString path() const { return audioFolder; } QString coverFile() const { return opts.coverName; } diff --git a/devices/mtpdevice.cpp b/devices/mtpdevice.cpp index 42a1f91b1..dcfd799ca 100644 --- a/devices/mtpdevice.cpp +++ b/devices/mtpdevice.cpp @@ -235,7 +235,7 @@ void MtpConnection::updateLibrary() MusicLibraryItemArtist *artistItem = 0; MusicLibraryItemAlbum *albumItem = 0; - while (track) { + while (track && !abortRequested()) { QMap::ConstIterator it=folderMap.find(track->parent_id); Song s; s.id=track->item_id; @@ -268,13 +268,15 @@ void MtpConnection::updateLibrary() library->addGenre(s.genre); track=track->next; } - if (MPDParseUtils::groupSingle()) { - library->groupSingleTracks(); + if (!abortRequested()) { + if (MPDParseUtils::groupSingle()) { + library->groupSingleTracks(); + } + if (MPDParseUtils::groupMultiple()) { + library->groupMultipleArtists(); + } + emit libraryUpdated(); } - if (MPDParseUtils::groupMultiple()) { - library->groupMultipleArtists(); - } - emit libraryUpdated(); } uint32_t MtpConnection::getMusicFolderId() @@ -964,10 +966,7 @@ MtpDevice::MtpDevice(DevicesModel *m, Solid::Device &dev) MtpDevice::~MtpDevice() { - Utils::stopThread(thread); - thread->deleteLater(); - thread=0; - deleteTemp(); + stop(); } void MtpDevice::deviceDetails(const QString &s) @@ -988,6 +987,14 @@ bool MtpDevice::isConnected() const return solidDev.isValid() && pmp && pmp->isValid() && connection->isConnected(); } +void MtpDevice::stop() +{ + jobAbortRequested=true; + Utils::stopThread(thread); + thread=0; + deleteTemp(); +} + void MtpDevice::configure(QWidget *parent) { if (!isIdle()) { diff --git a/devices/mtpdevice.h b/devices/mtpdevice.h index 67c1588e3..00f8741f5 100644 --- a/devices/mtpdevice.h +++ b/devices/mtpdevice.h @@ -129,6 +129,7 @@ public: bool isConnected() const; bool isRefreshing() const { return mtpUpdating; } + void stop(); void configure(QWidget *parent); QString path() const { return QString(); } // audioFolder; } void addSong(const Song &s, bool overwrite, bool copyCover); diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index b6900dcd8..0157cd727 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -914,6 +914,10 @@ MainWindow::~MainWindow() #if defined ENABLE_DEVICES_SUPPORT FileScheduler::self()->stop(); #endif + OnlineServicesModel::self()->stop(); + #ifdef ENABLE_DEVICES_SUPPORT + DevicesModel::self()->stop(); + #endif } void MainWindow::initSizes() diff --git a/http/httpserver.cpp b/http/httpserver.cpp index b4b8e7355..c30d3a831 100644 --- a/http/httpserver.cpp +++ b/http/httpserver.cpp @@ -55,7 +55,6 @@ void HttpServer::stop() if (thread) { Utils::stopThread(thread); - thread->deleteLater(); thread=0; } } diff --git a/models/devicesmodel.cpp b/models/devicesmodel.cpp index 6b6b178ca..a96f7fefa 100644 --- a/models/devicesmodel.cpp +++ b/models/devicesmodel.cpp @@ -340,17 +340,26 @@ void DevicesModel::setEnabled(bool e) loadRemote(); #endif } else { - disconnect(Solid::DeviceNotifier::instance(), SIGNAL(deviceAdded(const QString &)), this, SLOT(deviceAdded(const QString &))); - disconnect(Solid::DeviceNotifier::instance(), SIGNAL(deviceRemoved(const QString &)), this, SLOT(deviceRemoved(const QString &))); -// disconnect(Covers::self(), SIGNAL(cover(const Song &, const QImage &, const QString &)), -// this, SLOT(setCover(const Song &, const QImage &, const QString &))); - disconnect(MountPoints::self(), SIGNAL(updated()), this, SLOT(mountsChanged())); + stop(); clear(); } inhibitMenuUpdate=false; updateItemMenu(); } +void DevicesModel::stop() +{ + foreach (Device *dev, devices) { + dev->stop(); + } + + disconnect(Solid::DeviceNotifier::instance(), SIGNAL(deviceAdded(const QString &)), this, SLOT(deviceAdded(const QString &))); + disconnect(Solid::DeviceNotifier::instance(), SIGNAL(deviceRemoved(const QString &)), this, SLOT(deviceRemoved(const QString &))); +// disconnect(Covers::self(), SIGNAL(cover(const Song &, const QImage &, const QString &)), +// this, SLOT(setCover(const Song &, const QImage &, const QString &))); + disconnect(MountPoints::self(), SIGNAL(updated()), this, SLOT(mountsChanged())); +} + Device * DevicesModel::device(const QString &udi) { int idx=indexOf(udi); diff --git a/models/devicesmodel.h b/models/devicesmodel.h index 305586c66..6ab150b9f 100644 --- a/models/devicesmodel.h +++ b/models/devicesmodel.h @@ -56,6 +56,7 @@ public: Device * device(const QString &udi); bool isEnabled() const { return enabled; } void setEnabled(bool e); + void stop(); void getDetails(QSet &artists, QSet &albumArtists, QSet &albums, QSet &genres); QMimeData * mimeData(const QModelIndexList &indexes) const; #ifdef ENABLE_REMOTE_DEVICES diff --git a/models/musiclibraryitemroot.cpp b/models/musiclibraryitemroot.cpp index 0afa5687d..1c0d7eee9 100644 --- a/models/musiclibraryitemroot.cpp +++ b/models/musiclibraryitemroot.cpp @@ -296,8 +296,12 @@ void MusicLibraryItemRoot::toXML(QXmlStreamWriter &writer, const QDateTime &date foreach (const MusicLibraryItem *a, childItems()) { foreach (const MusicLibraryItem *al, static_cast(a)->childItems()) { total+=al->childCount(); + if (prog && prog->wasStopped()) { + return; + } } } + writer.writeAttribute("numTracks", QString::number(total)); if (prog) { prog->writeProgress(0.0); @@ -311,6 +315,9 @@ void MusicLibraryItemRoot::toXML(QXmlStreamWriter &writer, const QDateTime &date writer.writeAttribute("img", artist->imageUrl()); } foreach (const MusicLibraryItem *al, artist->childItems()) { + if (prog && prog->wasStopped()) { + return; + } const MusicLibraryItemAlbum *album = static_cast(al); QString albumGenre=!album->childItems().isEmpty() ? static_cast(album->childItems().at(0))->song().genre : QString(); writer.writeStartElement("Album"); @@ -367,7 +374,7 @@ void MusicLibraryItemRoot::toXML(QXmlStreamWriter &writer, const QDateTime &date if (track->song().year != album->year()) { writer.writeAttribute("year", QString::number(track->song().year)); } - if (prog && total>0) { + if (prog && !prog->wasStopped() && total>0) { count++; prog->writeProgress((count*100.0)/(total*1.0)); } @@ -411,7 +418,7 @@ quint32 MusicLibraryItemRoot::fromXML(QXmlStreamReader &reader, const QDateTime prog->readProgress(0.0); } - while (!reader.atEnd()) { + while (!reader.atEnd() && (!prog || !prog->wasStopped())) { reader.readNext(); /** @@ -528,7 +535,7 @@ quint32 MusicLibraryItemRoot::fromXML(QXmlStreamReader &reader, const QDateTime artistItem->addGenre(song.genre); addGenre(song.genre); - if (prog && total>0) { + if (prog && !prog->wasStopped() && total>0) { count++; prog->readProgress((count*100.0)/(total*1.0)); } diff --git a/models/musiclibraryitemroot.h b/models/musiclibraryitemroot.h index c9e597de2..4d2123684 100644 --- a/models/musiclibraryitemroot.h +++ b/models/musiclibraryitemroot.h @@ -45,6 +45,7 @@ class MusicLibraryProgressMonitor public: virtual void readProgress(double pc) =0; virtual void writeProgress(double pc) =0; + virtual bool wasStopped() const =0; }; class MusicLibraryItemRoot : public MusicLibraryItemContainer diff --git a/models/onlineservicesmodel.cpp b/models/onlineservicesmodel.cpp index 1dc22d13f..dedf9ddb2 100644 --- a/models/onlineservicesmodel.cpp +++ b/models/onlineservicesmodel.cpp @@ -308,15 +308,24 @@ void OnlineServicesModel::setEnabled(bool e) load(); } else { if (wasEnabled) { - disconnect(Covers::self(), SIGNAL(artistImage(const Song &, const QImage &)), - this, SLOT(setArtistImage(const Song &, const QImage &))); - disconnect(Covers::self(), SIGNAL(cover(const Song &, const QImage &, const QString &)), - this, SLOT(setCover(const Song &, const QImage &, const QString &))); + stop(); } clear(); } } +void OnlineServicesModel::stop() +{ + disconnect(Covers::self(), SIGNAL(artistImage(const Song &, const QImage &)), + this, SLOT(setArtistImage(const Song &, const QImage &))); + disconnect(Covers::self(), SIGNAL(cover(const Song &, const QImage &, const QString &)), + this, SLOT(setCover(const Song &, const QImage &, const QString &))); + + foreach (OnlineService *srv, services) { + srv->stopLoader(); + } +} + OnlineService * OnlineServicesModel::service(const QString &name) { int idx=indexOf(name); diff --git a/models/onlineservicesmodel.h b/models/onlineservicesmodel.h index 0470c66a6..bb8fc04fd 100644 --- a/models/onlineservicesmodel.h +++ b/models/onlineservicesmodel.h @@ -55,6 +55,7 @@ public: OnlineService * service(const QString &name); bool isEnabled() const { return enabled; } void setEnabled(bool e); + void stop(); void getDetails(QSet &artists, QSet &albumArtists, QSet &albums, QSet &genres); QMimeData * mimeData(const QModelIndexList &indexes) const; void toggleGrouping(); diff --git a/mpd/mpdconnection.cpp b/mpd/mpdconnection.cpp index 209381658..9e64950cd 100644 --- a/mpd/mpdconnection.cpp +++ b/mpd/mpdconnection.cpp @@ -187,7 +187,6 @@ void MPDConnection::stop() { if (thread) { Utils::stopThread(thread); - thread->deleteLater(); thread=0; } } diff --git a/online/onlinedevice.h b/online/onlinedevice.h index de1a11b7f..73b3fb510 100644 --- a/online/onlinedevice.h +++ b/online/onlinedevice.h @@ -39,6 +39,7 @@ public: bool isConnected() const { return true; } void rescan(bool) { } bool isRefreshing() const { return false; } + void stop() { } QString path() const { return QString(); } void addSong(const Song&, bool, bool) { } void copySongTo(const Song &s, const QString &baseDir, const QString &musicPath, bool overwrite, bool copyCover); diff --git a/online/onlineservice.cpp b/online/onlineservice.cpp index 668e998fc..6e3a49e73 100644 --- a/online/onlineservice.cpp +++ b/online/onlineservice.cpp @@ -84,9 +84,11 @@ bool OnlineMusicLoader::readFromCache() if (!cache.isEmpty() && QFile::exists(cache)) { emit status(i18n("Reading cache"), 0); if (library->fromXML(cache, QDateTime(), QString(), this)) { - fixLibrary(); - emit status(i18n("Updating display"), -100); - emit loaded(); + if (!stopRequested) { + fixLibrary(); + emit status(i18n("Updating display"), -100); + emit loaded(); + } return true; } } @@ -174,8 +176,8 @@ void OnlineService::stopLoader() disconnect(loader, SIGNAL(error(QString)), this, SLOT(loaderError(QString))); disconnect(loader, SIGNAL(status(QString,int)), this, SLOT(loaderstatus(QString,int))); disconnect(loader, SIGNAL(loaded()), this, SLOT(loaderFinished())); - loader->deleteLater(); loader->stop(); + loader->deleteLater(); loader=0; } }