From 40e21b0c6f6792348fe62623ce7efae483e53b24 Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Mon, 11 Jul 2022 20:43:47 +0300 Subject: [PATCH 01/24] coverartfetcher: update the latest status. --- CMakeLists.txt | 2 + src/library/dlgcoverartfullsize.cpp | 17 ++ src/library/dlgcoverartfullsize.h | 1 + src/library/dlgtagfetcher.cpp | 207 ++++++++++++++++- src/library/dlgtagfetcher.h | 33 ++- src/library/dlgtagfetcher.ui | 141 +++++++++++- src/library/dlgtrackinfo.cpp | 2 +- src/library/library_prefs.cpp | 5 + src/library/library_prefs.h | 2 + src/musicbrainz/tagfetcher.cpp | 213 ++++++++++++++++++ src/musicbrainz/tagfetcher.h | 45 ++++ .../web/coverartarchiveimagetask.cpp | 72 ++++++ .../web/coverartarchiveimagetask.h | 40 ++++ .../web/coverartarchivelinkstask.cpp | 158 +++++++++++++ .../web/coverartarchivelinkstask.h | 44 ++++ src/preferences/dialog/dlgpreflibrary.cpp | 33 +++ src/preferences/dialog/dlgpreflibrary.h | 7 + src/preferences/dialog/dlgpreflibrarydlg.ui | 66 +++++- src/widget/wcoverartlabel.cpp | 14 +- src/widget/wcoverartlabel.h | 4 + src/widget/wtrackmenu.cpp | 2 +- 21 files changed, 1084 insertions(+), 24 deletions(-) create mode 100644 src/musicbrainz/web/coverartarchiveimagetask.cpp create mode 100644 src/musicbrainz/web/coverartarchiveimagetask.h create mode 100644 src/musicbrainz/web/coverartarchivelinkstask.cpp create mode 100644 src/musicbrainz/web/coverartarchivelinkstask.h diff --git a/CMakeLists.txt b/CMakeLists.txt index aba4a764df8..643fb15907b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -818,6 +818,8 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL src/musicbrainz/musicbrainzxml.cpp src/musicbrainz/tagfetcher.cpp src/musicbrainz/web/acoustidlookuptask.cpp + src/musicbrainz/web/coverartarchiveimagetask.cpp + src/musicbrainz/web/coverartarchivelinkstask.cpp src/musicbrainz/web/musicbrainzrecordingstask.cpp src/network/jsonwebtask.cpp src/network/networktask.cpp diff --git a/src/library/dlgcoverartfullsize.cpp b/src/library/dlgcoverartfullsize.cpp index 8d63720fb55..6fa9e847ae5 100644 --- a/src/library/dlgcoverartfullsize.cpp +++ b/src/library/dlgcoverartfullsize.cpp @@ -82,6 +82,23 @@ void DlgCoverArtFullSize::init(TrackPointer pTrack) { slotLoadTrack(pTrack); } +void DlgCoverArtFullSize::init(const QByteArray& fetchedCoverArtBytes) { + QPixmap image; + image.loadFromData(fetchedCoverArtBytes); + + resize(image.size().width(), image.size().height()); + show(); + raise(); + activateWindow(); + + QString fetchedCoverArtWindowTitle = "Fetched Cover Art"; + + setWindowTitle(fetchedCoverArtWindowTitle); + + //TODO: Do a better scaling. It populates wrong if the cover art size highest. + coverArt->setPixmap(image); +} + void DlgCoverArtFullSize::slotLoadTrack(TrackPointer pTrack) { if (m_pLoadedTrack != nullptr) { disconnect(m_pLoadedTrack.get(), diff --git a/src/library/dlgcoverartfullsize.h b/src/library/dlgcoverartfullsize.h index cd7fb904a19..9c9444ffd95 100644 --- a/src/library/dlgcoverartfullsize.h +++ b/src/library/dlgcoverartfullsize.h @@ -22,6 +22,7 @@ class DlgCoverArtFullSize ~DlgCoverArtFullSize() override = default; void init(TrackPointer pTrack); + void init(const QByteArray& fetchedCoverArtBytes); void mousePressEvent(QMouseEvent* event) override; void mouseReleaseEvent(QMouseEvent* ) override; void mouseMoveEvent(QMouseEvent* ) override; diff --git a/src/library/dlgtagfetcher.cpp b/src/library/dlgtagfetcher.cpp index c6ea4adc776..8decb2e9f9a 100644 --- a/src/library/dlgtagfetcher.cpp +++ b/src/library/dlgtagfetcher.cpp @@ -4,7 +4,11 @@ #include #include "defs_urls.h" +#include "library/coverartcache.h" +#include "library/coverartutils.h" +#include "library/library_prefs.h" #include "moc_dlgtagfetcher.cpp" +#include "preferences/dialog/dlgpreflibrary.h" #include "track/track.h" #include "track/tracknumbers.h" @@ -96,13 +100,16 @@ void updateOriginalTag(const Track& track, QTreeWidget* pParent) { } // anonymous namespace -DlgTagFetcher::DlgTagFetcher( - const TrackModel* pTrackModel) +DlgTagFetcher::DlgTagFetcher(UserSettingsPointer pConfig, const TrackModel* pTrackModel) // No parent because otherwise it inherits the style parent's // style which can make it unreadable. Bug #673411 : QDialog(nullptr), + m_pConfig(pConfig), m_pTrackModel(pTrackModel), - m_tagFetcher(this) { + m_tagFetcher(this), + m_pWCoverArtMenu(make_parented(this)), + m_pWCurrentCoverArtLabel(make_parented(this)), + m_pWFetchedCoverArtLabel(make_parented(this)) { init(); } @@ -110,6 +117,16 @@ void DlgTagFetcher::init() { setupUi(this); setWindowIcon(QIcon(MIXXX_ICON_PATH)); + currentCoverArtLayout->setAlignment(Qt::AlignRight | Qt::AlignTop | Qt::AlignCenter); + currentCoverArtLayout->setSpacing(0); + currentCoverArtLayout->setContentsMargins(0, 0, 0, 0); + currentCoverArtLayout->insertWidget(0, m_pWCurrentCoverArtLabel.get()); + + fetchedCoverArtLayout->setAlignment(Qt::AlignRight | Qt::AlignBottom | Qt::AlignCenter); + fetchedCoverArtLayout->setSpacing(0); + fetchedCoverArtLayout->setContentsMargins(0, 0, 0, 0); + fetchedCoverArtLayout->insertWidget(0, m_pWFetchedCoverArtLabel.get()); + if (m_pTrackModel) { connect(btnPrev, &QPushButton::clicked, this, &DlgTagFetcher::slotPrev); connect(btnNext, &QPushButton::clicked, this, &DlgTagFetcher::slotNext); @@ -117,6 +134,7 @@ void DlgTagFetcher::init() { btnNext->hide(); btnPrev->hide(); } + connect(btnApply, &QPushButton::clicked, this, &DlgTagFetcher::apply); connect(btnQuit, &QPushButton::clicked, this, &DlgTagFetcher::quit); connect(btnRetry, &QPushButton::clicked, this, &DlgTagFetcher::retry); @@ -138,6 +156,31 @@ void DlgTagFetcher::init() { connect(&m_tagFetcher, &TagFetcher::networkError, this, &DlgTagFetcher::slotNetworkResult); loadingProgressBar->setMaximum(kMaximumValueOfQProgressBar); + + btnRetry->setDisabled(true); + + CoverArtCache* pCache = CoverArtCache::instance(); + if (pCache) { + connect(pCache, + &CoverArtCache::coverFound, + this, + &DlgTagFetcher::slotCoverFound); + } + + connect(&m_tagFetcher, + &TagFetcher::coverArtArchiveLinksAvailable, + this, + &DlgTagFetcher::slotStartFetchCoverArt); + + connect(&m_tagFetcher, + &TagFetcher::coverArtImageFetchAvailable, + this, + &DlgTagFetcher::slotLoadBytesToLabel); + + connect(&m_tagFetcher, + &TagFetcher::coverArtLinkNotFound, + this, + &DlgTagFetcher::slotCoverArtLinkNotFound); } void DlgTagFetcher::slotNext() { @@ -173,6 +216,16 @@ void DlgTagFetcher::loadTrack(const TrackPointer& pTrack) { &DlgTagFetcher::slotTrackChanged); m_data = Data(); } + tags->clear(); + + CoverInfo coverInfo; + QPixmap pixmap; + m_pWFetchedCoverArtLabel->setCoverArt(coverInfo, pixmap); + + disconnect(m_track.get(), + &Track::changed, + this, + &DlgTagFetcher::slotTrackChanged); m_track = pTrack; if (!m_track) { @@ -181,7 +234,7 @@ void DlgTagFetcher::loadTrack(const TrackPointer& pTrack) { btnRetry->setDisabled(true); btnApply->setDisabled(true); - successMessage->setVisible(false); + statusMessage->setVisible(false); loadingProgressBar->setVisible(true); loadingProgressBar->setValue(kMinimumValueOfQProgressBar); addDivider(tr("Original tags"), tags); @@ -202,6 +255,10 @@ void DlgTagFetcher::loadTrack(const QModelIndex& index) { } void DlgTagFetcher::slotTrackChanged(TrackId trackId) { + if (!m_fetchedCoverArtByteArrays.isNull()) { + m_fetchedCoverArtByteArrays.clear(); + } + if (m_track && m_track->getId() == trackId) { updateOriginalTag(*m_track, tags); } @@ -270,6 +327,35 @@ void DlgTagFetcher::apply() { trackRelease.releaseGroupId); } #endif // __EXTRA_METADATA__ + + if (!m_fetchedCoverArtByteArrays.isNull()) { + // Worker can be called here. + QString coverArtLocation = m_track->getLocation() + ".jpg"; + QFile coverArtFile(coverArtLocation); + coverArtFile.open(QIODevice::WriteOnly); + coverArtFile.write(m_fetchedCoverArtByteArrays); + coverArtFile.close(); + + auto selectedCover = mixxx::FileAccess(mixxx::FileInfo(coverArtLocation)); + QImage updatedCoverArtFound(coverArtLocation); + if (!updatedCoverArtFound.isNull()) { + CoverInfoRelative coverInfo; + coverInfo.type = CoverInfo::FILE; + coverInfo.source = CoverInfo::USER_SELECTED; + coverInfo.coverLocation = coverArtLocation; + coverInfo.setImage(updatedCoverArtFound); + m_pWCurrentCoverArtLabel->setCoverArt( + CoverInfo{}, QPixmap::fromImage(updatedCoverArtFound)); + m_track->setCoverInfo(coverInfo); + m_fetchedCoverArtByteArrays.clear(); + m_pWFetchedCoverArtLabel->loadData(m_fetchedCoverArtByteArrays); + m_pWFetchedCoverArtLabel->setCoverArt(CoverInfo{}, + QPixmap(CoverArtUtils::defaultCoverLocation())); + QString coverArtAppliedMessage = tr("Cover art applied."); + statusMessage->setText(coverArtAppliedMessage); + } + } + m_track->replaceMetadataFromSource( std::move(trackMetadata), // Prevent re-import of outdated metadata from file tags @@ -301,6 +387,12 @@ void DlgTagFetcher::showProgressOfConstantTask(const QString& text) { loadingProgressBar->setValue(loadingProgressBar->value() + kPercentOfConstantTask); } +void DlgTagFetcher::loadCurrentTrackCover() { + m_pWCurrentCoverArtLabel->loadTrack(m_track); + CoverArtCache* pCache = CoverArtCache::instance(); + pCache->requestTrackCover(this, m_track); +} + void DlgTagFetcher::showProgressOfRecordingTask() { QString status = tr("Fetching track data from the MusicBrainz database"); loadingProgressBar->setFormat(status); @@ -328,7 +420,7 @@ void DlgTagFetcher::fetchTagFinished( btnApply->setEnabled(true); btnRetry->setEnabled(false); loadingProgressBar->setVisible(false); - successMessage->setVisible(true); + statusMessage->setVisible(true); VERIFY_OR_DEBUG_ASSERT(m_track) { return; @@ -399,4 +491,109 @@ void DlgTagFetcher::tagSelected() { } const int tagIndex = tags->currentItem()->data(0, Qt::UserRole).toInt(); m_data.m_selectedTag = tagIndex; + + if (!m_fetchedCoverArtByteArrays.isNull()) { + m_fetchedCoverArtByteArrays.clear(); + CoverInfo coverInfo; + QPixmap pixmap; + m_pWFetchedCoverArtLabel->setCoverArt(coverInfo, pixmap); + } + + const mixxx::musicbrainz::TrackRelease& trackRelease = m_data.m_tags[tagIndex]; + QUuid selectedTagAlbumId = trackRelease.albumReleaseId; + statusMessage->setVisible(false); + + QString coverArtMessage = tr("Looking for cover art"); + loadingProgressBar->setVisible(true); + loadingProgressBar->setFormat(coverArtMessage); + loadingProgressBar->setMinimum(0); + loadingProgressBar->setMaximum(100); + loadingProgressBar->setValue(10); + + m_tagFetcher.startFetchCoverArtLinks(selectedTagAlbumId); +} + +void DlgTagFetcher::slotCoverFound( + const QObject* pRequestor, + const CoverInfo& coverInfo, + const QPixmap& pixmap, + mixxx::cache_key_t requestedCacheKey, + bool coverInfoUpdated) { + Q_UNUSED(requestedCacheKey); + Q_UNUSED(coverInfoUpdated); + if (pRequestor == this && + m_track && + m_track->getLocation() == coverInfo.trackLocation) { + m_trackRecord.setCoverInfo(coverInfo); + m_pWCurrentCoverArtLabel->setCoverArt(coverInfo, pixmap); + } +} + +void DlgTagFetcher::slotUpdateStatusMessage(const QString& message) { + loadingProgressBar->setVisible(false); + statusMessage->setVisible(true); + statusMessage->setText(message); +} + +void DlgTagFetcher::slotStartFetchCoverArt(const QList& allUrls) { + int fetchedCoverArtQualityConfigValue = + m_pConfig->getValue(mixxx::library::prefs::kCoverArtFetcherQualityConfigKey, + static_cast(DlgPrefLibrary::CoverArtFetcherQuality::Low)); + + DlgPrefLibrary::CoverArtFetcherQuality fetcherQuality = + static_cast( + fetchedCoverArtQualityConfigValue); + + // Maximum size of the allUrls are 4. + if (fetcherQuality == DlgPrefLibrary::CoverArtFetcherQuality::Highest) { + getCoverArt(allUrls.last()); + qDebug() << allUrls.last(); + return; + } else if (fetcherQuality == DlgPrefLibrary::CoverArtFetcherQuality::High) { + qDebug() << allUrls.size(); + qDebug() << allUrls; + allUrls.size() < 3 ? getCoverArt(allUrls.at(1)) : getCoverArt(allUrls.at(2)); + return; + } else if (fetcherQuality == DlgPrefLibrary::CoverArtFetcherQuality::Medium) { + getCoverArt(allUrls.at(1)); + qDebug() << allUrls.at(1); + return; + } else { + getCoverArt(allUrls.first()); + } +} + +void DlgTagFetcher::slotLoadBytesToLabel(const QByteArray& data) { + loadingProgressBar->setValue(80); + QPixmap fetchedCoverArtPixmap; + fetchedCoverArtPixmap.loadFromData(data); + CoverInfo coverInfo; + coverInfo.type = CoverInfo::NONE; + coverInfo.source = CoverInfo::USER_SELECTED; + coverInfo.setImage(); + + loadingProgressBar->setVisible(false); + QString coverArtMessage = tr("Cover art found and it is ready to be applied."); + statusMessage->setVisible(true); + statusMessage->setText(coverArtMessage); + + m_fetchedCoverArtByteArrays = data; + m_pWFetchedCoverArtLabel->loadData( + m_fetchedCoverArtByteArrays); //This data loaded because for full size. + m_pWFetchedCoverArtLabel->setCoverArt(coverInfo, fetchedCoverArtPixmap); +} + +void DlgTagFetcher::getCoverArt(const QString& url) { + QString coverArtMessage = tr("Cover art found getting image"); + loadingProgressBar->setFormat(coverArtMessage); + loadingProgressBar->setValue(40); + + m_tagFetcher.startFetchCoverArtImage(url); +} + +void DlgTagFetcher::slotCoverArtLinkNotFound() { + loadingProgressBar->setVisible(false); + statusMessage->setVisible(true); + QString message = tr("Cover Art not available for that tag. Please try another."); + statusMessage->setText(message); } diff --git a/src/library/dlgtagfetcher.h b/src/library/dlgtagfetcher.h index 0bfc759dd4b..345879d9356 100644 --- a/src/library/dlgtagfetcher.h +++ b/src/library/dlgtagfetcher.h @@ -8,6 +8,10 @@ #include "library/ui_dlgtagfetcher.h" #include "musicbrainz/tagfetcher.h" #include "track/track_decl.h" +#include "track/trackrecord.h" +#include "util/parented_ptr.h" +#include "widget/wcoverartlabel.h" +#include "widget/wcoverartmenu.h" /// A dialog box to fetch track metadata from MusicBrainz. /// Use TrackPointer to load a track into the dialog or @@ -19,7 +23,7 @@ class DlgTagFetcher : public QDialog, public Ui::DlgTagFetcher { public: // TODO: Remove dependency on TrackModel explicit DlgTagFetcher( - const TrackModel* pTrackModel = nullptr); + UserSettingsPointer pConfig, const TrackModel* pTrackModel = nullptr); ~DlgTagFetcher() override = default; void init(); @@ -49,10 +53,25 @@ class DlgTagFetcher : public QDialog, public Ui::DlgTagFetcher { void reject() override; void slotNext(); void slotPrev(); + void slotCoverFound( + const QObject* pRequestor, + const CoverInfo& coverInfo, + const QPixmap& pixmap, + mixxx::cache_key_t requestedCacheKey, + bool coverInfoUpdated); + void slotUpdateStatusMessage(const QString& message); + void slotStartFetchCoverArt(const QList& allUrls); + void slotLoadBytesToLabel(const QByteArray& data); + void slotCoverArtLinkNotFound(); private: - void updateStack(); + // Called on population or changed via buttons Next&Prev. + void loadCurrentTrackCover(); + void loadTrackInternal(const TrackPointer& track); void addDivider(const QString& text, QTreeWidget* parent) const; + void getCoverArt(const QString& url); + + UserSettingsPointer m_pConfig; const TrackModel* const m_pTrackModel; @@ -64,6 +83,14 @@ class DlgTagFetcher : public QDialog, public Ui::DlgTagFetcher { int m_percentForOneRecording; + parented_ptr m_pWCoverArtMenu; + parented_ptr m_pWCurrentCoverArtLabel; + parented_ptr m_pWFetchedCoverArtLabel; + + mixxx::TrackRecord m_trackRecord; + + int m_progressBarStep; + struct Data { Data() : m_selectedTag(-1) { @@ -72,4 +99,6 @@ class DlgTagFetcher : public QDialog, public Ui::DlgTagFetcher { QList m_tags; }; Data m_data; + + QByteArray m_fetchedCoverArtByteArrays; }; diff --git a/src/library/dlgtagfetcher.ui b/src/library/dlgtagfetcher.ui index 0ad0cc586b4..1cd7588af08 100644 --- a/src/library/dlgtagfetcher.ui +++ b/src/library/dlgtagfetcher.ui @@ -121,9 +121,12 @@ - - - + + Qt::LeftToRight + + + + QLabel { font-weight: bold; } @@ -181,14 +184,102 @@ + + + + + + + 0 + 0 + + + + QLabel { font-weight: bold; } + + + Current Cover Art + + + + + + + + 250 + 250 + + + + + 0 + + + QLayout::SetDefaultConstraint + + + + + + + + + 0 + 0 + + + + QLabel { font-weight: bold; } + + + Found Cover Art + + + + + + + + 250 + 250 + + + + + 0 + + + QLayout::SetDefaultConstraint + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + - + - + + + QLayout::SetMaximumSize + @@ -197,15 +288,44 @@ - + + + + 0 + 0 + + + + Qt::LeftToRight + The results are ready to be applied. + + + + + + Qt::Horizontal + + + QSizePolicy::Maximum + + + + 20000 + 0 + + + + + + - + @@ -221,7 +341,7 @@ - + @@ -237,10 +357,7 @@ - - - - + Qt::Horizontal diff --git a/src/library/dlgtrackinfo.cpp b/src/library/dlgtrackinfo.cpp index 5a77a64650b..705f095a118 100644 --- a/src/library/dlgtrackinfo.cpp +++ b/src/library/dlgtrackinfo.cpp @@ -707,7 +707,7 @@ void DlgTrackInfo::slotTrackChanged(TrackId trackId) { void DlgTrackInfo::slotImportMetadataFromMusicBrainz() { if (!m_pDlgTagFetcher) { m_pDlgTagFetcher = std::make_unique( - m_pTrackModel); + m_pUserSettings, m_pTrackModel); connect(m_pDlgTagFetcher.get(), &QDialog::finished, this, diff --git a/src/library/library_prefs.cpp b/src/library/library_prefs.cpp index 40d8db69bc2..5c8c57360e0 100644 --- a/src/library/library_prefs.cpp +++ b/src/library/library_prefs.cpp @@ -69,3 +69,8 @@ const ConfigKey mixxx::library::prefs::kUseRelativePathOnExportConfigKey = ConfigKey{ mixxx::library::prefs::kConfigGroup, QStringLiteral("UseRelativePathOnExport")}; + +const ConfigKey mixxx::library::prefs::kCoverArtFetcherQualityConfigKey = + ConfigKey{ + mixxx::library::prefs::kConfigGroup, + QStringLiteral("CoverArtFetcherQuality")}; diff --git a/src/library/library_prefs.h b/src/library/library_prefs.h index cf7cbfa6c1f..ba1a08878ee 100644 --- a/src/library/library_prefs.h +++ b/src/library/library_prefs.h @@ -40,6 +40,8 @@ extern const ConfigKey kSyncSeratoMetadataConfigKey; extern const ConfigKey kUseRelativePathOnExportConfigKey; +extern const ConfigKey kCoverArtFetcherQualityConfigKey; + } // namespace prefs } // namespace library diff --git a/src/musicbrainz/tagfetcher.cpp b/src/musicbrainz/tagfetcher.cpp index 7f07e1bdb81..9654e7b25fa 100644 --- a/src/musicbrainz/tagfetcher.cpp +++ b/src/musicbrainz/tagfetcher.cpp @@ -16,6 +16,12 @@ constexpr int kAcoustIdTimeoutMillis = 60000; // msec // Long timeout to cope with occasional server-side unresponsiveness constexpr int kMusicBrainzTimeoutMillis = 60000; // msec +// Long timeout to cope with occasional server-side unresponsiveness +constexpr int kCoverArtArchiveLinksTimeoutMilis = 60000; // msec + +// Long timeout to cope with occasional server-side unresponsiveness +constexpr int kCoverArtArchiveImageTimeoutMilis = 60000; // msec + } // anonymous namespace TagFetcher::TagFetcher(QObject* parent) @@ -56,6 +62,14 @@ void TagFetcher::cancel() { m_pMusicBrainzTask->invokeAbort(); DEBUG_ASSERT(!m_pMusicBrainzTask); } + if (m_pCoverArtArchiveLinksTask) { + m_pCoverArtArchiveLinksTask->invokeAbort(); + DEBUG_ASSERT(!m_pCoverArtArchiveLinksTask); + } + if (m_pCoverArtArchiveImageTask) { + m_pCoverArtArchiveImageTask->invokeAbort(); + DEBUG_ASSERT(!m_pCoverArtArchiveImageTask); + } } void TagFetcher::terminate() { @@ -277,3 +291,202 @@ void TagFetcher::slotMusicBrainzTaskSucceeded( std::move(pTrack), std::move(guessedTrackReleases)); } + +void TagFetcher::startFetchCoverArtLinks( + const QUuid& albumReleaseId) { + //In here the progress message can be handled better. + //emit fetchProgress(tr("Finding Possible Cover Arts on Cover Art Archive")); + DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); + terminate(); + + m_pCoverArtArchiveLinksTask = make_parented( + &m_network, + std::move(albumReleaseId), + this); + + connect(m_pCoverArtArchiveLinksTask, + &mixxx::CoverArtArchiveLinksTask::succeeded, + this, + &TagFetcher::slotCoverArtArchiveLinksTaskSucceeded); + connect(m_pCoverArtArchiveLinksTask, + &mixxx::CoverArtArchiveLinksTask::failed, + this, + &TagFetcher::slotCoverArtArchiveLinksTaskFailed); + connect(m_pCoverArtArchiveLinksTask, + &mixxx::CoverArtArchiveLinksTask::aborted, + this, + &TagFetcher::slotCoverArtArchiveLinksTaskAborted); + connect(m_pCoverArtArchiveLinksTask, + &mixxx::CoverArtArchiveLinksTask::networkError, + this, + &TagFetcher::slotCoverArtArchiveLinksTaskNetworkError); + + m_pCoverArtArchiveLinksTask->invokeStart( + kCoverArtArchiveLinksTimeoutMilis); +} + +bool TagFetcher::onCoverArtArchiveLinksTaskTerminated() { + DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); + auto* const pCoverArtArchiveLinksTask = m_pCoverArtArchiveLinksTask.get(); + DEBUG_ASSERT(sender()); + VERIFY_OR_DEBUG_ASSERT(pCoverArtArchiveLinksTask == + qobject_cast(sender())) { + return false; + } + m_pCoverArtArchiveLinksTask = nullptr; + const auto taskDeleter = mixxx::ScopedDeleteLater(pCoverArtArchiveLinksTask); + pCoverArtArchiveLinksTask->disconnect(this); + return true; +} + +void TagFetcher::slotCoverArtArchiveLinksTaskAborted() { + DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); + if (!onCoverArtArchiveLinksTaskTerminated()) { + return; + } + + terminate(); +} + +void TagFetcher::slotCoverArtArchiveLinksTaskNetworkError( + QNetworkReply::NetworkError errorCode, + const QString& errorString, + const mixxx::network::WebResponseWithContent& responseWithContent) { + Q_UNUSED(responseWithContent); + DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); + if (!onCoverArtArchiveLinksTaskTerminated()) { + return; + } + + // (TODO) Handle the error better for Cover Art Archive Links. + emit coverArtLinkNotFound(); + terminate(); +} + +void TagFetcher::slotCoverArtArchiveLinksTaskFailed( + const mixxx::network::JsonWebResponse& response) { + DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); + if (!onCoverArtArchiveLinksTaskTerminated()) { + return; + } + + terminate(); + + emit networkError( + response.statusCode(), + "CoverArtArchive", + response.content().toJson(), + -1); +} + +void TagFetcher::slotCoverArtArchiveLinksTaskSucceeded( + const QList& allUrls) { + DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); + if (!onCoverArtArchiveLinksTaskTerminated()) { + return; + } + + auto pTrack = std::move(m_pTrack); + terminate(); + + emit coverArtArchiveLinksAvailable(std::move(allUrls)); +} + +void TagFetcher::startFetchCoverArtImage( + const QString& coverArtUrl) { + m_pCoverArtArchiveImageTask = make_parented( + &m_network, + coverArtUrl, + this); + + connect(m_pCoverArtArchiveImageTask, + &mixxx::CoverArtArchiveImageTask::succeeded, + this, + &TagFetcher::slotCoverArtArchiveImageTaskSucceeded); + connect(m_pCoverArtArchiveImageTask, + &mixxx::CoverArtArchiveImageTask::failed, + this, + &TagFetcher::slotCoverArtArchiveImageTaskFailed); + connect(m_pCoverArtArchiveImageTask, + &mixxx::CoverArtArchiveImageTask::aborted, + this, + &TagFetcher::slotCoverArtArchiveImageTaskAborted); + connect(m_pCoverArtArchiveImageTask, + &mixxx::CoverArtArchiveImageTask::networkError, + this, + &TagFetcher::slotCoverArtArchiveImageTaskNetworkError); + + m_pCoverArtArchiveImageTask->invokeStart( + kCoverArtArchiveImageTimeoutMilis); +} + +void TagFetcher::slotCoverArtArchiveImageTaskSucceeded(const QByteArray& coverArtBytes) { + if (!onCoverArtArchiveImageTaskTerminated()) { + return; + } + + auto pTrack = std::move(m_pTrack); + terminate(); + + emit coverArtImageFetchAvailable(coverArtBytes); +} + +void TagFetcher::slotCoverArtArchiveImageTaskAborted() { + DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); + if (!onCoverArtArchiveImageTaskTerminated()) { + return; + } + + terminate(); +} + +bool TagFetcher::onCoverArtArchiveImageTaskTerminated() { + DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); + auto* const pCoverArtArchiveImageTask = m_pCoverArtArchiveImageTask.get(); + DEBUG_ASSERT(sender()); + VERIFY_OR_DEBUG_ASSERT(pCoverArtArchiveImageTask == + qobject_cast(sender())) { + return false; + } + m_pCoverArtArchiveImageTask = nullptr; + const auto taskDeleter = mixxx::ScopedDeleteLater(pCoverArtArchiveImageTask); + pCoverArtArchiveImageTask->disconnect(this); + return true; +} + +void TagFetcher::slotCoverArtArchiveImageTaskFailed( + const mixxx::network::WebResponse& response, + int errorCode, + const QString& errorMessage) { + DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); + if (!onCoverArtArchiveImageTaskTerminated()) { + return; + } + + terminate(); + + emit networkError( + response.statusCode(), + "CoverArtImageTask", + errorMessage, + errorCode); +} + +void TagFetcher::slotCoverArtArchiveImageTaskNetworkError( + QNetworkReply::NetworkError errorCode, + const QString& errorString, + const mixxx::network::WebResponseWithContent& responseWithContent) { + Q_UNUSED(responseWithContent); + DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); + if (!onCoverArtArchiveImageTaskTerminated()) { + return; + } + + terminate(); + + emit networkError( + mixxx::network::kHttpStatusCodeInvalid, + QStringLiteral("CoverArtArchive"), + errorString, + errorCode); +} diff --git a/src/musicbrainz/tagfetcher.h b/src/musicbrainz/tagfetcher.h index 1fad8369f99..63412d0acf1 100644 --- a/src/musicbrainz/tagfetcher.h +++ b/src/musicbrainz/tagfetcher.h @@ -4,6 +4,8 @@ #include #include "musicbrainz/web/acoustidlookuptask.h" +#include "musicbrainz/web/coverartarchiveimagetask.h" +#include "musicbrainz/web/coverartarchivelinkstask.h" #include "musicbrainz/web/musicbrainzrecordingstask.h" #include "track/track_decl.h" #include "util/parented_ptr.h" @@ -24,6 +26,21 @@ class TagFetcher : public QObject { void startFetch( TrackPointer pTrack); + //This is called from dlgTagFetcher. + //This starts the initial task for to find the cover art links + //4 Possible cover art links fetched in this task. + //This can be >1200px-1200px-500px-250px image links. + void startFetchCoverArtLinks(const QUuid& albumReleaseId); + + //After the first task is done successfully. + //This is called automatically. + //This task starts to fetch the image. + //Link provided from preference option. + //After a success task, related label updated with cover art. + //If user presses apply, cover art downloaded and applied to the song. + void startFetchCoverArtImage( + const QString& coverArtUrl); + public slots: void cancel(); @@ -40,6 +57,10 @@ class TagFetcher : public QObject { const QString& app, const QString& message, int code); + void fetchedCoverUpdate(const QByteArray& coverInfo); + void coverArtImageFetchAvailable(const QByteArray& coverArtBytes); + void coverArtArchiveLinksAvailable(const QList& allUrls); + void coverArtLinkNotFound(); private slots: void slotFingerprintReady(); @@ -66,6 +87,26 @@ class TagFetcher : public QObject { const QString& errorString, const mixxx::network::WebResponseWithContent& responseWithContent); + void slotCoverArtArchiveLinksTaskSucceeded(const QList& allUrls); + void slotCoverArtArchiveLinksTaskFailed( + const mixxx::network::JsonWebResponse& response); + void slotCoverArtArchiveLinksTaskAborted(); + void slotCoverArtArchiveLinksTaskNetworkError( + QNetworkReply::NetworkError errorCode, + const QString& errorString, + const mixxx::network::WebResponseWithContent& responseWithContent); + + void slotCoverArtArchiveImageTaskSucceeded(const QByteArray& coverArtBytes); + void slotCoverArtArchiveImageTaskFailed( + const mixxx::network::WebResponse& response, + int errorCode, + const QString& errorMessage); + void slotCoverArtArchiveImageTaskAborted(); + void slotCoverArtArchiveImageTaskNetworkError( + QNetworkReply::NetworkError errorCode, + const QString& errorString, + const mixxx::network::WebResponseWithContent& responseWithContent); + private: void terminate(); @@ -77,5 +118,9 @@ class TagFetcher : public QObject { parented_ptr m_pMusicBrainzTask; + parented_ptr m_pCoverArtArchiveLinksTask; + + parented_ptr m_pCoverArtArchiveImageTask; + TrackPointer m_pTrack; }; diff --git a/src/musicbrainz/web/coverartarchiveimagetask.cpp b/src/musicbrainz/web/coverartarchiveimagetask.cpp new file mode 100644 index 00000000000..5817e2faff3 --- /dev/null +++ b/src/musicbrainz/web/coverartarchiveimagetask.cpp @@ -0,0 +1,72 @@ +#include "musicbrainz/web/coverartarchiveimagetask.h" + +#include + +#include "defs_urls.h" +#include "network/httpstatuscode.h" +#include "util/assert.h" +#include "util/logger.h" +#include "util/thread_affinity.h" +#include "util/versionstore.h" + +namespace mixxx { + +namespace { + +const Logger kLogger("CoverArtArchiveImageTask"); + +QNetworkRequest createNetworkRequest(const QString& coverArtUrl) { + QUrl url = coverArtUrl; + DEBUG_ASSERT(url.isValid()); + QNetworkRequest networkRequest(url); + return networkRequest; +} + +} // anonymous namespace + +CoverArtArchiveImageTask::CoverArtArchiveImageTask( + QNetworkAccessManager* networkAccessManager, + const QString& coverArtLink, + QObject* parent) + : network::WebTask( + networkAccessManager, + parent), + m_coverArtUrl(coverArtLink) { +} + +QNetworkReply* CoverArtArchiveImageTask::doStartNetworkRequest( + QNetworkAccessManager* networkAccessManager, + int parentTimeoutMillis) { + networkAccessManager->setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy); + DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); + DEBUG_ASSERT(networkAccessManager); + + const QNetworkRequest networkRequest = + createNetworkRequest(m_coverArtUrl); + + if (kLogger.traceEnabled()) { + kLogger.trace() + << "GET" + << networkRequest.url(); + } + return networkAccessManager->get(networkRequest); +} + +void CoverArtArchiveImageTask::doNetworkReplyFinished( + QNetworkReply* finishedNetworkReply, + network::HttpStatusCode statusCode) { + DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); + + const QByteArray resultImageBytes = finishedNetworkReply->readAll(); + + if (statusCode != 200) { + kLogger.info() + << "GET reply" + << "statusCode:" << statusCode; + return; + } + + emit succeeded(resultImageBytes); +} + +} // namespace mixxx diff --git a/src/musicbrainz/web/coverartarchiveimagetask.h b/src/musicbrainz/web/coverartarchiveimagetask.h new file mode 100644 index 00000000000..eda0aacba53 --- /dev/null +++ b/src/musicbrainz/web/coverartarchiveimagetask.h @@ -0,0 +1,40 @@ +#pragma once + +#include "network/webtask.h" + +namespace mixxx { + +class CoverArtArchiveImageTask : public network::WebTask { + Q_OBJECT + + public: + CoverArtArchiveImageTask( + QNetworkAccessManager* networkAccessManager, + const QString& coverArtLink, + QObject* parent = nullptr); + ~CoverArtArchiveImageTask() override = default; + + signals: + void succeeded( + const QByteArray& coverArtImageBytes); + + void failed( + const network::WebResponse& response, + int errorCode, + const QString& errorMessage); + + private: + QNetworkReply* doStartNetworkRequest( + QNetworkAccessManager* networkAccessManager, + int parentTimeoutMillis) override; + + void doNetworkReplyFinished( + QNetworkReply* finishedNetworkReply, + network::HttpStatusCode statusCode) override; + + QString m_coverArtUrl; + + QByteArray coverArtImageBytes; +}; + +} // namespace mixxx diff --git a/src/musicbrainz/web/coverartarchivelinkstask.cpp b/src/musicbrainz/web/coverartarchivelinkstask.cpp new file mode 100644 index 00000000000..44d451ed93b --- /dev/null +++ b/src/musicbrainz/web/coverartarchivelinkstask.cpp @@ -0,0 +1,158 @@ +#include "musicbrainz/web/coverartarchivelinkstask.h" + +#include +#include +#include +#include + +#include "network/httpstatuscode.h" +#include "util/assert.h" +#include "util/logger.h" + +namespace mixxx { + +namespace { + +const Logger kLogger("CoverArtArchiveLinksTask"); + +const QUrl kBaseUrl = QStringLiteral("https://coverartarchive.org/"); + +const QString kRequestPath = QStringLiteral("/release/"); + +network::JsonWebRequest lookupRequest() { + return network::JsonWebRequest{ + network::HttpRequestMethod::Get, + kRequestPath, + QUrlQuery(), + QJsonDocument()}; +} + +QNetworkRequest createNetworkRequest( + const QUuid& releaseID) { + DEBUG_ASSERT(kBaseUrl.isValid()); + DEBUG_ASSERT(!releaseID.isNull()); + QUrl url = kBaseUrl; + url.setPath(kRequestPath + releaseID.toString(QUuid::WithoutBraces)); + DEBUG_ASSERT(url.isValid()); + QNetworkRequest networkRequest(url); + return networkRequest; +} + +} // anonymous namespace + +CoverArtArchiveLinksTask::CoverArtArchiveLinksTask( + QNetworkAccessManager* networkAccessManager, + const QUuid& albumReleaseId, + QObject* parent) + : network::JsonWebTask( + networkAccessManager, + kBaseUrl, + lookupRequest(), + parent), + m_albumReleaseId(albumReleaseId) { +} + +QNetworkReply* CoverArtArchiveLinksTask::sendNetworkRequest( + QNetworkAccessManager* networkAccessManager, + network::HttpRequestMethod method, + const QUrl& url, + const QJsonDocument& content) { + DEBUG_ASSERT(networkAccessManager); + //DEBUG_ASSERT(!m_queuedAlbumReleaseIds.first().isNull()); + Q_UNUSED(method); + DEBUG_ASSERT(method == network::HttpRequestMethod::Get); + networkAccessManager->setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy); + + const QNetworkRequest networkRequest = createNetworkRequest(m_albumReleaseId); + + VERIFY_OR_DEBUG_ASSERT(url.isValid()) { + kLogger.warning() << "Invalid URL" << url; + return nullptr; + } + if (kLogger.traceEnabled()) { + kLogger.trace() + << "Get" + << url; + } + return networkAccessManager->get(networkRequest); +} + +void CoverArtArchiveLinksTask::onFinished( + const network::JsonWebResponse& response) { + if (!response.isStatusCodeSuccess()) { + kLogger.warning() + << "Request failed with HTTP status code" + << response.statusCode(); + emitFailed(response); + return; + } + VERIFY_OR_DEBUG_ASSERT(response.statusCode() == network::kHttpStatusCodeOk) { + kLogger.warning() + << "Unexpected HTTP status code" + << response.statusCode(); + emitFailed(response); + return; + } + VERIFY_OR_DEBUG_ASSERT(response.content().isObject()) { + kLogger.warning() + << "Invalid JSON content" + << response.content(); + emitFailed(response); + return; + } + const auto jsonObject = response.content().object(); + + if (jsonObject.isEmpty()) { + kLogger.warning() + << "Empty Json"; + emitFailed(response); + return; + } + + QList allUrls; + DEBUG_ASSERT(jsonObject.value(QLatin1String("images")).isArray()); + const QJsonArray images = jsonObject.value(QLatin1String("images")).toArray(); + for (const auto& image : images) { + DEBUG_ASSERT(image.isObject()); + const auto imageObject = image.toObject(); + + const auto thumbnails = imageObject.value(QLatin1String("thumbnails")).toObject(); + DEBUG_ASSERT(!thumbnails.isEmpty()); + + const auto smallThumbnailUrl = thumbnails.value(QLatin1String("small")).toString(); + DEBUG_ASSERT(!smallThumbnailUrl.isNull()); + allUrls.append(smallThumbnailUrl); + + const auto largeThumbnailUrl = thumbnails.value(QLatin1String("large")).toString(); + DEBUG_ASSERT(!largeThumbnailUrl.isNull()); + allUrls.append(largeThumbnailUrl); + + if (thumbnails.value(QLatin1String("1200")).toString() != nullptr) { + const auto largestThumbnailUrl = thumbnails.value(QLatin1String("1200")).toString(); + allUrls.append(largestThumbnailUrl); + } + + if (!(imageObject.value(QLatin1String("image")).isNull())) { + const auto highestResolutionImageUrl = + imageObject.value(QLatin1String("image")).toString(); + allUrls.append(highestResolutionImageUrl); + } + + break; + } + emitSucceeded(allUrls); +} + +void CoverArtArchiveLinksTask::emitSucceeded( + const QList& allUrls) { + VERIFY_OR_DEBUG_ASSERT( + isSignalFuncConnected(&CoverArtArchiveLinksTask::succeeded)) { + kLogger.warning() + << "Unhandled succeeded signal"; + deleteLater(); + return; + } + emit succeeded(allUrls); +} + +} // namespace mixxx diff --git a/src/musicbrainz/web/coverartarchivelinkstask.h b/src/musicbrainz/web/coverartarchivelinkstask.h new file mode 100644 index 00000000000..09feae0332f --- /dev/null +++ b/src/musicbrainz/web/coverartarchivelinkstask.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include +#include +#include + +#include "network/jsonwebtask.h" + +namespace mixxx { + +class CoverArtArchiveLinksTask : public network::JsonWebTask { + Q_OBJECT + + public: + CoverArtArchiveLinksTask( + QNetworkAccessManager* networkAccessManager, + const QUuid& albumReleaseId, + QObject* parent = nullptr); + + ~CoverArtArchiveLinksTask() override = default; + + signals: + void succeeded( + const QList& allUrls); + + private: + QNetworkReply* sendNetworkRequest( + QNetworkAccessManager* networkAccessManager, + network::HttpRequestMethod method, + const QUrl& url, + const QJsonDocument& content) override; + + void onFinished( + const network::JsonWebResponse& response) override; + + void emitSucceeded(const QList& allUrls); + + QUuid m_albumReleaseId; + + QList m_allThumbnailUrls; +}; + +} // namespace mixxx diff --git a/src/preferences/dialog/dlgpreflibrary.cpp b/src/preferences/dialog/dlgpreflibrary.cpp index ee0802c7937..b9b8b27d242 100644 --- a/src/preferences/dialog/dlgpreflibrary.cpp +++ b/src/preferences/dialog/dlgpreflibrary.cpp @@ -206,6 +206,10 @@ void DlgPrefLibrary::slotResetToDefaults() { radioButton_dbclick_bottom->setChecked(false); radioButton_dbclick_top->setChecked(false); radioButton_dbclick_deck->setChecked(true); + radioButton_cover_art_fetcher_highest->setChecked(false); + radioButton_cover_art_fetcher_high->setChecked(false); + radioButton_cover_art_fetcher_medium->setChecked(false); + radioButton_cover_art_fetcher_lowest->setChecked(true); spinBoxRowHeight->setValue(Library::kDefaultRowHeightPx); setLibraryFont(QApplication::font()); searchDebouncingTimeoutSpinBox->setValue( @@ -261,6 +265,23 @@ void DlgPrefLibrary::slotUpdate() { break; } + switch (m_pConfig->getValue( + kCoverArtFetcherQualityConfigKey, + static_cast(CoverArtFetcherQuality::Low))) { + case static_cast(CoverArtFetcherQuality::Highest): + radioButton_cover_art_fetcher_highest->setChecked(true); + break; + case static_cast(CoverArtFetcherQuality::High): + radioButton_cover_art_fetcher_high->setChecked(true); + break; + case static_cast(CoverArtFetcherQuality::Medium): + radioButton_cover_art_fetcher_medium->setChecked(true); + break; + default: + radioButton_cover_art_fetcher_lowest->setChecked(true); + break; + } + bool editMetadataSelectedClick = m_pConfig->getValue( kEditMetadataSelectedClickConfigKey, kEditMetadataSelectedClickDefault); @@ -426,6 +447,18 @@ void DlgPrefLibrary::slotApply() { m_pConfig->set(ConfigKey("[Library]", "ShowSeratoLibrary"), ConfigValue((int)checkBox_show_serato->isChecked())); + int coverartfetcherquality_status; + if (radioButton_cover_art_fetcher_highest->isChecked()) { + coverartfetcherquality_status = static_cast(CoverArtFetcherQuality::Highest); + } else if (radioButton_cover_art_fetcher_high->isChecked()) { + coverartfetcherquality_status = static_cast(CoverArtFetcherQuality::High); + } else if (radioButton_cover_art_fetcher_medium->isChecked()) { + coverartfetcherquality_status = static_cast(CoverArtFetcherQuality::Medium); + } else { + coverartfetcherquality_status = static_cast(CoverArtFetcherQuality::Low); + } + m_pConfig->set(kCoverArtFetcherQualityConfigKey, ConfigValue(coverartfetcherquality_status)); + int dbclick_status; if (radioButton_dbclick_bottom->isChecked()) { dbclick_status = static_cast(TrackDoubleClickAction::AddToAutoDJBottom); diff --git a/src/preferences/dialog/dlgpreflibrary.h b/src/preferences/dialog/dlgpreflibrary.h index 6a2f12310a4..1c930c10459 100644 --- a/src/preferences/dialog/dlgpreflibrary.h +++ b/src/preferences/dialog/dlgpreflibrary.h @@ -20,6 +20,13 @@ class DlgPrefLibrary : public DlgPreferencePage, public Ui::DlgPrefLibraryDlg { Ignore = 3, }; + enum class CoverArtFetcherQuality : int { + Low = 0, + Medium = 1, + High = 2, + Highest = 3, + }; + DlgPrefLibrary( QWidget* pParent, UserSettingsPointer pConfig, diff --git a/src/preferences/dialog/dlgpreflibrarydlg.ui b/src/preferences/dialog/dlgpreflibrarydlg.ui index c20e4e0c24c..c2ae8a5b900 100644 --- a/src/preferences/dialog/dlgpreflibrarydlg.ui +++ b/src/preferences/dialog/dlgpreflibrarydlg.ui @@ -442,7 +442,7 @@ - + You will need to restart Mixxx for these settings to take effect. @@ -452,6 +452,66 @@ + + + + Cover Art Fetcher + + + + + + Highest + + + + + + + + + High + + + + + + + + + Medium + + + + + + + + + Low + + + + + + + + + Fetch cover art from coverartarchive.com by using Import Metadata From Musicbrainz. + + + + + + + Highest resolution can fetch up to very large cover arts. + + + + + + + @@ -546,6 +606,10 @@ checkBox_show_traktor checkBox_show_rekordbox checkBox_show_serato + radioButton_cover_art_fetcher_highest + radioButton_cover_art_fetcher_high + radioButton_cover_art_fetcher_medium + radioButton_cover_art_fetcher_lowest PushButtonOpenSettingsDir diff --git a/src/widget/wcoverartlabel.cpp b/src/widget/wcoverartlabel.cpp index a38640e0149..8e60f281a14 100644 --- a/src/widget/wcoverartlabel.cpp +++ b/src/widget/wcoverartlabel.cpp @@ -84,6 +84,10 @@ void WCoverArtLabel::loadTrack(TrackPointer pTrack) { m_pLoadedTrack = pTrack; } +void WCoverArtLabel::loadData(const QByteArray& data) { + m_Data = data; +} + void WCoverArtLabel::mousePressEvent(QMouseEvent* event) { if (m_pCoverMenu != nullptr && m_pCoverMenu->isVisible()) { return; @@ -92,8 +96,14 @@ void WCoverArtLabel::mousePressEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) { if (m_pDlgFullSize->isVisible()) { m_pDlgFullSize->close(); - } else if (!m_loadedCover.isNull()) { - m_pDlgFullSize->init(m_pLoadedTrack); + } else { + if (m_loadedCover.isNull()) { + return; + } else if (!m_pLoadedTrack && !m_Data.isNull()) { + m_pDlgFullSize->init(m_Data); + } else { + m_pDlgFullSize->init(m_pLoadedTrack); + } } } } diff --git a/src/widget/wcoverartlabel.h b/src/widget/wcoverartlabel.h index e0ffc94553f..58937c152e4 100644 --- a/src/widget/wcoverartlabel.h +++ b/src/widget/wcoverartlabel.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -22,6 +23,7 @@ class WCoverArtLabel : public QLabel { void setCoverArt(const CoverInfo& coverInfo, const QPixmap& px); void loadTrack(TrackPointer pTrack); + void loadData(const QByteArray& data); protected: void mousePressEvent(QMouseEvent* event) override; @@ -37,6 +39,8 @@ class WCoverArtLabel : public QLabel { const QPixmap m_defaultCover; + QByteArray m_Data; + TrackPointer m_pLoadedTrack; QPixmap m_loadedCover; diff --git a/src/widget/wtrackmenu.cpp b/src/widget/wtrackmenu.cpp index a190b1035e0..b192644f9e9 100644 --- a/src/widget/wtrackmenu.cpp +++ b/src/widget/wtrackmenu.cpp @@ -2117,7 +2117,7 @@ void WTrackMenu::slotShowDlgTagFetcher() { } // Create a fresh dialog on invocation m_pDlgTagFetcher = std::make_unique( - m_pTrackModel); + m_pConfig, m_pTrackModel); connect(m_pDlgTagFetcher.get(), &QDialog::finished, this, From 200f37ec4b532314e84e8f6f97b11038440bb485 Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Sun, 16 Oct 2022 09:52:25 +0300 Subject: [PATCH 02/24] dlgtagfetcher.ui: fix wrong display. --- src/library/dlgtagfetcher.ui | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/library/dlgtagfetcher.ui b/src/library/dlgtagfetcher.ui index 1cd7588af08..6cb87d6b402 100644 --- a/src/library/dlgtagfetcher.ui +++ b/src/library/dlgtagfetcher.ui @@ -135,7 +135,7 @@ - + QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed @@ -184,7 +184,7 @@ - + From bb7ec6df7ccfcf14a1e0d313a839770921c7b81d Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Sun, 16 Oct 2022 10:03:52 +0300 Subject: [PATCH 03/24] dlgtagfetcher: comment add to fetching user choice --- src/library/dlgtagfetcher.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/library/dlgtagfetcher.cpp b/src/library/dlgtagfetcher.cpp index 8decb2e9f9a..c3197368f03 100644 --- a/src/library/dlgtagfetcher.cpp +++ b/src/library/dlgtagfetcher.cpp @@ -544,19 +544,28 @@ void DlgTagFetcher::slotStartFetchCoverArt(const QList& allUrls) { static_cast( fetchedCoverArtQualityConfigValue); - // Maximum size of the allUrls are 4. + // Cover art links task can retrieve us variable number of links with different cover art sizes + // Every single successful response has 2 links. + // These links are cover arts with 250 PX and 500 PX + // Some of the tags might have link of a cover art with 1200 PX + // Some of the tags might have link of a cover art more than 1200 PX + // At final, we always retrieve 2 links, but for some tags this can be 3 or 4 + // We need to pick the correct size according to user choice + + // User choices and the possible fetched cover art sizes are: + // Highest -> More than 1200 PX, if not available 1200 PX or 500 PX + // High -> 1200 PX if not available 500 PX + // Medium -> Always 500 PX fetched + // Low -> Always 250 PX fetched + if (fetcherQuality == DlgPrefLibrary::CoverArtFetcherQuality::Highest) { getCoverArt(allUrls.last()); - qDebug() << allUrls.last(); return; } else if (fetcherQuality == DlgPrefLibrary::CoverArtFetcherQuality::High) { - qDebug() << allUrls.size(); - qDebug() << allUrls; - allUrls.size() < 3 ? getCoverArt(allUrls.at(1)) : getCoverArt(allUrls.at(2)); + allUrls.size() < 3 ? getCoverArt(allUrls.last()) : getCoverArt(allUrls.at(2)); return; } else if (fetcherQuality == DlgPrefLibrary::CoverArtFetcherQuality::Medium) { getCoverArt(allUrls.at(1)); - qDebug() << allUrls.at(1); return; } else { getCoverArt(allUrls.first()); From 6885b359b94128bfe09b317156f6e8e0dcde4c6c Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Sun, 16 Oct 2022 10:05:30 +0300 Subject: [PATCH 04/24] imagefiledata: improve format not matching warning --- src/util/imagefiledata.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/util/imagefiledata.cpp b/src/util/imagefiledata.cpp index 9f6c9d1b6f9..648cc52c985 100644 --- a/src/util/imagefiledata.cpp +++ b/src/util/imagefiledata.cpp @@ -50,10 +50,10 @@ bool ImageFileData::saveFile(const QString& coverArtAbsoluteFilePath) const { } if (QFileInfo(coverArtAbsoluteFilePath).suffix() != m_coverArtFormat) { - qWarning() << "Cover Art format and extension does not match" - << "format" + qWarning() << "Cover Art format and extension does not match!" + << "Cover art format:" << m_coverArtFormat - << "extension" + << "File extension:" << QFileInfo(coverArtAbsoluteFilePath).suffix(); return save(coverArtAbsoluteFilePath); } From 50318f10113054fb0baffa2c8e6446b6474e2d4e Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Sun, 16 Oct 2022 10:21:18 +0300 Subject: [PATCH 05/24] dlgtagfetcher: polished & deleted redundants. --- src/library/dlgtagfetcher.cpp | 19 +++++++++---------- src/library/dlgtagfetcher.h | 5 +---- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/library/dlgtagfetcher.cpp b/src/library/dlgtagfetcher.cpp index c3197368f03..a0b01a5c967 100644 --- a/src/library/dlgtagfetcher.cpp +++ b/src/library/dlgtagfetcher.cpp @@ -107,7 +107,6 @@ DlgTagFetcher::DlgTagFetcher(UserSettingsPointer pConfig, const TrackModel* pTra m_pConfig(pConfig), m_pTrackModel(pTrackModel), m_tagFetcher(this), - m_pWCoverArtMenu(make_parented(this)), m_pWCurrentCoverArtLabel(make_parented(this)), m_pWFetchedCoverArtLabel(make_parented(this)) { init(); @@ -245,6 +244,7 @@ void DlgTagFetcher::loadTrack(const TrackPointer& pTrack) { this, &DlgTagFetcher::slotTrackChanged); + loadCurrentTrackCover(); m_tagFetcher.startFetch(m_track); } @@ -255,10 +255,6 @@ void DlgTagFetcher::loadTrack(const QModelIndex& index) { } void DlgTagFetcher::slotTrackChanged(TrackId trackId) { - if (!m_fetchedCoverArtByteArrays.isNull()) { - m_fetchedCoverArtByteArrays.clear(); - } - if (m_track && m_track->getId() == trackId) { updateOriginalTag(*m_track, tags); } @@ -448,6 +444,9 @@ void DlgTagFetcher::fetchTagFinished( } } + QString fetchTagFinishedMessage = tr("The results are ready to be applied"); + statusMessage->setText(fetchTagFinishedMessage); + // qDebug() << "number of tags = " << guessedTrackReleases.size(); } @@ -494,9 +493,9 @@ void DlgTagFetcher::tagSelected() { if (!m_fetchedCoverArtByteArrays.isNull()) { m_fetchedCoverArtByteArrays.clear(); - CoverInfo coverInfo; - QPixmap pixmap; - m_pWFetchedCoverArtLabel->setCoverArt(coverInfo, pixmap); + m_pWFetchedCoverArtLabel->loadData(m_fetchedCoverArtByteArrays); + m_pWFetchedCoverArtLabel->setCoverArt(CoverInfo{}, + QPixmap(CoverArtUtils::defaultCoverLocation())); } const mixxx::musicbrainz::TrackRelease& trackRelease = m_data.m_tags[tagIndex]; @@ -582,7 +581,7 @@ void DlgTagFetcher::slotLoadBytesToLabel(const QByteArray& data) { coverInfo.setImage(); loadingProgressBar->setVisible(false); - QString coverArtMessage = tr("Cover art found and it is ready to be applied."); + QString coverArtMessage = tr("Cover art is ready to be applied"); statusMessage->setVisible(true); statusMessage->setText(coverArtMessage); @@ -603,6 +602,6 @@ void DlgTagFetcher::getCoverArt(const QString& url) { void DlgTagFetcher::slotCoverArtLinkNotFound() { loadingProgressBar->setVisible(false); statusMessage->setVisible(true); - QString message = tr("Cover Art not available for that tag. Please try another."); + QString message = tr("Cover Art is not available for selected tag"); statusMessage->setText(message); } diff --git a/src/library/dlgtagfetcher.h b/src/library/dlgtagfetcher.h index 345879d9356..a09328c93d3 100644 --- a/src/library/dlgtagfetcher.h +++ b/src/library/dlgtagfetcher.h @@ -66,10 +66,10 @@ class DlgTagFetcher : public QDialog, public Ui::DlgTagFetcher { private: // Called on population or changed via buttons Next&Prev. - void loadCurrentTrackCover(); void loadTrackInternal(const TrackPointer& track); void addDivider(const QString& text, QTreeWidget* parent) const; void getCoverArt(const QString& url); + void loadCurrentTrackCover(); UserSettingsPointer m_pConfig; @@ -83,14 +83,11 @@ class DlgTagFetcher : public QDialog, public Ui::DlgTagFetcher { int m_percentForOneRecording; - parented_ptr m_pWCoverArtMenu; parented_ptr m_pWCurrentCoverArtLabel; parented_ptr m_pWFetchedCoverArtLabel; mixxx::TrackRecord m_trackRecord; - int m_progressBarStep; - struct Data { Data() : m_selectedTag(-1) { From 8a0dc28672a5b0748e4982024a1274a87a5c3a51 Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Sun, 16 Oct 2022 10:25:27 +0300 Subject: [PATCH 06/24] dlgtagfetcher: CA constants added for progressbar --- src/library/dlgtagfetcher.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/library/dlgtagfetcher.cpp b/src/library/dlgtagfetcher.cpp index a0b01a5c967..5eda698ecb4 100644 --- a/src/library/dlgtagfetcher.cpp +++ b/src/library/dlgtagfetcher.cpp @@ -37,6 +37,20 @@ constexpr int kMaximumValueOfQProgressBar = 100; constexpr int kMinimumValueOfQProgressBar = 0; +// There are 2 following steps for cover art fetching. +// 1. -> "Cover Art Links Task" +// 2. -> "Cover Art Image Task" +// When a tag is selected, first step starts. +// First step looks for available cover art links for selected tag. +// Some tags might not have any available cover arts. +// If no links found, user is informed and cover art fetching is finished. +// If links are found, second step starts instantly. +// Second step gets actual cover art with according to user's chosen size. + +constexpr int kPercentForCoverArtLinksTask = 35; + +constexpr int kPercentForCoverArtImageTask = 70; + // Original Index of the track tag, listed all the time below 'Original Tags'. constexpr int kOriginalTrackIndex = -1; @@ -505,9 +519,7 @@ void DlgTagFetcher::tagSelected() { QString coverArtMessage = tr("Looking for cover art"); loadingProgressBar->setVisible(true); loadingProgressBar->setFormat(coverArtMessage); - loadingProgressBar->setMinimum(0); - loadingProgressBar->setMaximum(100); - loadingProgressBar->setValue(10); + loadingProgressBar->setValue(kPercentForCoverArtLinksTask); m_tagFetcher.startFetchCoverArtLinks(selectedTagAlbumId); } @@ -572,7 +584,6 @@ void DlgTagFetcher::slotStartFetchCoverArt(const QList& allUrls) { } void DlgTagFetcher::slotLoadBytesToLabel(const QByteArray& data) { - loadingProgressBar->setValue(80); QPixmap fetchedCoverArtPixmap; fetchedCoverArtPixmap.loadFromData(data); CoverInfo coverInfo; @@ -594,8 +605,7 @@ void DlgTagFetcher::slotLoadBytesToLabel(const QByteArray& data) { void DlgTagFetcher::getCoverArt(const QString& url) { QString coverArtMessage = tr("Cover art found getting image"); loadingProgressBar->setFormat(coverArtMessage); - loadingProgressBar->setValue(40); - + loadingProgressBar->setValue(kPercentForCoverArtImageTask); m_tagFetcher.startFetchCoverArtImage(url); } From b1379dbd7889ab2fe979377db370b44273444469 Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Sun, 16 Oct 2022 10:33:23 +0300 Subject: [PATCH 07/24] cacworker: worker refactored for cover art fetcher --- src/library/export/coverartcopyworker.cpp | 17 ++++++++++++++--- src/library/export/coverartcopyworker.h | 7 +++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/library/export/coverartcopyworker.cpp b/src/library/export/coverartcopyworker.cpp index 037be65b27e..47071303e5d 100644 --- a/src/library/export/coverartcopyworker.cpp +++ b/src/library/export/coverartcopyworker.cpp @@ -13,6 +13,17 @@ CoverArtCopyWorker::~CoverArtCopyWorker() { } void CoverArtCopyWorker::run() { + m_coverInfo.type = CoverInfo::FILE; + m_coverInfo.source = CoverInfo::USER_SELECTED; + + if (m_selectedCoverArtFilePath.isEmpty()) { + ImageFileData imageFileData = ImageFileData(m_fetchedCoverArtByteArray); + m_coverInfo.coverLocation = m_oldCoverArtFilePath; + m_coverInfo.setImage(imageFileData); + copyFile(QString(), m_oldCoverArtFilePath); + return; + } + // Create a security token for the file. auto selectedCoverFileAccess = mixxx::FileAccess(mixxx::FileInfo(m_selectedCoverArtFilePath)); @@ -22,8 +33,6 @@ void CoverArtCopyWorker::run() { return; } - m_coverInfo.type = CoverInfo::FILE; - m_coverInfo.source = CoverInfo::USER_SELECTED; m_coverInfo.coverLocation = m_selectedCoverArtFilePath; m_coverInfo.setImage(imageFileData); @@ -43,7 +52,9 @@ void CoverArtCopyWorker::copyFile( const QString& m_selectedCoverArtFilePath, const QString& m_oldCoverArtFilePath) { QFileInfo coverArtPathFileInfo(m_oldCoverArtFilePath); - ImageFileData imageFileData = ImageFileData::fromFilePath(m_selectedCoverArtFilePath); + ImageFileData imageFileData = m_selectedCoverArtFilePath.isEmpty() + ? ImageFileData(m_fetchedCoverArtByteArray) + : ImageFileData::fromFilePath(m_selectedCoverArtFilePath); QString errorMessage = tr("Error while copying the cover art to: %1") .arg(m_oldCoverArtFilePath); if (coverArtPathFileInfo.exists()) { diff --git a/src/library/export/coverartcopyworker.h b/src/library/export/coverartcopyworker.h index 1f6d7728d1c..f5f1ec93a1c 100644 --- a/src/library/export/coverartcopyworker.h +++ b/src/library/export/coverartcopyworker.h @@ -22,9 +22,11 @@ class CoverArtCopyWorker : public QThread { }; CoverArtCopyWorker(const QString& selectedCoverArtFilePath, - const QString& oldCoverArtFilePath) + const QString& oldCoverArtFilePath, + const QByteArray& fetchedCoverArtByteArray = nullptr) : m_selectedCoverArtFilePath(selectedCoverArtFilePath), - m_oldCoverArtFilePath(oldCoverArtFilePath) { + m_oldCoverArtFilePath(oldCoverArtFilePath), + m_fetchedCoverArtByteArray(fetchedCoverArtByteArray) { qRegisterMetaType("CoverInfoRelative"); } @@ -48,4 +50,5 @@ class CoverArtCopyWorker : public QThread { CoverInfoRelative m_coverInfo; const QString m_selectedCoverArtFilePath; const QString m_oldCoverArtFilePath; + const QByteArray m_fetchedCoverArtByteArray; }; From b4bb70e212705d869d9d1d1d53d01dfcc7176a47 Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Sun, 16 Oct 2022 10:34:20 +0300 Subject: [PATCH 08/24] dlgtagfetcher: cacopyworker implemented. --- src/library/dlgtagfetcher.cpp | 117 ++++++++++++++++++++++++++-------- src/library/dlgtagfetcher.h | 10 +++ 2 files changed, 102 insertions(+), 25 deletions(-) diff --git a/src/library/dlgtagfetcher.cpp b/src/library/dlgtagfetcher.cpp index 5eda698ecb4..bfbdf297655 100644 --- a/src/library/dlgtagfetcher.cpp +++ b/src/library/dlgtagfetcher.cpp @@ -121,6 +121,7 @@ DlgTagFetcher::DlgTagFetcher(UserSettingsPointer pConfig, const TrackModel* pTra m_pConfig(pConfig), m_pTrackModel(pTrackModel), m_tagFetcher(this), + m_isCoverArtCopyWorkerRunning(false), m_pWCurrentCoverArtLabel(make_parented(this)), m_pWFetchedCoverArtLabel(make_parented(this)) { init(); @@ -339,33 +340,51 @@ void DlgTagFetcher::apply() { #endif // __EXTRA_METADATA__ if (!m_fetchedCoverArtByteArrays.isNull()) { - // Worker can be called here. - QString coverArtLocation = m_track->getLocation() + ".jpg"; - QFile coverArtFile(coverArtLocation); - coverArtFile.open(QIODevice::WriteOnly); - coverArtFile.write(m_fetchedCoverArtByteArrays); - coverArtFile.close(); - - auto selectedCover = mixxx::FileAccess(mixxx::FileInfo(coverArtLocation)); - QImage updatedCoverArtFound(coverArtLocation); - if (!updatedCoverArtFound.isNull()) { - CoverInfoRelative coverInfo; - coverInfo.type = CoverInfo::FILE; - coverInfo.source = CoverInfo::USER_SELECTED; - coverInfo.coverLocation = coverArtLocation; - coverInfo.setImage(updatedCoverArtFound); - m_pWCurrentCoverArtLabel->setCoverArt( - CoverInfo{}, QPixmap::fromImage(updatedCoverArtFound)); - m_track->setCoverInfo(coverInfo); - m_fetchedCoverArtByteArrays.clear(); - m_pWFetchedCoverArtLabel->loadData(m_fetchedCoverArtByteArrays); - m_pWFetchedCoverArtLabel->setCoverArt(CoverInfo{}, - QPixmap(CoverArtUtils::defaultCoverLocation())); - QString coverArtAppliedMessage = tr("Cover art applied."); - statusMessage->setText(coverArtAppliedMessage); - } + VERIFY_OR_DEBUG_ASSERT(m_isCoverArtCopyWorkerRunning == false) { + return; + }; + + QFileInfo trackFileInfo = QFileInfo(m_track->getLocation()); + + QString coverArtCopyFilePath = + trackFileInfo.absoluteFilePath().left( + trackFileInfo.absoluteFilePath().lastIndexOf('.') + 1) + + "jpeg"; + + m_worker.reset(new CoverArtCopyWorker( + QString(), coverArtCopyFilePath, m_fetchedCoverArtByteArrays)); + + connect(m_worker.data(), + &CoverArtCopyWorker::started, + this, + &DlgTagFetcher::slotWorkerStarted); + + connect(m_worker.data(), + &CoverArtCopyWorker::askOverwrite, + this, + &DlgTagFetcher::slotWorkerAskOverwrite); + + connect(m_worker.data(), + &CoverArtCopyWorker::coverArtCopyFailed, + this, + &DlgTagFetcher::slotWorkerCoverArtCopyFailed); + + connect(m_worker.data(), + &CoverArtCopyWorker::coverArtUpdated, + this, + &DlgTagFetcher::slotWorkerCoverArtUpdated); + + connect(m_worker.data(), + &CoverArtCopyWorker::finished, + this, + &DlgTagFetcher::slotWorkerFinished); + + m_worker->start(); } + QString coverArtAppliedMessage = tr("Selected metadata applied"); + statusMessage->setText(coverArtAppliedMessage); + m_track->replaceMetadataFromSource( std::move(trackMetadata), // Prevent re-import of outdated metadata from file tags @@ -615,3 +634,51 @@ void DlgTagFetcher::slotCoverArtLinkNotFound() { QString message = tr("Cover Art is not available for selected tag"); statusMessage->setText(message); } + +void DlgTagFetcher::slotWorkerStarted() { + m_isCoverArtCopyWorkerRunning = true; +} + +void DlgTagFetcher::slotWorkerCoverArtUpdated(const CoverInfoRelative& coverInfo) { + qDebug() << "DlgTagFetcher::slotWorkerCoverArtUpdated" << coverInfo; + m_track->setCoverInfo(coverInfo); + loadCurrentTrackCover(); + QString coverArtAppliedMessage = tr("Metadata & Cover Art applied"); + statusMessage->setText(coverArtAppliedMessage); +} + +void DlgTagFetcher::slotWorkerAskOverwrite(const QString& coverArtAbsolutePath, + std::promise* promise) { + QFileInfo coverArtInfo(coverArtAbsolutePath); + QString coverArtName = coverArtInfo.completeBaseName(); + QString coverArtFolder = coverArtInfo.absolutePath(); + QMessageBox overwrite_box( + QMessageBox::Warning, + tr("Cover Art File Already Exists"), + tr("File: %1\n" + "Folder: %2\n" + "Override existing file?\n" + "This can not be undone!") + .arg(coverArtName, coverArtFolder)); + overwrite_box.addButton(QMessageBox::Yes); + overwrite_box.addButton(QMessageBox::No); + + switch (overwrite_box.exec()) { + case QMessageBox::No: + promise->set_value(CoverArtCopyWorker::OverwriteAnswer::Cancel); + return; + case QMessageBox::Yes: + promise->set_value(CoverArtCopyWorker::OverwriteAnswer::Overwrite); + return; + } +} + +void DlgTagFetcher::slotWorkerCoverArtCopyFailed(const QString& errorMessage) { + QMessageBox copyFailBox; + copyFailBox.setText(errorMessage); + copyFailBox.exec(); +} + +void DlgTagFetcher::slotWorkerFinished() { + m_isCoverArtCopyWorkerRunning = false; +} diff --git a/src/library/dlgtagfetcher.h b/src/library/dlgtagfetcher.h index a09328c93d3..7e50249ffc0 100644 --- a/src/library/dlgtagfetcher.h +++ b/src/library/dlgtagfetcher.h @@ -63,6 +63,12 @@ class DlgTagFetcher : public QDialog, public Ui::DlgTagFetcher { void slotStartFetchCoverArt(const QList& allUrls); void slotLoadBytesToLabel(const QByteArray& data); void slotCoverArtLinkNotFound(); + void slotWorkerStarted(); + void slotWorkerAskOverwrite(const QString& coverArtAbsolutePath, + std::promise* promise); + void slotWorkerCoverArtCopyFailed(const QString& errorMessage); + void slotWorkerCoverArtUpdated(const CoverInfoRelative& coverInfo); + void slotWorkerFinished(); private: // Called on population or changed via buttons Next&Prev. @@ -77,6 +83,8 @@ class DlgTagFetcher : public QDialog, public Ui::DlgTagFetcher { TagFetcher m_tagFetcher; + bool m_isCoverArtCopyWorkerRunning; + TrackPointer m_track; QModelIndex m_currentTrackIndex; @@ -98,4 +106,6 @@ class DlgTagFetcher : public QDialog, public Ui::DlgTagFetcher { Data m_data; QByteArray m_fetchedCoverArtByteArrays; + + QScopedPointer m_worker; }; From 69ac2d603df31a4a78b2aca94157e894fb9aa35d Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Sun, 13 Nov 2022 14:10:14 +0300 Subject: [PATCH 09/24] dlgcoverartfullsize: special init renamed & tr add --- src/library/dlgcoverartfullsize.cpp | 4 ++-- src/library/dlgcoverartfullsize.h | 2 +- src/widget/wcoverartlabel.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/library/dlgcoverartfullsize.cpp b/src/library/dlgcoverartfullsize.cpp index 6fa9e847ae5..d7e9f88a20f 100644 --- a/src/library/dlgcoverartfullsize.cpp +++ b/src/library/dlgcoverartfullsize.cpp @@ -82,7 +82,7 @@ void DlgCoverArtFullSize::init(TrackPointer pTrack) { slotLoadTrack(pTrack); } -void DlgCoverArtFullSize::init(const QByteArray& fetchedCoverArtBytes) { +void DlgCoverArtFullSize::initFetchedCoverArt(const QByteArray& fetchedCoverArtBytes) { QPixmap image; image.loadFromData(fetchedCoverArtBytes); @@ -91,7 +91,7 @@ void DlgCoverArtFullSize::init(const QByteArray& fetchedCoverArtBytes) { raise(); activateWindow(); - QString fetchedCoverArtWindowTitle = "Fetched Cover Art"; + QString fetchedCoverArtWindowTitle = tr("Fetched Cover Art"); setWindowTitle(fetchedCoverArtWindowTitle); diff --git a/src/library/dlgcoverartfullsize.h b/src/library/dlgcoverartfullsize.h index 9c9444ffd95..e2d71215421 100644 --- a/src/library/dlgcoverartfullsize.h +++ b/src/library/dlgcoverartfullsize.h @@ -22,7 +22,7 @@ class DlgCoverArtFullSize ~DlgCoverArtFullSize() override = default; void init(TrackPointer pTrack); - void init(const QByteArray& fetchedCoverArtBytes); + void initFetchedCoverArt(const QByteArray& fetchedCoverArtBytes); void mousePressEvent(QMouseEvent* event) override; void mouseReleaseEvent(QMouseEvent* ) override; void mouseMoveEvent(QMouseEvent* ) override; diff --git a/src/widget/wcoverartlabel.cpp b/src/widget/wcoverartlabel.cpp index 8e60f281a14..c064d549479 100644 --- a/src/widget/wcoverartlabel.cpp +++ b/src/widget/wcoverartlabel.cpp @@ -100,7 +100,7 @@ void WCoverArtLabel::mousePressEvent(QMouseEvent* event) { if (m_loadedCover.isNull()) { return; } else if (!m_pLoadedTrack && !m_Data.isNull()) { - m_pDlgFullSize->init(m_Data); + m_pDlgFullSize->initFetchedCoverArt(m_Data); } else { m_pDlgFullSize->init(m_pLoadedTrack); } From ceb3978dfa0aa8ccb1f6c70136a39f195bd590d0 Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Sun, 13 Nov 2022 15:10:05 +0300 Subject: [PATCH 10/24] dlgtagfetcher: polishing & check add for urls --- src/library/dlgtagfetcher.cpp | 49 +++++++++---------------- src/library/dlgtagfetcher.h | 1 - src/preferences/dialog/dlgpreflibrary.h | 2 +- 3 files changed, 18 insertions(+), 34 deletions(-) diff --git a/src/library/dlgtagfetcher.cpp b/src/library/dlgtagfetcher.cpp index bfbdf297655..403c49bfab5 100644 --- a/src/library/dlgtagfetcher.cpp +++ b/src/library/dlgtagfetcher.cpp @@ -232,9 +232,7 @@ void DlgTagFetcher::loadTrack(const TrackPointer& pTrack) { } tags->clear(); - CoverInfo coverInfo; - QPixmap pixmap; - m_pWFetchedCoverArtLabel->setCoverArt(coverInfo, pixmap); + m_pWFetchedCoverArtLabel->setCoverArt(CoverInfo{}, QPixmap{}); disconnect(m_track.get(), &Track::changed, @@ -382,8 +380,7 @@ void DlgTagFetcher::apply() { m_worker->start(); } - QString coverArtAppliedMessage = tr("Selected metadata applied"); - statusMessage->setText(coverArtAppliedMessage); + statusMessage->setText(tr("Selected metadata applied")); m_track->replaceMetadataFromSource( std::move(trackMetadata), @@ -423,8 +420,7 @@ void DlgTagFetcher::loadCurrentTrackCover() { } void DlgTagFetcher::showProgressOfRecordingTask() { - QString status = tr("Fetching track data from the MusicBrainz database"); - loadingProgressBar->setFormat(status); + loadingProgressBar->setFormat(tr("Fetching track data from the MusicBrainz database")); loadingProgressBar->setValue(loadingProgressBar->value() + m_percentForOneRecording); } @@ -477,8 +473,7 @@ void DlgTagFetcher::fetchTagFinished( } } - QString fetchTagFinishedMessage = tr("The results are ready to be applied"); - statusMessage->setText(fetchTagFinishedMessage); + statusMessage->setText(tr("The results are ready to be applied")); // qDebug() << "number of tags = " << guessedTrackReleases.size(); } @@ -535,10 +530,9 @@ void DlgTagFetcher::tagSelected() { QUuid selectedTagAlbumId = trackRelease.albumReleaseId; statusMessage->setVisible(false); - QString coverArtMessage = tr("Looking for cover art"); - loadingProgressBar->setVisible(true); - loadingProgressBar->setFormat(coverArtMessage); + loadingProgressBar->setFormat(tr("Looking for cover art")); loadingProgressBar->setValue(kPercentForCoverArtLinksTask); + loadingProgressBar->setVisible(true); m_tagFetcher.startFetchCoverArtLinks(selectedTagAlbumId); } @@ -559,20 +553,11 @@ void DlgTagFetcher::slotCoverFound( } } -void DlgTagFetcher::slotUpdateStatusMessage(const QString& message) { - loadingProgressBar->setVisible(false); - statusMessage->setVisible(true); - statusMessage->setText(message); -} - void DlgTagFetcher::slotStartFetchCoverArt(const QList& allUrls) { - int fetchedCoverArtQualityConfigValue = - m_pConfig->getValue(mixxx::library::prefs::kCoverArtFetcherQualityConfigKey, - static_cast(DlgPrefLibrary::CoverArtFetcherQuality::Low)); - DlgPrefLibrary::CoverArtFetcherQuality fetcherQuality = static_cast( - fetchedCoverArtQualityConfigValue); + m_pConfig->getValue(mixxx::library::prefs::kCoverArtFetcherQualityConfigKey, + static_cast(DlgPrefLibrary::CoverArtFetcherQuality::Low))); // Cover art links task can retrieve us variable number of links with different cover art sizes // Every single successful response has 2 links. @@ -588,6 +573,10 @@ void DlgTagFetcher::slotStartFetchCoverArt(const QList& allUrls) { // Medium -> Always 500 PX fetched // Low -> Always 250 PX fetched + VERIFY_OR_DEBUG_ASSERT(!allUrls.isEmpty()) { + return; + } + if (fetcherQuality == DlgPrefLibrary::CoverArtFetcherQuality::Highest) { getCoverArt(allUrls.last()); return; @@ -595,7 +584,7 @@ void DlgTagFetcher::slotStartFetchCoverArt(const QList& allUrls) { allUrls.size() < 3 ? getCoverArt(allUrls.last()) : getCoverArt(allUrls.at(2)); return; } else if (fetcherQuality == DlgPrefLibrary::CoverArtFetcherQuality::Medium) { - getCoverArt(allUrls.at(1)); + allUrls.size() == 2 ? getCoverArt(allUrls.at(1)) : getCoverArt(allUrls.first()); return; } else { getCoverArt(allUrls.first()); @@ -611,9 +600,8 @@ void DlgTagFetcher::slotLoadBytesToLabel(const QByteArray& data) { coverInfo.setImage(); loadingProgressBar->setVisible(false); - QString coverArtMessage = tr("Cover art is ready to be applied"); + statusMessage->setText(tr("Cover art is ready to be applied")); statusMessage->setVisible(true); - statusMessage->setText(coverArtMessage); m_fetchedCoverArtByteArrays = data; m_pWFetchedCoverArtLabel->loadData( @@ -622,17 +610,15 @@ void DlgTagFetcher::slotLoadBytesToLabel(const QByteArray& data) { } void DlgTagFetcher::getCoverArt(const QString& url) { - QString coverArtMessage = tr("Cover art found getting image"); - loadingProgressBar->setFormat(coverArtMessage); + loadingProgressBar->setFormat(tr("Cover art found, receiving image.")); loadingProgressBar->setValue(kPercentForCoverArtImageTask); m_tagFetcher.startFetchCoverArtImage(url); } void DlgTagFetcher::slotCoverArtLinkNotFound() { loadingProgressBar->setVisible(false); + statusMessage->setText(tr("Cover Art is not available for selected metadata")); statusMessage->setVisible(true); - QString message = tr("Cover Art is not available for selected tag"); - statusMessage->setText(message); } void DlgTagFetcher::slotWorkerStarted() { @@ -643,8 +629,7 @@ void DlgTagFetcher::slotWorkerCoverArtUpdated(const CoverInfoRelative& coverInfo qDebug() << "DlgTagFetcher::slotWorkerCoverArtUpdated" << coverInfo; m_track->setCoverInfo(coverInfo); loadCurrentTrackCover(); - QString coverArtAppliedMessage = tr("Metadata & Cover Art applied"); - statusMessage->setText(coverArtAppliedMessage); + statusMessage->setText(tr("Metadata & Cover Art applied")); } void DlgTagFetcher::slotWorkerAskOverwrite(const QString& coverArtAbsolutePath, diff --git a/src/library/dlgtagfetcher.h b/src/library/dlgtagfetcher.h index 7e50249ffc0..750c3232c31 100644 --- a/src/library/dlgtagfetcher.h +++ b/src/library/dlgtagfetcher.h @@ -59,7 +59,6 @@ class DlgTagFetcher : public QDialog, public Ui::DlgTagFetcher { const QPixmap& pixmap, mixxx::cache_key_t requestedCacheKey, bool coverInfoUpdated); - void slotUpdateStatusMessage(const QString& message); void slotStartFetchCoverArt(const QList& allUrls); void slotLoadBytesToLabel(const QByteArray& data); void slotCoverArtLinkNotFound(); diff --git a/src/preferences/dialog/dlgpreflibrary.h b/src/preferences/dialog/dlgpreflibrary.h index 1c930c10459..d1c958d3b2f 100644 --- a/src/preferences/dialog/dlgpreflibrary.h +++ b/src/preferences/dialog/dlgpreflibrary.h @@ -20,7 +20,7 @@ class DlgPrefLibrary : public DlgPreferencePage, public Ui::DlgPrefLibraryDlg { Ignore = 3, }; - enum class CoverArtFetcherQuality : int { + enum class CoverArtFetcherQuality { Low = 0, Medium = 1, High = 2, From 850db448a3f9b685d99a9bf03a500267db89130d Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Sun, 13 Nov 2022 18:31:29 +0300 Subject: [PATCH 11/24] dlgtagfetcher: ui methods move to related .ui file --- src/library/dlgtagfetcher.cpp | 7 ------- src/library/dlgtagfetcher.ui | 30 ++++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/library/dlgtagfetcher.cpp b/src/library/dlgtagfetcher.cpp index 403c49bfab5..0c84caf7bda 100644 --- a/src/library/dlgtagfetcher.cpp +++ b/src/library/dlgtagfetcher.cpp @@ -131,14 +131,7 @@ void DlgTagFetcher::init() { setupUi(this); setWindowIcon(QIcon(MIXXX_ICON_PATH)); - currentCoverArtLayout->setAlignment(Qt::AlignRight | Qt::AlignTop | Qt::AlignCenter); - currentCoverArtLayout->setSpacing(0); - currentCoverArtLayout->setContentsMargins(0, 0, 0, 0); currentCoverArtLayout->insertWidget(0, m_pWCurrentCoverArtLabel.get()); - - fetchedCoverArtLayout->setAlignment(Qt::AlignRight | Qt::AlignBottom | Qt::AlignCenter); - fetchedCoverArtLayout->setSpacing(0); - fetchedCoverArtLayout->setContentsMargins(0, 0, 0, 0); fetchedCoverArtLayout->insertWidget(0, m_pWFetchedCoverArtLabel.get()); if (m_pTrackModel) { diff --git a/src/library/dlgtagfetcher.ui b/src/library/dlgtagfetcher.ui index 6cb87d6b402..aad93e9b0ad 100644 --- a/src/library/dlgtagfetcher.ui +++ b/src/library/dlgtagfetcher.ui @@ -217,6 +217,21 @@ QLayout::SetDefaultConstraint + + 0 + + + 0 + + + 0 + + + 0 + + + Qt::AlignRight|Qt::AlignTop|Qt::AlignCenter + @@ -251,6 +266,21 @@ QLayout::SetDefaultConstraint + + 0 + + + 0 + + + 0 + + + 0 + + + Qt::AlignRight|Qt::AlignBottom|Qt::AlignCenter + From 01d04004226a77ffd4406eb0ed9bd6e40cda662e Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Sun, 13 Nov 2022 23:28:03 +0300 Subject: [PATCH 12/24] tagfetcher: updated to latest musicbrainz fixes. --- src/musicbrainz/tagfetcher.cpp | 64 +++++++++++++++------------------- 1 file changed, 28 insertions(+), 36 deletions(-) diff --git a/src/musicbrainz/tagfetcher.cpp b/src/musicbrainz/tagfetcher.cpp index 9654e7b25fa..9da70a9d884 100644 --- a/src/musicbrainz/tagfetcher.cpp +++ b/src/musicbrainz/tagfetcher.cpp @@ -90,6 +90,18 @@ void TagFetcher::terminate() { m_pMusicBrainzTask->deleteLater(); m_pMusicBrainzTask = nullptr; } + + if (m_pCoverArtArchiveImageTask) { + m_pCoverArtArchiveImageTask->disconnect(this); + m_pCoverArtArchiveImageTask->deleteLater(); + m_pCoverArtArchiveImageTask = nullptr; + } + + if (m_pCoverArtArchiveLinksTask) { + m_pCoverArtArchiveLinksTask->disconnect(this); + m_pCoverArtArchiveLinksTask->deleteLater(); + m_pCoverArtArchiveLinksTask = nullptr; + } } void TagFetcher::slotFingerprintReady() { @@ -325,23 +337,10 @@ void TagFetcher::startFetchCoverArtLinks( kCoverArtArchiveLinksTimeoutMilis); } -bool TagFetcher::onCoverArtArchiveLinksTaskTerminated() { - DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); - auto* const pCoverArtArchiveLinksTask = m_pCoverArtArchiveLinksTask.get(); - DEBUG_ASSERT(sender()); - VERIFY_OR_DEBUG_ASSERT(pCoverArtArchiveLinksTask == - qobject_cast(sender())) { - return false; - } - m_pCoverArtArchiveLinksTask = nullptr; - const auto taskDeleter = mixxx::ScopedDeleteLater(pCoverArtArchiveLinksTask); - pCoverArtArchiveLinksTask->disconnect(this); - return true; -} - void TagFetcher::slotCoverArtArchiveLinksTaskAborted() { DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); - if (!onCoverArtArchiveLinksTaskTerminated()) { + if (m_pCoverArtArchiveLinksTask.get() != sender()) { + // stray call from an already aborted try return; } @@ -354,7 +353,8 @@ void TagFetcher::slotCoverArtArchiveLinksTaskNetworkError( const mixxx::network::WebResponseWithContent& responseWithContent) { Q_UNUSED(responseWithContent); DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); - if (!onCoverArtArchiveLinksTaskTerminated()) { + if (m_pCoverArtArchiveLinksTask.get() != sender()) { + // stray call from an already aborted try return; } @@ -366,7 +366,8 @@ void TagFetcher::slotCoverArtArchiveLinksTaskNetworkError( void TagFetcher::slotCoverArtArchiveLinksTaskFailed( const mixxx::network::JsonWebResponse& response) { DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); - if (!onCoverArtArchiveLinksTaskTerminated()) { + if (m_pCoverArtArchiveLinksTask.get() != sender()) { + // stray call from an already aborted try return; } @@ -382,7 +383,8 @@ void TagFetcher::slotCoverArtArchiveLinksTaskFailed( void TagFetcher::slotCoverArtArchiveLinksTaskSucceeded( const QList& allUrls) { DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); - if (!onCoverArtArchiveLinksTaskTerminated()) { + if (m_pCoverArtArchiveLinksTask.get() != sender()) { + // stray call from an already aborted try return; } @@ -421,7 +423,8 @@ void TagFetcher::startFetchCoverArtImage( } void TagFetcher::slotCoverArtArchiveImageTaskSucceeded(const QByteArray& coverArtBytes) { - if (!onCoverArtArchiveImageTaskTerminated()) { + if (m_pCoverArtArchiveImageTask.get() != sender()) { + // stray call from an already aborted try return; } @@ -433,33 +436,21 @@ void TagFetcher::slotCoverArtArchiveImageTaskSucceeded(const QByteArray& coverAr void TagFetcher::slotCoverArtArchiveImageTaskAborted() { DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); - if (!onCoverArtArchiveImageTaskTerminated()) { + if (m_pCoverArtArchiveImageTask.get() != sender()) { + // stray call from an already aborted try return; } terminate(); } -bool TagFetcher::onCoverArtArchiveImageTaskTerminated() { - DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); - auto* const pCoverArtArchiveImageTask = m_pCoverArtArchiveImageTask.get(); - DEBUG_ASSERT(sender()); - VERIFY_OR_DEBUG_ASSERT(pCoverArtArchiveImageTask == - qobject_cast(sender())) { - return false; - } - m_pCoverArtArchiveImageTask = nullptr; - const auto taskDeleter = mixxx::ScopedDeleteLater(pCoverArtArchiveImageTask); - pCoverArtArchiveImageTask->disconnect(this); - return true; -} - void TagFetcher::slotCoverArtArchiveImageTaskFailed( const mixxx::network::WebResponse& response, int errorCode, const QString& errorMessage) { DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); - if (!onCoverArtArchiveImageTaskTerminated()) { + if (m_pCoverArtArchiveImageTask.get() != sender()) { + // stray call from an already aborted try return; } @@ -478,7 +469,8 @@ void TagFetcher::slotCoverArtArchiveImageTaskNetworkError( const mixxx::network::WebResponseWithContent& responseWithContent) { Q_UNUSED(responseWithContent); DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); - if (!onCoverArtArchiveImageTaskTerminated()) { + if (m_pCoverArtArchiveImageTask.get() != sender()) { + // stray call from an already aborted try return; } From 4e53b079c37c17525ed16e6a526c3da7a95fd269 Mon Sep 17 00:00:00 2001 From: ronso0 Date: Sun, 20 Nov 2022 01:04:41 +0100 Subject: [PATCH 13/24] DlgCoverArtFullSize: adjust for population via CoverArtFetcher --- src/library/dlgcoverartfullsize.cpp | 21 +++++++++++---------- src/library/dlgcoverartfullsize.h | 1 + 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/library/dlgcoverartfullsize.cpp b/src/library/dlgcoverartfullsize.cpp index d7e9f88a20f..f1a9806ca0b 100644 --- a/src/library/dlgcoverartfullsize.cpp +++ b/src/library/dlgcoverartfullsize.cpp @@ -17,7 +17,8 @@ DlgCoverArtFullSize::DlgCoverArtFullSize( WCoverArtMenu* pCoverMenu) : QDialog(parent), m_pPlayer(pPlayer), - m_pCoverMenu(pCoverMenu) { + m_pCoverMenu(pCoverMenu), + m_coverPressed(false) { CoverArtCache* pCache = CoverArtCache::instance(); if (pCache) { connect(pCache, @@ -83,20 +84,16 @@ void DlgCoverArtFullSize::init(TrackPointer pTrack) { } void DlgCoverArtFullSize::initFetchedCoverArt(const QByteArray& fetchedCoverArtBytes) { - QPixmap image; - image.loadFromData(fetchedCoverArtBytes); + m_pixmap.loadFromData(fetchedCoverArtBytes); - resize(image.size().width(), image.size().height()); + // The real size will be calculated later by adjustImageAndDialogSize(). + resize(100, 100); show(); + setWindowTitle(tr("Fetched Cover Art")); raise(); activateWindow(); - QString fetchedCoverArtWindowTitle = tr("Fetched Cover Art"); - - setWindowTitle(fetchedCoverArtWindowTitle); - - //TODO: Do a better scaling. It populates wrong if the cover art size highest. - coverArt->setPixmap(image); + adjustImageAndDialogSize(); } void DlgCoverArtFullSize::slotLoadTrack(TrackPointer pTrack) { @@ -175,6 +172,10 @@ void DlgCoverArtFullSize::slotCoverFound( m_pixmap = pixmap; + adjustImageAndDialogSize(); +} + +void DlgCoverArtFullSize::adjustImageAndDialogSize() { if (m_pixmap.isNull()) { coverArt->setPixmap(QPixmap()); hide(); diff --git a/src/library/dlgcoverartfullsize.h b/src/library/dlgcoverartfullsize.h index e2d71215421..d6d770d6278 100644 --- a/src/library/dlgcoverartfullsize.h +++ b/src/library/dlgcoverartfullsize.h @@ -39,6 +39,7 @@ class DlgCoverArtFullSize mixxx::cache_key_t requestedCacheKey, bool coverInfoUpdated); void slotTrackCoverArtUpdated(); + void adjustImageAndDialogSize(); // slots that handle signals from WCoverArtMenu void slotCoverMenu(const QPoint& pos); From cf54d53516ceebf4ff42dccb3e34de0cf4b089ca Mon Sep 17 00:00:00 2001 From: ronso0 Date: Sun, 20 Nov 2022 01:23:10 +0100 Subject: [PATCH 14/24] DlgPrefLibrary::slotResetToDefaults: remove obsolete actions --- src/preferences/dialog/dlgpreflibrary.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/preferences/dialog/dlgpreflibrary.cpp b/src/preferences/dialog/dlgpreflibrary.cpp index b9b8b27d242..280b4bcfa6a 100644 --- a/src/preferences/dialog/dlgpreflibrary.cpp +++ b/src/preferences/dialog/dlgpreflibrary.cpp @@ -203,12 +203,7 @@ void DlgPrefLibrary::slotResetToDefaults() { checkBox_show_traktor->setChecked(true); checkBox_show_rekordbox->setChecked(true); checkBoxEditMetadataSelectedClicked->setChecked(kEditMetadataSelectedClickDefault); - radioButton_dbclick_bottom->setChecked(false); - radioButton_dbclick_top->setChecked(false); radioButton_dbclick_deck->setChecked(true); - radioButton_cover_art_fetcher_highest->setChecked(false); - radioButton_cover_art_fetcher_high->setChecked(false); - radioButton_cover_art_fetcher_medium->setChecked(false); radioButton_cover_art_fetcher_lowest->setChecked(true); spinBoxRowHeight->setValue(Library::kDefaultRowHeightPx); setLibraryFont(QApplication::font()); From a79b1bbe0af94a44b6eb20a9cd88e9dde1c8af63 Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Mon, 21 Nov 2022 10:41:52 +0300 Subject: [PATCH 15/24] dlgpreflibrary: Preference changed with pixels --- src/preferences/dialog/dlgpreflibrary.cpp | 2 +- src/preferences/dialog/dlgpreflibrarydlg.ui | 34 ++++++++++----------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/preferences/dialog/dlgpreflibrary.cpp b/src/preferences/dialog/dlgpreflibrary.cpp index 280b4bcfa6a..10a1b203b36 100644 --- a/src/preferences/dialog/dlgpreflibrary.cpp +++ b/src/preferences/dialog/dlgpreflibrary.cpp @@ -204,7 +204,7 @@ void DlgPrefLibrary::slotResetToDefaults() { checkBox_show_rekordbox->setChecked(true); checkBoxEditMetadataSelectedClicked->setChecked(kEditMetadataSelectedClickDefault); radioButton_dbclick_deck->setChecked(true); - radioButton_cover_art_fetcher_lowest->setChecked(true); + radioButton_cover_art_fetcher_medium->setChecked(true); spinBoxRowHeight->setValue(Library::kDefaultRowHeightPx); setLibraryFont(QApplication::font()); searchDebouncingTimeoutSpinBox->setValue( diff --git a/src/preferences/dialog/dlgpreflibrarydlg.ui b/src/preferences/dialog/dlgpreflibrarydlg.ui index c2ae8a5b900..89916ce2463 100644 --- a/src/preferences/dialog/dlgpreflibrarydlg.ui +++ b/src/preferences/dialog/dlgpreflibrarydlg.ui @@ -455,56 +455,56 @@ - Cover Art Fetcher + Preferred Cover Art Fetcher Resolution - + - Highest - - + Fetch cover art from coverartarchive.com by using Import Metadata From Musicbrainz. - + - High - - + Note: ">1200 px" can fetch up to very large cover arts. - + - Medium + >1200 px (if available) - + - Low + 1200 px (if available) - + - Fetch cover art from coverartarchive.com by using Import Metadata From Musicbrainz. + 500 px + + - + - Highest resolution can fetch up to very large cover arts. + 250 px + + From 4c1cc06ed35118e461bb44e82fad746ba982b78d Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Mon, 21 Nov 2022 11:02:00 +0300 Subject: [PATCH 16/24] coverartfetcher: fix pre-commit. --- src/library/dlgtagfetcher.cpp | 2 +- src/musicbrainz/tagfetcher.cpp | 4 ++-- src/musicbrainz/tagfetcher.h | 20 +++++++++---------- .../web/coverartarchivelinkstask.cpp | 1 - 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/library/dlgtagfetcher.cpp b/src/library/dlgtagfetcher.cpp index 0c84caf7bda..895aa4277bf 100644 --- a/src/library/dlgtagfetcher.cpp +++ b/src/library/dlgtagfetcher.cpp @@ -598,7 +598,7 @@ void DlgTagFetcher::slotLoadBytesToLabel(const QByteArray& data) { m_fetchedCoverArtByteArrays = data; m_pWFetchedCoverArtLabel->loadData( - m_fetchedCoverArtByteArrays); //This data loaded because for full size. + m_fetchedCoverArtByteArrays); // This data loaded because for full size. m_pWFetchedCoverArtLabel->setCoverArt(coverInfo, fetchedCoverArtPixmap); } diff --git a/src/musicbrainz/tagfetcher.cpp b/src/musicbrainz/tagfetcher.cpp index 9da70a9d884..f4b1710a96e 100644 --- a/src/musicbrainz/tagfetcher.cpp +++ b/src/musicbrainz/tagfetcher.cpp @@ -306,8 +306,8 @@ void TagFetcher::slotMusicBrainzTaskSucceeded( void TagFetcher::startFetchCoverArtLinks( const QUuid& albumReleaseId) { - //In here the progress message can be handled better. - //emit fetchProgress(tr("Finding Possible Cover Arts on Cover Art Archive")); + // In here the progress message can be handled better. + // emit fetchProgress(tr("Finding Possible Cover Arts on Cover Art Archive")); DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); terminate(); diff --git a/src/musicbrainz/tagfetcher.h b/src/musicbrainz/tagfetcher.h index 63412d0acf1..55043273bac 100644 --- a/src/musicbrainz/tagfetcher.h +++ b/src/musicbrainz/tagfetcher.h @@ -26,18 +26,18 @@ class TagFetcher : public QObject { void startFetch( TrackPointer pTrack); - //This is called from dlgTagFetcher. - //This starts the initial task for to find the cover art links - //4 Possible cover art links fetched in this task. - //This can be >1200px-1200px-500px-250px image links. + // This is called from dlgTagFetcher. + // This starts the initial task for to find the cover art links + // 4 Possible cover art links fetched in this task. + // This can be >1200px-1200px-500px-250px image links. void startFetchCoverArtLinks(const QUuid& albumReleaseId); - //After the first task is done successfully. - //This is called automatically. - //This task starts to fetch the image. - //Link provided from preference option. - //After a success task, related label updated with cover art. - //If user presses apply, cover art downloaded and applied to the song. + // After the first task is done successfully. + // This is called automatically. + // This task starts to fetch the image. + // Link provided from preference option. + // After a success task, related label updated with cover art. + // If user presses apply, cover art downloaded and applied to the song. void startFetchCoverArtImage( const QString& coverArtUrl); diff --git a/src/musicbrainz/web/coverartarchivelinkstask.cpp b/src/musicbrainz/web/coverartarchivelinkstask.cpp index 44d451ed93b..4b263ba7611 100644 --- a/src/musicbrainz/web/coverartarchivelinkstask.cpp +++ b/src/musicbrainz/web/coverartarchivelinkstask.cpp @@ -58,7 +58,6 @@ QNetworkReply* CoverArtArchiveLinksTask::sendNetworkRequest( const QUrl& url, const QJsonDocument& content) { DEBUG_ASSERT(networkAccessManager); - //DEBUG_ASSERT(!m_queuedAlbumReleaseIds.first().isNull()); Q_UNUSED(method); DEBUG_ASSERT(method == network::HttpRequestMethod::Get); networkAccessManager->setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy); From c3cd36883da354e18dfd624115ddb070971d6168 Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Tue, 22 Nov 2022 03:03:58 +0300 Subject: [PATCH 17/24] covarartarchiveitasks: p prefix added for pointers --- .../web/coverartarchiveimagetask.cpp | 20 +++++++++---------- .../web/coverartarchiveimagetask.h | 8 ++++---- .../web/coverartarchivelinkstask.cpp | 16 +++++++-------- .../web/coverartarchivelinkstask.h | 6 +++--- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/musicbrainz/web/coverartarchiveimagetask.cpp b/src/musicbrainz/web/coverartarchiveimagetask.cpp index 5817e2faff3..6bdb2c0672f 100644 --- a/src/musicbrainz/web/coverartarchiveimagetask.cpp +++ b/src/musicbrainz/web/coverartarchiveimagetask.cpp @@ -25,21 +25,21 @@ QNetworkRequest createNetworkRequest(const QString& coverArtUrl) { } // anonymous namespace CoverArtArchiveImageTask::CoverArtArchiveImageTask( - QNetworkAccessManager* networkAccessManager, + QNetworkAccessManager* pNetworkAccessManager, const QString& coverArtLink, - QObject* parent) + QObject* pParent) : network::WebTask( - networkAccessManager, - parent), + pNetworkAccessManager, + pParent), m_coverArtUrl(coverArtLink) { } QNetworkReply* CoverArtArchiveImageTask::doStartNetworkRequest( - QNetworkAccessManager* networkAccessManager, + QNetworkAccessManager* pNetworkAccessManager, int parentTimeoutMillis) { - networkAccessManager->setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy); + pNetworkAccessManager->setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy); DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); - DEBUG_ASSERT(networkAccessManager); + DEBUG_ASSERT(pNetworkAccessManager); const QNetworkRequest networkRequest = createNetworkRequest(m_coverArtUrl); @@ -49,15 +49,15 @@ QNetworkReply* CoverArtArchiveImageTask::doStartNetworkRequest( << "GET" << networkRequest.url(); } - return networkAccessManager->get(networkRequest); + return pNetworkAccessManager->get(networkRequest); } void CoverArtArchiveImageTask::doNetworkReplyFinished( - QNetworkReply* finishedNetworkReply, + QNetworkReply* pFinishedNetworkReply, network::HttpStatusCode statusCode) { DEBUG_ASSERT_QOBJECT_THREAD_AFFINITY(this); - const QByteArray resultImageBytes = finishedNetworkReply->readAll(); + const QByteArray resultImageBytes = pFinishedNetworkReply->readAll(); if (statusCode != 200) { kLogger.info() diff --git a/src/musicbrainz/web/coverartarchiveimagetask.h b/src/musicbrainz/web/coverartarchiveimagetask.h index eda0aacba53..c2833f4a8e4 100644 --- a/src/musicbrainz/web/coverartarchiveimagetask.h +++ b/src/musicbrainz/web/coverartarchiveimagetask.h @@ -9,9 +9,9 @@ class CoverArtArchiveImageTask : public network::WebTask { public: CoverArtArchiveImageTask( - QNetworkAccessManager* networkAccessManager, + QNetworkAccessManager* pNetworkAccessManager, const QString& coverArtLink, - QObject* parent = nullptr); + QObject* pParent = nullptr); ~CoverArtArchiveImageTask() override = default; signals: @@ -25,11 +25,11 @@ class CoverArtArchiveImageTask : public network::WebTask { private: QNetworkReply* doStartNetworkRequest( - QNetworkAccessManager* networkAccessManager, + QNetworkAccessManager* pNetworkAccessManager, int parentTimeoutMillis) override; void doNetworkReplyFinished( - QNetworkReply* finishedNetworkReply, + QNetworkReply* pFinishedNetworkReply, network::HttpStatusCode statusCode) override; QString m_coverArtUrl; diff --git a/src/musicbrainz/web/coverartarchivelinkstask.cpp b/src/musicbrainz/web/coverartarchivelinkstask.cpp index 4b263ba7611..21dc9f2c101 100644 --- a/src/musicbrainz/web/coverartarchivelinkstask.cpp +++ b/src/musicbrainz/web/coverartarchivelinkstask.cpp @@ -41,26 +41,26 @@ QNetworkRequest createNetworkRequest( } // anonymous namespace CoverArtArchiveLinksTask::CoverArtArchiveLinksTask( - QNetworkAccessManager* networkAccessManager, + QNetworkAccessManager* pNetworkAccessManager, const QUuid& albumReleaseId, - QObject* parent) + QObject* pParent) : network::JsonWebTask( - networkAccessManager, + pNetworkAccessManager, kBaseUrl, lookupRequest(), - parent), + pParent), m_albumReleaseId(albumReleaseId) { } QNetworkReply* CoverArtArchiveLinksTask::sendNetworkRequest( - QNetworkAccessManager* networkAccessManager, + QNetworkAccessManager* pNetworkAccessManager, network::HttpRequestMethod method, const QUrl& url, const QJsonDocument& content) { - DEBUG_ASSERT(networkAccessManager); + DEBUG_ASSERT(pNetworkAccessManager); Q_UNUSED(method); DEBUG_ASSERT(method == network::HttpRequestMethod::Get); - networkAccessManager->setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy); + pNetworkAccessManager->setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy); const QNetworkRequest networkRequest = createNetworkRequest(m_albumReleaseId); @@ -73,7 +73,7 @@ QNetworkReply* CoverArtArchiveLinksTask::sendNetworkRequest( << "Get" << url; } - return networkAccessManager->get(networkRequest); + return pNetworkAccessManager->get(networkRequest); } void CoverArtArchiveLinksTask::onFinished( diff --git a/src/musicbrainz/web/coverartarchivelinkstask.h b/src/musicbrainz/web/coverartarchivelinkstask.h index 09feae0332f..434ab699235 100644 --- a/src/musicbrainz/web/coverartarchivelinkstask.h +++ b/src/musicbrainz/web/coverartarchivelinkstask.h @@ -14,9 +14,9 @@ class CoverArtArchiveLinksTask : public network::JsonWebTask { public: CoverArtArchiveLinksTask( - QNetworkAccessManager* networkAccessManager, + QNetworkAccessManager* pNetworkAccessManager, const QUuid& albumReleaseId, - QObject* parent = nullptr); + QObject* pParent = nullptr); ~CoverArtArchiveLinksTask() override = default; @@ -26,7 +26,7 @@ class CoverArtArchiveLinksTask : public network::JsonWebTask { private: QNetworkReply* sendNetworkRequest( - QNetworkAccessManager* networkAccessManager, + QNetworkAccessManager* pNetworkAccessManager, network::HttpRequestMethod method, const QUrl& url, const QJsonDocument& content) override; From d59da65fc7ab891df72efb5381be4f1d6aecea50 Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Tue, 22 Nov 2022 03:22:47 +0300 Subject: [PATCH 18/24] coverartarchiveimagetask: missing emit methods add --- .../web/coverartarchiveimagetask.cpp | 41 ++++++++++++++++++- .../web/coverartarchiveimagetask.h | 7 ++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/musicbrainz/web/coverartarchiveimagetask.cpp b/src/musicbrainz/web/coverartarchiveimagetask.cpp index 6bdb2c0672f..0dec9b4ef9f 100644 --- a/src/musicbrainz/web/coverartarchiveimagetask.cpp +++ b/src/musicbrainz/web/coverartarchiveimagetask.cpp @@ -63,10 +63,49 @@ void CoverArtArchiveImageTask::doNetworkReplyFinished( kLogger.info() << "GET reply" << "statusCode:" << statusCode; + emitFailed( + network::WebResponse( + pFinishedNetworkReply->url(), + pFinishedNetworkReply->request().url(), + statusCode), + statusCode, + QStringLiteral("Failed to get Image")); return; } - emit succeeded(resultImageBytes); + emitSucceeded(resultImageBytes); +} + +void CoverArtArchiveImageTask::emitSucceeded( + const QByteArray& coverArtImageBytes) { + VERIFY_OR_DEBUG_ASSERT( + isSignalFuncConnected(&CoverArtArchiveImageTask::succeeded)) { + kLogger.warning() + << "Unhandled succeeded signal"; + deleteLater(); + return; + } + emit succeeded(coverArtImageBytes); +} + +void CoverArtArchiveImageTask::emitFailed( + const network::WebResponse& response, + int errorCode, + const QString& errorMessage) { + VERIFY_OR_DEBUG_ASSERT( + isSignalFuncConnected(&CoverArtArchiveImageTask::failed)) { + kLogger.warning() + << "Unhandled failed signal" + << response + << errorCode + << errorMessage; + deleteLater(); + return; + } + emit failed( + response, + errorCode, + errorMessage); } } // namespace mixxx diff --git a/src/musicbrainz/web/coverartarchiveimagetask.h b/src/musicbrainz/web/coverartarchiveimagetask.h index c2833f4a8e4..c6bddf9d39b 100644 --- a/src/musicbrainz/web/coverartarchiveimagetask.h +++ b/src/musicbrainz/web/coverartarchiveimagetask.h @@ -32,6 +32,13 @@ class CoverArtArchiveImageTask : public network::WebTask { QNetworkReply* pFinishedNetworkReply, network::HttpStatusCode statusCode) override; + void emitSucceeded(const QByteArray& coverArtImageBytes); + + void emitFailed( + const network::WebResponse& response, + int errorCode, + const QString& errorMessage); + QString m_coverArtUrl; QByteArray coverArtImageBytes; From b5a5e7293da110a59b591ff3afbe1a2033889ba8 Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Thu, 24 Nov 2022 13:47:15 +0300 Subject: [PATCH 19/24] dlgtagfetcher: fixed 500px cover art not fetching. --- src/library/dlgtagfetcher.cpp | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/src/library/dlgtagfetcher.cpp b/src/library/dlgtagfetcher.cpp index 895aa4277bf..183e100e326 100644 --- a/src/library/dlgtagfetcher.cpp +++ b/src/library/dlgtagfetcher.cpp @@ -550,37 +550,30 @@ void DlgTagFetcher::slotStartFetchCoverArt(const QList& allUrls) { DlgPrefLibrary::CoverArtFetcherQuality fetcherQuality = static_cast( m_pConfig->getValue(mixxx::library::prefs::kCoverArtFetcherQualityConfigKey, - static_cast(DlgPrefLibrary::CoverArtFetcherQuality::Low))); + static_cast(DlgPrefLibrary::CoverArtFetcherQuality::Medium))); // Cover art links task can retrieve us variable number of links with different cover art sizes // Every single successful response has 2 links. - // These links are cover arts with 250 PX and 500 PX - // Some of the tags might have link of a cover art with 1200 PX - // Some of the tags might have link of a cover art more than 1200 PX - // At final, we always retrieve 2 links, but for some tags this can be 3 or 4 - // We need to pick the correct size according to user choice + // These links belongs to cover arts with 250 PX and 500 PX + // Some of the releases might have link of a cover art with 1200 PX + // Some of the releases might have link of a cover art which is more than 1200 PX + // To sum up, 2 links are always retrieved, but for some releases this can be 3 or 4 + // Picking the correct size according to user choice is a must. // User choices and the possible fetched cover art sizes are: - // Highest -> More than 1200 PX, if not available 1200 PX or 500 PX - // High -> 1200 PX if not available 500 PX - // Medium -> Always 500 PX fetched - // Low -> Always 250 PX fetched + // Highest -> >1200 PX, if not available highest possible + // High -> 1200 PX, if not available highest possible + // Medium -> 500 PX, at all times + // Low -> 250 PX, at all times VERIFY_OR_DEBUG_ASSERT(!allUrls.isEmpty()) { return; } - if (fetcherQuality == DlgPrefLibrary::CoverArtFetcherQuality::Highest) { - getCoverArt(allUrls.last()); - return; - } else if (fetcherQuality == DlgPrefLibrary::CoverArtFetcherQuality::High) { - allUrls.size() < 3 ? getCoverArt(allUrls.last()) : getCoverArt(allUrls.at(2)); - return; - } else if (fetcherQuality == DlgPrefLibrary::CoverArtFetcherQuality::Medium) { - allUrls.size() == 2 ? getCoverArt(allUrls.at(1)) : getCoverArt(allUrls.first()); - return; + if (allUrls.size() > static_cast(fetcherQuality)) { + getCoverArt(allUrls.at(static_cast(fetcherQuality))); } else { - getCoverArt(allUrls.first()); + getCoverArt(allUrls.last()); } } From 74550683578f1a859ca7dafe84ec40682eb1869b Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Thu, 24 Nov 2022 13:48:15 +0300 Subject: [PATCH 20/24] dlgtagfetcher: compose fetched CA path improved --- src/library/dlgtagfetcher.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/library/dlgtagfetcher.cpp b/src/library/dlgtagfetcher.cpp index 183e100e326..4187be51e2a 100644 --- a/src/library/dlgtagfetcher.cpp +++ b/src/library/dlgtagfetcher.cpp @@ -337,10 +337,13 @@ void DlgTagFetcher::apply() { QFileInfo trackFileInfo = QFileInfo(m_track->getLocation()); + // Compose the Cover Art file path. Use the correct file extension + // by checking from the fetched image bytes (disregard extension + // from file link). QString coverArtCopyFilePath = trackFileInfo.absoluteFilePath().left( trackFileInfo.absoluteFilePath().lastIndexOf('.') + 1) + - "jpeg"; + ImageFileData::readFormatFrom(m_fetchedCoverArtByteArrays); m_worker.reset(new CoverArtCopyWorker( QString(), coverArtCopyFilePath, m_fetchedCoverArtByteArrays)); From 32e95f9fd44e623aca0da62a6ea0b0c9ff830ed0 Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Thu, 24 Nov 2022 13:48:44 +0300 Subject: [PATCH 21/24] coverartarchivelinkstask: example JSON schema add --- src/musicbrainz/web/coverartarchivelinkstask.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/musicbrainz/web/coverartarchivelinkstask.cpp b/src/musicbrainz/web/coverartarchivelinkstask.cpp index 21dc9f2c101..571f002999f 100644 --- a/src/musicbrainz/web/coverartarchivelinkstask.cpp +++ b/src/musicbrainz/web/coverartarchivelinkstask.cpp @@ -108,6 +108,10 @@ void CoverArtArchiveLinksTask::onFinished( return; } + // An example JSON schema can be found for the release: 48cf6a4e-4c61-4214-afe3-ed4e11d902c9 + // JSON Schema: https://coverartarchive.org/release/48cf6a4e-4c61-4214-afe3-ed4e11d902c9 + // See also: https://wiki.musicbrainz.org/Cover_Art_Archive/API + QList allUrls; DEBUG_ASSERT(jsonObject.value(QLatin1String("images")).isArray()); const QJsonArray images = jsonObject.value(QLatin1String("images")).toArray(); @@ -118,6 +122,10 @@ void CoverArtArchiveLinksTask::onFinished( const auto thumbnails = imageObject.value(QLatin1String("thumbnails")).toObject(); DEBUG_ASSERT(!thumbnails.isEmpty()); + // Due to few exceptions encountered + // For 250 PX and 500 PX cover arts, "small" and "large" keys are used. + // See: https://coverartarchive.org/release/5240094f-9d79-44fd-9985-77c7287bcc16 + const auto smallThumbnailUrl = thumbnails.value(QLatin1String("small")).toString(); DEBUG_ASSERT(!smallThumbnailUrl.isNull()); allUrls.append(smallThumbnailUrl); From 6bb4db1db7ef3d1d13757c9dc33494949bbb59c9 Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Thu, 1 Dec 2022 19:03:41 +0300 Subject: [PATCH 22/24] dlgtagfetcher: redundant disconnect deleted --- src/library/dlgtagfetcher.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/library/dlgtagfetcher.cpp b/src/library/dlgtagfetcher.cpp index 4187be51e2a..708c77f01e3 100644 --- a/src/library/dlgtagfetcher.cpp +++ b/src/library/dlgtagfetcher.cpp @@ -227,11 +227,6 @@ void DlgTagFetcher::loadTrack(const TrackPointer& pTrack) { m_pWFetchedCoverArtLabel->setCoverArt(CoverInfo{}, QPixmap{}); - disconnect(m_track.get(), - &Track::changed, - this, - &DlgTagFetcher::slotTrackChanged); - m_track = pTrack; if (!m_track) { return; From 5e48d83e84b56e4a60e1c40ccc1a90eeb28c6d56 Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Thu, 1 Dec 2022 19:06:19 +0300 Subject: [PATCH 23/24] dlgtagfetcher: add fetched coverart always deleted --- src/library/dlgtagfetcher.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/library/dlgtagfetcher.cpp b/src/library/dlgtagfetcher.cpp index 708c77f01e3..e99db12c8fc 100644 --- a/src/library/dlgtagfetcher.cpp +++ b/src/library/dlgtagfetcher.cpp @@ -510,12 +510,10 @@ void DlgTagFetcher::tagSelected() { const int tagIndex = tags->currentItem()->data(0, Qt::UserRole).toInt(); m_data.m_selectedTag = tagIndex; - if (!m_fetchedCoverArtByteArrays.isNull()) { - m_fetchedCoverArtByteArrays.clear(); - m_pWFetchedCoverArtLabel->loadData(m_fetchedCoverArtByteArrays); - m_pWFetchedCoverArtLabel->setCoverArt(CoverInfo{}, - QPixmap(CoverArtUtils::defaultCoverLocation())); - } + m_fetchedCoverArtByteArrays.clear(); + m_pWFetchedCoverArtLabel->loadData(QByteArray()); + m_pWFetchedCoverArtLabel->setCoverArt(CoverInfo{}, + QPixmap(CoverArtUtils::defaultCoverLocation())); const mixxx::musicbrainz::TrackRelease& trackRelease = m_data.m_tags[tagIndex]; QUuid selectedTagAlbumId = trackRelease.albumReleaseId; From 697f41a74707eec4eb1ecb4932f5b3404daa11ea Mon Sep 17 00:00:00 2001 From: Fatih Emre YILDIZ Date: Thu, 1 Dec 2022 19:15:54 +0300 Subject: [PATCH 24/24] dlgtagfetcher: p prefix added for pointers --- src/library/dlgtagfetcher.cpp | 78 +++++++++++++++++------------------ src/library/dlgtagfetcher.h | 12 +++--- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/library/dlgtagfetcher.cpp b/src/library/dlgtagfetcher.cpp index e99db12c8fc..c12dacfbda9 100644 --- a/src/library/dlgtagfetcher.cpp +++ b/src/library/dlgtagfetcher.cpp @@ -93,9 +93,9 @@ void addTrack( const QStringList& trackRow, int tagIndex, QTreeWidget* pParent) { - QTreeWidgetItem* item = new QTreeWidgetItem(pParent, trackRow); - item->setData(0, Qt::UserRole, tagIndex); - item->setData(0, Qt::TextAlignmentRole, Qt::AlignLeft); + QTreeWidgetItem* pItem = new QTreeWidgetItem(pParent, trackRow); + pItem->setData(0, Qt::UserRole, tagIndex); + pItem->setData(0, Qt::TextAlignmentRole, Qt::AlignLeft); } void updateOriginalTag(const Track& track, QTreeWidget* pParent) { @@ -215,9 +215,9 @@ void DlgTagFetcher::slotPrev() { } void DlgTagFetcher::loadTrack(const TrackPointer& pTrack) { - if (m_track) { + if (m_pTrack) { tags->clear(); - disconnect(m_track.get(), + disconnect(m_pTrack.get(), &Track::changed, this, &DlgTagFetcher::slotTrackChanged); @@ -227,8 +227,8 @@ void DlgTagFetcher::loadTrack(const TrackPointer& pTrack) { m_pWFetchedCoverArtLabel->setCoverArt(CoverInfo{}, QPixmap{}); - m_track = pTrack; - if (!m_track) { + m_pTrack = pTrack; + if (!m_pTrack) { return; } @@ -238,15 +238,15 @@ void DlgTagFetcher::loadTrack(const TrackPointer& pTrack) { loadingProgressBar->setVisible(true); loadingProgressBar->setValue(kMinimumValueOfQProgressBar); addDivider(tr("Original tags"), tags); - addTrack(trackColumnValues(*m_track), kOriginalTrackIndex, tags); + addTrack(trackColumnValues(*m_pTrack), kOriginalTrackIndex, tags); - connect(m_track.get(), + connect(m_pTrack.get(), &Track::changed, this, &DlgTagFetcher::slotTrackChanged); loadCurrentTrackCover(); - m_tagFetcher.startFetch(m_track); + m_tagFetcher.startFetch(m_pTrack); } void DlgTagFetcher::loadTrack(const QModelIndex& index) { @@ -256,8 +256,8 @@ void DlgTagFetcher::loadTrack(const QModelIndex& index) { } void DlgTagFetcher::slotTrackChanged(TrackId trackId) { - if (m_track && m_track->getId() == trackId) { - updateOriginalTag(*m_track, tags); + if (m_pTrack && m_pTrack->getId() == trackId) { + updateOriginalTag(*m_pTrack, tags); } } @@ -269,7 +269,7 @@ void DlgTagFetcher::apply() { DEBUG_ASSERT(tagIndex < m_data.m_tags.size()); const mixxx::musicbrainz::TrackRelease& trackRelease = m_data.m_tags[tagIndex]; - mixxx::TrackMetadata trackMetadata = m_track->getMetadata(); + mixxx::TrackMetadata trackMetadata = m_pTrack->getMetadata(); if (!trackRelease.artist.isEmpty()) { trackMetadata.refTrackInfo().setArtist( trackRelease.artist); @@ -330,7 +330,7 @@ void DlgTagFetcher::apply() { return; }; - QFileInfo trackFileInfo = QFileInfo(m_track->getLocation()); + QFileInfo trackFileInfo = QFileInfo(m_pTrack->getLocation()); // Compose the Cover Art file path. Use the correct file extension // by checking from the fetched image bytes (disregard extension @@ -340,40 +340,40 @@ void DlgTagFetcher::apply() { trackFileInfo.absoluteFilePath().lastIndexOf('.') + 1) + ImageFileData::readFormatFrom(m_fetchedCoverArtByteArrays); - m_worker.reset(new CoverArtCopyWorker( + m_pWorker.reset(new CoverArtCopyWorker( QString(), coverArtCopyFilePath, m_fetchedCoverArtByteArrays)); - connect(m_worker.data(), + connect(m_pWorker.data(), &CoverArtCopyWorker::started, this, &DlgTagFetcher::slotWorkerStarted); - connect(m_worker.data(), + connect(m_pWorker.data(), &CoverArtCopyWorker::askOverwrite, this, &DlgTagFetcher::slotWorkerAskOverwrite); - connect(m_worker.data(), + connect(m_pWorker.data(), &CoverArtCopyWorker::coverArtCopyFailed, this, &DlgTagFetcher::slotWorkerCoverArtCopyFailed); - connect(m_worker.data(), + connect(m_pWorker.data(), &CoverArtCopyWorker::coverArtUpdated, this, &DlgTagFetcher::slotWorkerCoverArtUpdated); - connect(m_worker.data(), + connect(m_pWorker.data(), &CoverArtCopyWorker::finished, this, &DlgTagFetcher::slotWorkerFinished); - m_worker->start(); + m_pWorker->start(); } statusMessage->setText(tr("Selected metadata applied")); - m_track->replaceMetadataFromSource( + m_pTrack->replaceMetadataFromSource( std::move(trackMetadata), // Prevent re-import of outdated metadata from file tags // by explicitly setting the synchronization time stamp @@ -385,7 +385,7 @@ void DlgTagFetcher::retry() { btnRetry->setDisabled(true); btnApply->setDisabled(true); loadingProgressBar->setValue(kMinimumValueOfQProgressBar); - m_tagFetcher.startFetch(m_track); + m_tagFetcher.startFetch(m_pTrack); } void DlgTagFetcher::quit() { @@ -405,9 +405,9 @@ void DlgTagFetcher::showProgressOfConstantTask(const QString& text) { } void DlgTagFetcher::loadCurrentTrackCover() { - m_pWCurrentCoverArtLabel->loadTrack(m_track); + m_pWCurrentCoverArtLabel->loadTrack(m_pTrack); CoverArtCache* pCache = CoverArtCache::instance(); - pCache->requestTrackCover(this, m_track); + pCache->requestTrackCover(this, m_pTrack); } void DlgTagFetcher::showProgressOfRecordingTask() { @@ -423,7 +423,7 @@ void DlgTagFetcher::setPercentOfEachRecordings(int totalRecordingsFound) { void DlgTagFetcher::fetchTagFinished( TrackPointer pTrack, const QList& guessedTrackReleases) { - VERIFY_OR_DEBUG_ASSERT(pTrack == m_track) { + VERIFY_OR_DEBUG_ASSERT(pTrack == m_pTrack) { return; } m_data.m_tags = guessedTrackReleases; @@ -438,7 +438,7 @@ void DlgTagFetcher::fetchTagFinished( loadingProgressBar->setVisible(false); statusMessage->setVisible(true); - VERIFY_OR_DEBUG_ASSERT(m_track) { + VERIFY_OR_DEBUG_ASSERT(m_pTrack) { return; } @@ -487,15 +487,15 @@ void DlgTagFetcher::slotNetworkResult( } void DlgTagFetcher::addDivider(const QString& text, QTreeWidget* pParent) const { - QTreeWidgetItem* item = new QTreeWidgetItem(pParent); - item->setFirstColumnSpanned(true); - item->setText(0, text); - item->setFlags(Qt::NoItemFlags); - item->setForeground(0, palette().color(QPalette::Disabled, QPalette::Text)); + QTreeWidgetItem* pItem = new QTreeWidgetItem(pParent); + pItem->setFirstColumnSpanned(true); + pItem->setText(0, text); + pItem->setFlags(Qt::NoItemFlags); + pItem->setForeground(0, palette().color(QPalette::Disabled, QPalette::Text)); QFont bold_font(font()); bold_font.setBold(true); - item->setFont(0, bold_font); + pItem->setFont(0, bold_font); } void DlgTagFetcher::tagSelected() { @@ -535,8 +535,8 @@ void DlgTagFetcher::slotCoverFound( Q_UNUSED(requestedCacheKey); Q_UNUSED(coverInfoUpdated); if (pRequestor == this && - m_track && - m_track->getLocation() == coverInfo.trackLocation) { + m_pTrack && + m_pTrack->getLocation() == coverInfo.trackLocation) { m_trackRecord.setCoverInfo(coverInfo); m_pWCurrentCoverArtLabel->setCoverArt(coverInfo, pixmap); } @@ -609,13 +609,13 @@ void DlgTagFetcher::slotWorkerStarted() { void DlgTagFetcher::slotWorkerCoverArtUpdated(const CoverInfoRelative& coverInfo) { qDebug() << "DlgTagFetcher::slotWorkerCoverArtUpdated" << coverInfo; - m_track->setCoverInfo(coverInfo); + m_pTrack->setCoverInfo(coverInfo); loadCurrentTrackCover(); statusMessage->setText(tr("Metadata & Cover Art applied")); } void DlgTagFetcher::slotWorkerAskOverwrite(const QString& coverArtAbsolutePath, - std::promise* promise) { + std::promise* pPromise) { QFileInfo coverArtInfo(coverArtAbsolutePath); QString coverArtName = coverArtInfo.completeBaseName(); QString coverArtFolder = coverArtInfo.absolutePath(); @@ -632,10 +632,10 @@ void DlgTagFetcher::slotWorkerAskOverwrite(const QString& coverArtAbsolutePath, switch (overwrite_box.exec()) { case QMessageBox::No: - promise->set_value(CoverArtCopyWorker::OverwriteAnswer::Cancel); + pPromise->set_value(CoverArtCopyWorker::OverwriteAnswer::Cancel); return; case QMessageBox::Yes: - promise->set_value(CoverArtCopyWorker::OverwriteAnswer::Overwrite); + pPromise->set_value(CoverArtCopyWorker::OverwriteAnswer::Overwrite); return; } } diff --git a/src/library/dlgtagfetcher.h b/src/library/dlgtagfetcher.h index 750c3232c31..7d7da00dc85 100644 --- a/src/library/dlgtagfetcher.h +++ b/src/library/dlgtagfetcher.h @@ -29,7 +29,7 @@ class DlgTagFetcher : public QDialog, public Ui::DlgTagFetcher { void init(); public slots: - void loadTrack(const TrackPointer& track); + void loadTrack(const TrackPointer& pTrack); void loadTrack(const QModelIndex& index); signals: @@ -64,15 +64,15 @@ class DlgTagFetcher : public QDialog, public Ui::DlgTagFetcher { void slotCoverArtLinkNotFound(); void slotWorkerStarted(); void slotWorkerAskOverwrite(const QString& coverArtAbsolutePath, - std::promise* promise); + std::promise* pPromise); void slotWorkerCoverArtCopyFailed(const QString& errorMessage); void slotWorkerCoverArtUpdated(const CoverInfoRelative& coverInfo); void slotWorkerFinished(); private: // Called on population or changed via buttons Next&Prev. - void loadTrackInternal(const TrackPointer& track); - void addDivider(const QString& text, QTreeWidget* parent) const; + void loadTrackInternal(const TrackPointer& pTrack); + void addDivider(const QString& text, QTreeWidget* pParent) const; void getCoverArt(const QString& url); void loadCurrentTrackCover(); @@ -84,7 +84,7 @@ class DlgTagFetcher : public QDialog, public Ui::DlgTagFetcher { bool m_isCoverArtCopyWorkerRunning; - TrackPointer m_track; + TrackPointer m_pTrack; QModelIndex m_currentTrackIndex; @@ -106,5 +106,5 @@ class DlgTagFetcher : public QDialog, public Ui::DlgTagFetcher { QByteArray m_fetchedCoverArtByteArrays; - QScopedPointer m_worker; + QScopedPointer m_pWorker; };