/* This file is part of Clementine. Copyright 2010, David Sansome 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 . */ #include "tagfetcher.h" #include #include #include #include #include "acoustidclient.h" #include "chromaprinter.h" #include "core/timeconstants.h" #include "musicbrainzclient.h" 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 future = QtConcurrent::mapped(songs_, GetFingerprint); fingerprint_watcher_ = new QFutureWatcher(this); connect(fingerprint_watcher_, SIGNAL(resultReadyAt(int)), SLOT(FingerprintFound(int))); fingerprint_watcher_->setFuture(future); 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* watcher = reinterpret_cast*>(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); }