summaryrefslogtreecommitdiffstats
path: root/src/musicbrainz/tagfetcher.cpp
blob: 9a7320f15831470abf79f8439829905bd6088555 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*****************************************************************************
 *  Copyright © 2012 John Maguire <john.maguire@gmail.com>                   *
 *                   David Sansome <me@davidsansome.com>                     *
 *  This work is free. You can redistribute it and/or modify it under the    *
 *  terms of the Do What The Fuck You Want To Public License, Version 2,     *
 *  as published by Sam Hocevar.                                             *
 *  See http://www.wtfpl.net/ for more details.                              *
 *****************************************************************************/

#include <QFuture>
#include <QUrl>
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
#include <QtConcurrent>
#endif
#include <QtConcurrentMap>

#include "musicbrainz/tagfetcher.h"
#include "musicbrainz/chromaprinter.h"
#include "musicbrainz/musicbrainzclient.h"

TagFetcher::TagFetcher(QObject* parent)
          : QObject(parent),
            m_pFingerprintWatcher(NULL),
            m_AcoustidClient(this),
            m_MusicbrainzClient(this) {
    connect(&m_AcoustidClient, SIGNAL(finished(int,QString)),
            this, SLOT(mbidFound(int,QString)));
    connect(&m_MusicbrainzClient, SIGNAL(finished(int,MusicBrainzClient::ResultList)),
            this, SLOT(tagsFetched(int,MusicBrainzClient::ResultList)));
    connect(&m_AcoustidClient, SIGNAL(networkError(int, QString)),
            this, SIGNAL(networkError(int, QString)));
    connect(&m_MusicbrainzClient, SIGNAL(networkError(int, QString)),
            this, SIGNAL(networkError(int, QString)));
}

QString TagFetcher::getFingerprint(const TrackPointer tio) {
    return ChromaPrinter(NULL).getFingerprint(tio);
}

void TagFetcher::startFetch(const TrackPointer track) {
    cancel();
    // qDebug() << "start to fetch track metadata";
    QList<TrackPointer> tracks;
    tracks.append(track);
    m_tracks = tracks;

    QFuture<QString> future = QtConcurrent::mapped(m_tracks, getFingerprint);
    m_pFingerprintWatcher = new QFutureWatcher<QString>(this);
    m_pFingerprintWatcher->setFuture(future);
    connect(m_pFingerprintWatcher, SIGNAL(resultReadyAt(int)),
            SLOT(fingerprintFound(int)));

    foreach (const TrackPointer ptrack, m_tracks) {
        emit(fetchProgress(tr("Fingerprinting track")));
    }
}

void TagFetcher::cancel() {
    // qDebug()<< "Cancel tagfetching";
    if (m_pFingerprintWatcher) {
        m_pFingerprintWatcher->cancel();

        delete m_pFingerprintWatcher;
        m_pFingerprintWatcher = NULL;
    }

    m_AcoustidClient.cancelAll();
    m_MusicbrainzClient.cancelAll();
    m_tracks.clear();
}

void TagFetcher::fingerprintFound(int index) {
    QFutureWatcher<QString>* watcher = reinterpret_cast<QFutureWatcher<QString>*>(sender());
    if (!watcher || index >= m_tracks.count()) {
        return;
    }

    const QString fingerprint = watcher->resultAt(index);
    const TrackPointer ptrack = m_tracks[index];

    if (fingerprint.isEmpty()) {
        emit(resultAvailable(ptrack, QList<TrackPointer>()));
        return;
    }

    emit(fetchProgress(tr("Identifying track")));
    // qDebug() << "start to look up the MBID";
    m_AcoustidClient.start(index, fingerprint, ptrack->getDurationInt());
}

void TagFetcher::mbidFound(int index, const QString& mbid) {
    if (index >= m_tracks.count()) {
        return;
    }

    const TrackPointer pTrack = m_tracks[index];

    if (mbid.isEmpty()) {
        emit(resultAvailable(pTrack, QList<TrackPointer>()));
        return;
    }

    emit fetchProgress(tr("Downloading Metadata"));
    //qDebug() << "start to fetch tags from MB";
    m_MusicbrainzClient.start(index, mbid);
}

void TagFetcher::tagsFetched(int index, const MusicBrainzClient::ResultList& results) {
    if (index >= m_tracks.count()) {
        return;
    }
    // qDebug() << "Tagfetcher got musicbrainz results and now parses them";
    const TrackPointer originalTrack = m_tracks[index];
    QList<TrackPointer> tracksGuessed;
    foreach (const MusicBrainzClient::Result& result, results) {
        TrackPointer track(
                Track::newTemporary(
                        originalTrack->getFileInfo(),
                        originalTrack->getSecurityToken()));
        track->setTitle(result.m_title);
        track->setArtist(result.m_artist);
        track->setAlbum(result.m_album);
        track->setDuration(result.m_duration);
        track->setTrackNumber(QString::number(result.m_track));
        track->setYear(QString::number(result.m_year));
        tracksGuessed << track;
    }
    emit(resultAvailable(originalTrack, tracksGuessed));
}