Clementine-audio-player-Mac.../src/musicbrainz/tagfetcher.cpp

131 lines
3.7 KiB
C++

/* This file is part of Clementine.
Copyright 2010, David Sansome <me@davidsansome.com>
Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Clementine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tagfetcher.h"
#include "acoustidclient.h"
#include "chromaprinter.h"
#include "musicbrainzclient.h"
#include "core/timeconstants.h"
#include <QFuture>
#include <QFutureWatcher>
#include <QUrl>
#include <QtConcurrentMap>
TagFetcher::TagFetcher(QObject* parent)
: QObject(parent),
fingerprint_watcher_(nullptr),
acoustid_client_(new AcoustidClient(this)),
musicbrainz_client_(new MusicBrainzClient(this)) {
connect(acoustid_client_, SIGNAL(Finished(int, QStringList)),
SLOT(PuidsFound(int, QStringList)));
connect(musicbrainz_client_,
SIGNAL(Finished(int, MusicBrainzClient::ResultList)),
SLOT(TagsFetched(int, MusicBrainzClient::ResultList)));
}
QString TagFetcher::GetFingerprint(const Song& song) {
return Chromaprinter(song.url().toLocalFile()).CreateFingerprint();
}
void TagFetcher::StartFetch(const SongList& songs) {
Cancel();
songs_ = songs;
QFuture<QString> future = QtConcurrent::mapped(songs_, GetFingerprint);
fingerprint_watcher_ = new QFutureWatcher<QString>(this);
fingerprint_watcher_->setFuture(future);
connect(fingerprint_watcher_, SIGNAL(resultReadyAt(int)),
SLOT(FingerprintFound(int)));
for (const Song& song : songs) {
emit Progress(song, tr("Fingerprinting song"));
}
}
void TagFetcher::Cancel() {
if (fingerprint_watcher_) {
fingerprint_watcher_->cancel();
delete fingerprint_watcher_;
fingerprint_watcher_ = nullptr;
}
acoustid_client_->CancelAll();
musicbrainz_client_->CancelAll();
songs_.clear();
}
void TagFetcher::FingerprintFound(int index) {
QFutureWatcher<QString>* watcher =
reinterpret_cast<QFutureWatcher<QString>*>(sender());
if (!watcher || index >= songs_.count()) {
return;
}
const QString fingerprint = watcher->resultAt(index);
const Song& song = songs_[index];
if (fingerprint.isEmpty()) {
emit ResultAvailable(song, SongList());
return;
}
emit Progress(song, tr("Identifying song"));
acoustid_client_->Start(index, fingerprint,
song.length_nanosec() / kNsecPerMsec);
}
void TagFetcher::PuidsFound(int index, const QStringList& puid_list) {
if (index >= songs_.count()) {
return;
}
const Song& song = songs_[index];
if (puid_list.isEmpty()) {
emit ResultAvailable(song, SongList());
return;
}
emit Progress(song, tr("Downloading metadata"));
musicbrainz_client_->Start(index, puid_list);
}
void TagFetcher::TagsFetched(int index,
const MusicBrainzClient::ResultList& results) {
if (index >= songs_.count()) {
return;
}
const Song& original_song = songs_[index];
SongList songs_guessed;
for (const MusicBrainzClient::Result& result : results) {
Song song;
song.Init(result.title_, result.artist_, result.album_,
result.duration_msec_ * kNsecPerMsec);
song.set_track(result.track_);
song.set_year(result.year_);
songs_guessed << song;
}
emit ResultAvailable(original_song, songs_guessed);
}