7#include "musicbrainzlookup.h"
11#include <musicbrainz5/Query.h>
12#include <musicbrainz5/Medium.h>
13#include <musicbrainz5/Release.h>
14#include <musicbrainz5/ReleaseGroup.h>
15#include <musicbrainz5/Track.h>
16#include <musicbrainz5/Recording.h>
17#include <musicbrainz5/Disc.h>
18#include <musicbrainz5/HTTPFetch.h>
19#include <musicbrainz5/ArtistCredit.h>
20#include <musicbrainz5/Artist.h>
21#include <musicbrainz5/NameCredit.h>
22#include <musicbrainz5/SecondaryType.h>
24#include <QCryptographicHash>
26#include <QRegularExpression>
33 MusicBrainzLookup::MusicBrainzLookup()
38 MusicBrainzLookup::~MusicBrainzLookup()
43 Result MusicBrainzLookup::lookup(
const QString &, uint,
const TrackOffsetList & trackOffsetList )
45 QString discId = calculateDiscId(trackOffsetList);
47 qDebug() <<
"Should lookup " << discId;
49 MusicBrainz5::CQuery Query(
"libkcddb-0.5");
54 MusicBrainz5::CMetadata Metadata=Query.Query(
"discid",discId.
toLatin1().
constData());
56 if (Metadata.Disc() && Metadata.Disc()->ReleaseList())
58 MusicBrainz5::CReleaseList *ReleaseList=Metadata.Disc()->ReleaseList();
59 qDebug() <<
"Found " << ReleaseList->NumItems() <<
" release(s)";
63 for (
int i = 0; i < ReleaseList->NumItems(); i++)
65 MusicBrainz5::CRelease*
Release=ReleaseList->Item(i);
69 MusicBrainz5::CQuery::tParamMap Params;
70 Params[
"inc"]=
"artists labels recordings release-groups url-rels discids artist-credits";
72 std::string ReleaseID=
Release->ID();
74 MusicBrainz5::CMetadata Metadata2=Query.Query(
"release",ReleaseID,
"",Params);
75 if (Metadata2.Release())
77 MusicBrainz5::CRelease *FullRelease=Metadata2.Release();
82 MusicBrainz5::CMediumList MediaList=FullRelease->MediaMatchingDiscID(discId.
toLatin1().
constData());
84 if (MediaList.NumItems() > 0)
91 qDebug() <<
"Found " << MediaList.NumItems() <<
" media item(s)";
93 for (
int i=0; i < MediaList.NumItems(); i++)
95 MusicBrainz5::CMedium* Medium= MediaList.Item(i);
111 if (FullRelease->MediumList()->NumItems() > 1)
112 title =
i18n(
"%1 (disc %2)", title, Medium->Position());
114 info.set(Title, title);
115 info.set(Artist, artistFromCreditList(FullRelease->ArtistCredit()));
120 if (
const auto yearMatch = yearRe.match(date); yearMatch.hasMatch())
122 QString yearString = yearMatch.captured(1);
124 year=yearString.
toInt(&ok);
128 info.set(Year, year);
130 MusicBrainz5::CTrackList *TrackList=Medium->TrackList();
133 for (
int i=0; i < TrackList->NumItems(); i++)
135 MusicBrainz5::CTrack* Track=TrackList->Item(i);
136 MusicBrainz5::CRecording *Recording=Track->Recording();
138 TrackInfo& track = info.track(i);
146 if(Recording && Track->ArtistCredit() ==
nullptr)
147 track.set(Artist, artistFromCreditList(Recording->ArtistCredit()));
149 track.set(Artist, artistFromCreditList(Track->ArtistCredit()));
151 if(Recording && Track->Title().empty())
166 catch (MusicBrainz5::CConnectionError& Error)
168 qDebug() <<
"Connection Exception: '" <<
Error.what() <<
"'";
169 qDebug() <<
"LastResult: " << Query.LastResult();
170 qDebug() <<
"LastHTTPCode: " << Query.LastHTTPCode();
171 qDebug() <<
"LastErrorMessage: " <<
QString::fromUtf8(Query.LastErrorMessage().c_str());
176 catch (MusicBrainz5::CTimeoutError& Error)
178 qDebug() <<
"Timeout Exception: '" <<
Error.what() <<
"'";
179 qDebug() <<
"LastResult: " << Query.LastResult();
180 qDebug() <<
"LastHTTPCode: " << Query.LastHTTPCode();
181 qDebug() <<
"LastErrorMessage: " <<
QString::fromUtf8(Query.LastErrorMessage().c_str());
186 catch (MusicBrainz5::CAuthenticationError& Error)
188 qDebug() <<
"Authentication Exception: '" <<
Error.what() <<
"'";
189 qDebug() <<
"LastResult: " << Query.LastResult();
190 qDebug() <<
"LastHTTPCode: " << Query.LastHTTPCode();
191 qDebug() <<
"LastErrorMessage: " <<
QString::fromUtf8(Query.LastErrorMessage().c_str());
196 catch (MusicBrainz5::CFetchError& Error)
198 qDebug() <<
"Fetch Exception: '" <<
Error.what() <<
"'";
199 qDebug() <<
"LastResult: " << Query.LastResult();
200 qDebug() <<
"LastHTTPCode: " << Query.LastHTTPCode();
201 qDebug() <<
"LastErrorMessage: " <<
QString::fromUtf8(Query.LastErrorMessage().c_str());
206 catch (MusicBrainz5::CRequestError& Error)
208 qDebug() <<
"Request Exception: '" <<
Error.what() <<
"'";
209 qDebug() <<
"LastResult: " << Query.LastResult();
210 qDebug() <<
"LastHTTPCode: " << Query.LastHTTPCode();
211 qDebug() <<
"LastErrorMessage: " <<
QString::fromUtf8(Query.LastErrorMessage().c_str());
216 catch (MusicBrainz5::CResourceNotFoundError& Error)
218 qDebug() <<
"ResourceNotFound Exception: '" <<
Error.what() <<
"'";
219 qDebug() <<
"LastResult: " << Query.LastResult();
220 qDebug() <<
"LastHTTPCode: " << Query.LastHTTPCode();
221 qDebug() <<
"LastErrorMessage: " <<
QString::fromUtf8(Query.LastErrorMessage().c_str());
228 qDebug() <<
"No record found";
229 return NoRecordFound;
232 qDebug() <<
"Query succeeded :-)";
237 QString MusicBrainzLookup::calculateDiscId(
const TrackOffsetList & trackOffsetList )
241 int numTracks = trackOffsetList.
count()-1;
248 int lastTrack = numTracks;
250 sprintf(temp,
"%02X", firstTrack);
251#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
254 sha.addData(temp, strlen(temp));
257 sprintf(temp,
"%02X", lastTrack);
258#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
261 sha.addData(temp, strlen(temp));
264 for(
int i = 0; i < 100; i++)
268 offset = trackOffsetList[numTracks];
269 else if (i <= numTracks)
270 offset = trackOffsetList[i-1];
274 sprintf(temp,
"%08lX", offset);
275#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
278 sha.addData(temp, strlen(temp));
290 CDInfoList MusicBrainzLookup::cacheFiles(
const TrackOffsetList &offsetList,
const Config& c )
294 QString discid = calculateDiscId(offsetList);
297 cddbCacheDir != cddbCacheDirs.
constEnd(); ++cddbCacheDir)
306 qDebug() <<
"Cache files found: " << files.
count();
313#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
314 ts.setCodec(
"UTF-8");
316 QString cddbData = ts.readAll();
326 qDebug() <<
"Could not read file: " << f.fileName();
333 QString MusicBrainzLookup::artistFromCreditList(MusicBrainz5::CArtistCredit * artistCredit )
338 MusicBrainz5::CNameCreditList *ArtistList=artistCredit->NameCreditList();
342 for (
int i=0; i < ArtistList->NumItems(); i++)
344 MusicBrainz5::CNameCredit* Name=ArtistList->Item(i);
345 MusicBrainz5::CArtist*
Artist = Name->Artist();
347 if (!Name->Name().empty())
355 qDebug() <<
"Artist:" << artistName;
363#include "moc_musicbrainzlookup.cpp"
QString i18n(const char *text, const TYPE &arg...)
KIOCORE_EXPORT QString dir(const QString &fileClass)
const char * constData() const const
QByteArray toBase64(Base64Options options) const const
const_iterator constBegin() const const
const_iterator constEnd() const const
qsizetype count() const const
bool isEmpty() const const
qsizetype count() const const
QString & append(QChar ch)
QString fromLatin1(QByteArrayView str)
QString fromUtf8(QByteArrayView str)
QString number(double n, char format, int precision)
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
int toInt(bool *ok, int base) const const
QByteArray toLatin1() const const