Disconnect tagreader reply metaobject connection in lambda

Otherwise the tagreader reply is deleted to early causing crashes.
This commit is contained in:
Jonas Kvinge
2024-11-21 15:43:33 +01:00
parent d500d38e63
commit a26066d70f
10 changed files with 39 additions and 22 deletions

View File

@@ -2197,7 +2197,11 @@ void MainWindow::RenumberTracks() {
song.set_track(track); song.set_track(track);
TagReaderReplyPtr reply = app_->tagreader_client()->WriteFileAsync(song.url().toLocalFile(), song); TagReaderReplyPtr reply = app_->tagreader_client()->WriteFileAsync(song.url().toLocalFile(), song);
QPersistentModelIndex persistent_index = QPersistentModelIndex(source_index); QPersistentModelIndex persistent_index = QPersistentModelIndex(source_index);
QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, persistent_index]() { SongSaveComplete(reply, persistent_index); }, Qt::QueuedConnection); SharedPtr<QMetaObject::Connection> connection = make_shared<QMetaObject::Connection>();
*connection = QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, persistent_index, connection]() {
SongSaveComplete(reply, persistent_index);
QObject::disconnect(*connection);
}, Qt::QueuedConnection);
} }
++track; ++track;
} }
@@ -2228,7 +2232,11 @@ void MainWindow::SelectionSetValue() {
if (song.url().isLocalFile() && Playlist::set_column_value(song, column, column_value)) { if (song.url().isLocalFile() && Playlist::set_column_value(song, column, column_value)) {
TagReaderReplyPtr reply = app_->tagreader_client()->WriteFileAsync(song.url().toLocalFile(), song); TagReaderReplyPtr reply = app_->tagreader_client()->WriteFileAsync(song.url().toLocalFile(), song);
QPersistentModelIndex persistent_index = QPersistentModelIndex(source_index); QPersistentModelIndex persistent_index = QPersistentModelIndex(source_index);
QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, persistent_index]() { SongSaveComplete(reply, persistent_index); }, Qt::QueuedConnection); SharedPtr<QMetaObject::Connection> connection = make_shared<QMetaObject::Connection>();
*connection = QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, persistent_index, connection]() {
SongSaveComplete(reply, persistent_index);
QObject::disconnect(*connection);
}, Qt::QueuedConnection);
} }
else if (song.source() == Song::Source::Stream) { else if (song.source() == Song::Source::Stream) {
app_->playlist_manager()->current()->setData(source_index, column_value, 0); app_->playlist_manager()->current()->setData(source_index, column_value, 0);

View File

@@ -22,6 +22,7 @@
#include "config.h" #include "config.h"
#include <utility> #include <utility>
#include <memory>
#include <QtGlobal> #include <QtGlobal>
#include <QGuiApplication> #include <QGuiApplication>
@@ -79,6 +80,7 @@
#include "coverfromurldialog.h" #include "coverfromurldialog.h"
#include "currentalbumcoverloader.h" #include "currentalbumcoverloader.h"
using std::make_shared;
using namespace Qt::Literals::StringLiterals; using namespace Qt::Literals::StringLiterals;
QSet<QString> *AlbumCoverChoiceController::sImageExtensions = nullptr; QSet<QString> *AlbumCoverChoiceController::sImageExtensions = nullptr;
@@ -743,7 +745,11 @@ void AlbumCoverChoiceController::SaveCoverEmbeddedToSong(const Song &song, const
cover_save_tasks_.append(song); cover_save_tasks_.append(song);
const bool art_embedded = !image_data.isNull(); const bool art_embedded = !image_data.isNull();
TagReaderReplyPtr reply = tagreader_client_->SaveCoverAsync(song.url().toLocalFile(), SaveTagCoverData(cover_filename, image_data, mime_type)); TagReaderReplyPtr reply = tagreader_client_->SaveCoverAsync(song.url().toLocalFile(), SaveTagCoverData(cover_filename, image_data, mime_type));
QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, song, art_embedded]() { SaveEmbeddedCoverFinished(reply, song, art_embedded); }); SharedPtr<QMetaObject::Connection> connection = make_shared<QMetaObject::Connection>();
*connection = QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, song, art_embedded, connection]() {
SaveEmbeddedCoverFinished(reply, song, art_embedded);
QObject::disconnect(*connection);
});
} }

View File

@@ -24,6 +24,7 @@
#include <algorithm> #include <algorithm>
#include <utility> #include <utility>
#include <chrono> #include <chrono>
#include <memory>
#include <QObject> #include <QObject>
#include <QMainWindow> #include <QMainWindow>
@@ -96,6 +97,7 @@
using namespace std::literals::chrono_literals; using namespace std::literals::chrono_literals;
using namespace Qt::Literals::StringLiterals; using namespace Qt::Literals::StringLiterals;
using std::make_shared;
namespace { namespace {
constexpr char kSettingsGroup[] = "CoverManager"; constexpr char kSettingsGroup[] = "CoverManager";
@@ -855,8 +857,10 @@ void AlbumCoverManager::SaveImageToAlbums(Song *song, const AlbumCoverImageResul
for (const QUrl &url : std::as_const(album_item->urls)) { for (const QUrl &url : std::as_const(album_item->urls)) {
const bool art_embedded = !result.image_data.isEmpty(); const bool art_embedded = !result.image_data.isEmpty();
TagReaderReplyPtr reply = tagreader_client_->SaveCoverAsync(url.toLocalFile(), SaveTagCoverData(result.image_data, result.mime_type)); TagReaderReplyPtr reply = tagreader_client_->SaveCoverAsync(url.toLocalFile(), SaveTagCoverData(result.image_data, result.mime_type));
QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, album_item, url, art_embedded]() { SharedPtr<QMetaObject::Connection> connection = make_shared<QMetaObject::Connection>();
*connection = QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, album_item, url, art_embedded, connection]() {
SaveEmbeddedCoverFinished(reply, album_item, url, art_embedded); SaveEmbeddedCoverFinished(reply, album_item, url, art_embedded);
QObject::disconnect(*connection);
}); });
cover_save_tasks_.insert(album_item, url); cover_save_tasks_.insert(album_item, url);
} }
@@ -1005,8 +1009,10 @@ void AlbumCoverManager::SaveAndSetCover(AlbumItem *album_item, const AlbumCoverI
for (const QUrl &url : urls) { for (const QUrl &url : urls) {
const bool art_embedded = !result.image_data.isEmpty(); const bool art_embedded = !result.image_data.isEmpty();
TagReaderReplyPtr reply = tagreader_client_->SaveCoverAsync(url.toLocalFile(), SaveTagCoverData(result.cover_url.isValid() ? result.cover_url.toLocalFile() : QString(), result.image_data, result.mime_type)); TagReaderReplyPtr reply = tagreader_client_->SaveCoverAsync(url.toLocalFile(), SaveTagCoverData(result.cover_url.isValid() ? result.cover_url.toLocalFile() : QString(), result.image_data, result.mime_type));
QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, album_item, url, art_embedded]() { SharedPtr<QMetaObject::Connection> connection = std::make_shared<QMetaObject::Connection>();
*connection = QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, album_item, url, art_embedded, connection]() {
SaveEmbeddedCoverFinished(reply, album_item, url, art_embedded); SaveEmbeddedCoverFinished(reply, album_item, url, art_embedded);
QObject::disconnect(*connection);
}); });
cover_save_tasks_.insert(album_item, url); cover_save_tasks_.insert(album_item, url);
} }

View File

@@ -26,6 +26,7 @@
#include <functional> #include <functional>
#include <iterator> #include <iterator>
#include <limits> #include <limits>
#include <memory>
#include <QtGlobal> #include <QtGlobal>
#include <QtConcurrentRun> #include <QtConcurrentRun>
@@ -99,6 +100,7 @@
#include "edittagdialog.h" #include "edittagdialog.h"
#include "ui_edittagdialog.h" #include "ui_edittagdialog.h"
using std::make_shared;
using namespace Qt::Literals::StringLiterals; using namespace Qt::Literals::StringLiterals;
namespace { namespace {
@@ -1311,7 +1313,11 @@ void EditTagDialog::SaveData() {
save_tags_options |= TagReaderClient::SaveOption::Cover; save_tags_options |= TagReaderClient::SaveOption::Cover;
} }
TagReaderReplyPtr reply = tagreader_client_->WriteFileAsync(ref.current_.url().toLocalFile(), ref.current_, save_tags_options, save_tag_cover_data); TagReaderReplyPtr reply = tagreader_client_->WriteFileAsync(ref.current_.url().toLocalFile(), ref.current_, save_tags_options, save_tag_cover_data);
QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, ref]() { SongSaveTagsComplete(reply, ref.current_.url().toLocalFile(), ref.current_, ref.cover_action_); }, Qt::QueuedConnection); SharedPtr<QMetaObject::Connection> connection = make_shared<QMetaObject::Connection>();
*connection = QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, ref, connection]() {
SongSaveTagsComplete(reply, ref.current_.url().toLocalFile(), ref.current_, ref.cover_action_);
QObject::disconnect(*connection);
}, Qt::QueuedConnection);
} }
// If the cover was changed, but no tags written, make sure to update the collection. // If the cover was changed, but no tags written, make sure to update the collection.
else if (ref.cover_action_ != UpdateCoverAction::None && !ref.current_.effective_albumartist().isEmpty() && !ref.current_.album().isEmpty()) { else if (ref.cover_action_ != UpdateCoverAction::None && !ref.current_.effective_albumartist().isEmpty() && !ref.current_.album().isEmpty()) {

View File

@@ -434,7 +434,11 @@ bool Playlist::setData(const QModelIndex &idx, const QVariant &value, const int
if (song.url().isLocalFile()) { if (song.url().isLocalFile()) {
TagReaderReplyPtr reply = tagreader_client_->WriteFileAsync(song.url().toLocalFile(), song); TagReaderReplyPtr reply = tagreader_client_->WriteFileAsync(song.url().toLocalFile(), song);
QPersistentModelIndex persistent_index = QPersistentModelIndex(idx); QPersistentModelIndex persistent_index = QPersistentModelIndex(idx);
QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, persistent_index, item]() { SongSaveComplete(reply, persistent_index, item->OriginalMetadata()); }, Qt::QueuedConnection); SharedPtr<QMetaObject::Connection> connection = make_shared<QMetaObject::Connection>();
*connection = QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, persistent_index, item, connection]() {
SongSaveComplete(reply, persistent_index, item->OriginalMetadata());
QObject::disconnect(*connection);
}, Qt::QueuedConnection);
} }
else if (song.is_radio()) { else if (song.is_radio()) {
item->SetMetadata(song); item->SetMetadata(song);

View File

@@ -384,8 +384,7 @@ void TagReaderClient::SaveSongsPlaycountAsync(const SongList &songs) {
Q_ASSERT(QThread::currentThread() != thread()); Q_ASSERT(QThread::currentThread() != thread());
for (const Song &song : songs) { for (const Song &song : songs) {
TagReaderReplyPtr reply = SaveSongPlaycountAsync(song.url().toLocalFile(), song.playcount()); SaveSongPlaycountAsync(song.url().toLocalFile(), song.playcount());
QObject::connect(&*reply, &TagReaderReply::Finished, &*reply, &TagReaderReply::deleteLater);
} }
} }
@@ -418,8 +417,7 @@ void TagReaderClient::SaveSongsRatingAsync(const SongList &songs) {
Q_ASSERT(QThread::currentThread() != thread()); Q_ASSERT(QThread::currentThread() != thread());
for (const Song &song : songs) { for (const Song &song : songs) {
TagReaderReplyPtr reply = SaveSongRatingAsync(song.url().toLocalFile(), song.rating()); SaveSongRatingAsync(song.url().toLocalFile(), song.rating());
QObject::connect(&*reply, &TagReaderReply::Finished, &*reply, &TagReaderReply::deleteLater);
} }
} }

View File

@@ -40,7 +40,4 @@ void TagReaderLoadCoverDataReply::EmitFinished() {
Q_EMIT TagReaderReply::Finished(filename_, result_); Q_EMIT TagReaderReply::Finished(filename_, result_);
Q_EMIT TagReaderLoadCoverDataReply::Finished(filename_, data_, result_); Q_EMIT TagReaderLoadCoverDataReply::Finished(filename_, data_, result_);
QObject::disconnect(this, &TagReaderReply::Finished, nullptr, nullptr);
QObject::disconnect(this, &TagReaderLoadCoverDataReply::Finished, nullptr, nullptr);
} }

View File

@@ -40,7 +40,4 @@ void TagReaderLoadCoverImageReply::EmitFinished() {
Q_EMIT TagReaderReply::Finished(filename_, result_); Q_EMIT TagReaderReply::Finished(filename_, result_);
Q_EMIT TagReaderLoadCoverImageReply::Finished(filename_, image_, result_); Q_EMIT TagReaderLoadCoverImageReply::Finished(filename_, image_, result_);
QObject::disconnect(this, &TagReaderReply::Finished, nullptr, nullptr);
QObject::disconnect(this, &TagReaderLoadCoverImageReply::Finished, nullptr, nullptr);
} }

View File

@@ -40,7 +40,4 @@ void TagReaderReadFileReply::EmitFinished() {
Q_EMIT TagReaderReply::Finished(filename_, result_); Q_EMIT TagReaderReply::Finished(filename_, result_);
Q_EMIT TagReaderReadFileReply::Finished(filename_, song_, result_); Q_EMIT TagReaderReadFileReply::Finished(filename_, song_, result_);
QObject::disconnect(this, &TagReaderReply::Finished, nullptr, nullptr);
QObject::disconnect(this, &TagReaderReadFileReply::Finished, nullptr, nullptr);
} }

View File

@@ -52,6 +52,4 @@ void TagReaderReply::EmitFinished() {
Q_EMIT TagReaderReply::Finished(filename_, result_); Q_EMIT TagReaderReply::Finished(filename_, result_);
QObject::disconnect(this, &TagReaderReply::Finished, nullptr, nullptr);
} }