Search discogs for covers

This commit is contained in:
craig.p.drummond
2013-04-11 19:36:12 +00:00
parent 8436eb205c
commit 4bfe360e27
3 changed files with 129 additions and 107 deletions

View File

@@ -25,7 +25,7 @@
and cache items deleted.
13. Move group warning to last stage of intial settings wizard.
14. Basic cover fetching dialog, allowing to change downloaded cover. Currently
only Last.fm and Google are used to find images.
Last.fm, Google, and Discogs are used to find images.
15. Use cache by default for devices.
16. GZip compress cache files.
17. Save remote device library settings on remote device.

View File

@@ -31,6 +31,7 @@
#include "utils.h"
#include "spinner.h"
#include "icon.h"
#include "qjson/parser.h"
#include <QVBoxLayout>
#include <QLabel>
#include <QListWidget>
@@ -79,9 +80,9 @@ public:
Type_Existing,
Type_Local,
Type_LastFm,
Type_Google
// Type_Yahoo,
// Type_Discogs
Type_Google,
// Type_Yahoo
Type_Discogs
};
CoverItem(const QString &u, const QString &tu, QListWidget *parent)
@@ -187,24 +188,23 @@ private:
// Type type() const { return Type_Yahoo; }
//};
//class DiscogsCover : public CoverItem
//{
//public:
// DiscogsCover(const QString &u, const QString &tu, const QImage &img, int w, int h, QListWidget *parent)
// : CoverItem(u, tu, parent)
// , width(w)
// , height(h) {
// setImage(img);
// setText(i18nc("Discogs\nwidth x height", "Discogs\n%1 x %2").arg(width).arg(height));
// }
class DiscogsCover : public CoverItem
{
public:
DiscogsCover(const QString &u, const QString &tu, const QImage &img, int w, int h, QListWidget *parent)
: CoverItem(u, tu, parent)
, width(w)
, height(h) {
setImage(img);
setText(i18nc("Discogs\nwidth x height", "Discogs\n%1 x %2").arg(width).arg(height));
}
// quint32 key() const { return width*height; }
// Type type() const { return Type_Discogs; }
//private:
// int width;
// int height;
//};
quint32 key() const { return width*height; }
Type type() const { return Type_Discogs; }
private:
int width;
int height;
};
class ExistingCover : public CoverItem
{
@@ -433,9 +433,8 @@ static const char * constTypeProperty="type";
static const char * constLastFmHost="ws.audioscrobbler.com";
static const char * constGoogleHost="images.google.com";
//static const char * constYahooHost="boss.yahooapis.com";
//static const char * constDiscogsHost="www.discogs.com";
static const char * constDiscogsHost="api.discogs.com";
//static const char * constYahooApiKey=0;
//static const char * constDiscogsApiKey=0;
void CoverDialog::queryJobFinished()
{
@@ -446,17 +445,17 @@ void CoverDialog::queryJobFinished()
currentQuery.remove(reply);
if(QNetworkReply::NoError==reply->error()) {
QString resp=QString::fromUtf8(reply->readAll());
QByteArray resp=reply->readAll();
QString host=reply->property(constHostProperty).toString();
if (constLastFmHost==host) {
parseLstFmQueryResponse(resp);
} else if (constGoogleHost==host) {
parseGoogleQueryResponse(resp);
} else if (constDiscogsHost==host) {
parseDiscogsQueryResponse(resp);
}
// else if (constYahooHost==host) {
// parseYahooQueryResponse(resp);
// } else if (constDiscogsHost==host) {
// parseDiscogsQueryResponse(resp);
// }
}
reply->deleteLater();
@@ -521,7 +520,7 @@ void CoverDialog::downloadJobFinished()
if(QNetworkReply::NoError==reply->error()) {
QString url=reply->url().toString();
QByteArray data=reply->readAll();
FileType fileType=url.endsWith(".jpg") ? FT_Jpg : (url.endsWith(".png") ? FT_Png : FT_Other);
FileType fileType=url.endsWith(".jpg") || url.endsWith(".jpeg") ? FT_Jpg : (url.endsWith(".png") ? FT_Png : FT_Other);
QImage img=QImage::fromData(data, FT_Jpg==fileType ? "JPG" : (FT_Png==fileType ? "PNG" : 0));
if (!img.isNull()) {
QString host=reply->property(constHostProperty).toString();
@@ -567,12 +566,12 @@ void CoverDialog::downloadJobFinished()
item=new GoogleCover(reply->property(constLargeProperty).toString(), url, img,
reply->property(constWidthProperty).toInt(), reply->property(constHeightProperty).toInt(),
reply->property(constSizeProperty).toInt(), list);
} else if (constDiscogsHost==host) {
item=new DiscogsCover(reply->property(constLargeProperty).toString(), url, img,
reply->property(constWidthProperty).toInt(), reply->property(constHeightProperty).toInt(), list);
}
// else if (constYahooHost==host) {
// item=new YahooCover(reply->property(constLargeProperty).toString(), url, img, list);
// } else if (constDiscogsHost==host) {
// item=new DiscogsCover(reply->property(constLargeProperty).toString(), url, img,
// reply->property(constWidthProperty).toInt(), reply->property(constHeightProperty).toInt(), list);
// }
if (item) {
insertItem(item);
@@ -670,13 +669,12 @@ void CoverDialog::sendQuery()
}
spinner->start();
cancelButton->setEnabled(true);
currentQueryString=fixedQuery;
#if QT_VERSION < 0x050000
QUrl lastFmUrl;
#if QT_VERSION < 0x050000
QUrl &lastFmQuery=lastFmUrl;
#else
QUrl lastFmUrl;
QUrlQuery lastFmQuery;
#endif
lastFmUrl.setScheme("http");
@@ -692,11 +690,10 @@ void CoverDialog::sendQuery()
#endif
sendQueryRequest(lastFmUrl);
#if QT_VERSION < 0x050000
QUrl googleUrl;
#if QT_VERSION < 0x050000
QUrl &googleQuery=googleUrl;
#else
QUrl googleUrl;
QUrlQuery googleQuery;
#endif
googleUrl.setScheme("http");
@@ -721,16 +718,24 @@ void CoverDialog::sendQuery()
// yahoo.addQueryItem("format", "xml");
// sendQueryRequest(yahoo);
// QUrl discogs;
// discogs.setScheme("http");
// discogs.setHost(constDiscogsHost);
// discogs.setPath("/search");
// discogs.addQueryItem("api_key", constDiscogsApiKey);
// discogs.addQueryItem("page", QString::number(page + 1));
// discogs.addQueryItem("type", "all");
// discogs.addQueryItem("q", fixedQuery);
// discogs.addQueryItem("f", "xml");
// sendQueryRequest(discogs);
QUrl discogsUrl;
#if QT_VERSION < 0x050000
QUrl &discogsQuery=discogsUrl;
#else
QUrlQuery discogsQuery;
#endif
discogsUrl.setScheme("http");
discogsUrl.setHost(constDiscogsHost);
discogsUrl.setPath("/search");
discogsQuery.addQueryItem("page", QString::number(page + 1));
discogsQuery.addQueryItem("per_page", QString::number(20));
discogsQuery.addQueryItem("type", "release");
discogsQuery.addQueryItem("q", fixedQuery);
discogsQuery.addQueryItem("f", "json");
#if QT_VERSION >= 0x050000
discogsUrl.setQuery(discogsQuery);
#endif
sendQueryRequest(discogsUrl);
}
void CoverDialog::checkStatus()
@@ -884,7 +889,7 @@ QNetworkReply * CoverDialog::downloadImage(const QString &url, DownloadType dlTy
}
typedef QMap<QString, QString> SizeMap;
void CoverDialog::parseLstFmQueryResponse(const QString &resp)
void CoverDialog::parseLstFmQueryResponse(const QByteArray &resp)
{
bool inSection=false;
QXmlStreamReader doc(resp);
@@ -946,7 +951,7 @@ void CoverDialog::parseLstFmQueryResponse(const QString &resp)
}
}
void CoverDialog::parseGoogleQueryResponse(const QString &resp)
void CoverDialog::parseGoogleQueryResponse(const QByteArray &resp)
{
// Code based on Audex CDDA Extractor
QRegExp rx("<a\\shref=\"(\\/imgres\\?imgurl=[^\"]+)\">[\\s\\n]*<img[^>]+src=\"([^\"]+)\"");
@@ -954,7 +959,7 @@ void CoverDialog::parseGoogleQueryResponse(const QString &resp)
rx.setMinimal(true);
int pos = 0;
QString xml(resp);
QString xml(QString::fromUtf8(resp));
QString html = xml.replace(QLatin1String("&amp;"), QLatin1String("&"));
while (-1!=(pos=rx.indexIn(html, pos))) {
@@ -1040,63 +1045,80 @@ void CoverDialog::parseGoogleQueryResponse(const QString &resp)
// }
//}
//void CoverDialog::parseDiscogsQueryResponse(const QString &resp)
//{
// QXmlStreamReader xml(resp);
// while (!xml.atEnd() && !xml.hasError()) {
// xml.readNext();
// if(!xml.isStartElement() || "release"!=xml.name()) {
// continue;
// }
// const QString releaseId = xml.attributes().value("id").toString();
// while(!xml.atEnd() && !xml.hasError()) {
// xml.readNext();
// const QStringRef &n = xml.name();
// if(xml.isEndElement() && "release"==n) {
// break;
// }
// if(!xml.isStartElement()) {
// continue;
// }
// if ("images"==n) {
// while (!xml.atEnd() && !xml.hasError()) {
// xml.readNext();
// if (xml.isEndElement() && "images"==xml.name()) {
// break;
// }
// if (!xml.isStartElement()) {
// continue;
// }
// if ("image"==xml.name()) {
// const QXmlStreamAttributes &attr = xml.attributes();
// QString thumbUrl(attr.value("uri150").toString());
// QString largeUrl(attr.value("uri").toString());
// if (!thumbUrl.isEmpty() && !largeUrl.isEmpty()) {
// QNetworkReply *j=downloadImage(thumbUrl, DL_Thumbnail);
// if (j) {
// j->setProperty(constHostProperty, constDiscogsHost);
// j->setProperty(constLargeProperty, largeUrl);
// j->setProperty(constThumbProperty, thumbUrl);
// j->setProperty(constWidthProperty, attr.value("width").toString().toInt());
// j->setProperty(constHeightProperty, attr.value("height").toString().toInt());
void CoverDialog::parseDiscogsQueryResponse(const QByteArray &resp)
{
QJson::Parser parser;
bool ok=false;
QVariantMap parsed=parser.parse(resp, &ok).toMap();
if (ok && parsed.contains("resp")) {
QVariantMap response=parsed["resp"].toMap();
if (response.contains("search")) {
QVariantMap search=response["search"].toMap();
if (search.contains("searchresults")) {
QVariantMap searchresults=search["searchresults"].toMap();
if (searchresults.contains("results")) {
QVariantList results=searchresults["results"].toList();
foreach (const QVariant &r, results) {
QVariantMap rm=r.toMap();
if (rm.contains("uri")) {
QStringList parts=rm["uri"].toString().split("/", QString::SkipEmptyParts);
if (!parts.isEmpty()) {
QUrl discogsUrl;
#if QT_VERSION < 0x050000
QUrl &discogsQuery=discogsUrl;
#else
QUrlQuery discogsQuery;
#endif
discogsUrl.setScheme("http");
discogsUrl.setHost(constDiscogsHost);
discogsUrl.setPath("/release/"+parts.last());
discogsQuery.addQueryItem("f", "json");
#if QT_VERSION >= 0x050000
discogsUrl.setQuery(discogsQuery);
#endif
sendQueryRequest(discogsUrl);
}
}
// if (rm.contains("thumb")) {
// QString thumbUrl=rm["thumb"].toString();
// if (thumbUrl.contains("/image/R-150-")) {
// QString largeUrl=thumbUrl.replace("image/R-150-", "/image/R-");
// QNetworkReply *j=downloadImage(thumbUrl, DL_Thumbnail);
// if (j) {
// j->setProperty(constHostProperty, constDiscogsHost);
// j->setProperty(constLargeProperty, largeUrl);
// j->setProperty(constThumbProperty, thumbUrl);
// }
// }
// }
// } else {
// xml.skipCurrentElement();
// }
// }
// }
// else
// xml.skipCurrentElement();
// }
// }
//}
}
}
}
} else if (response.contains("release")) {
QVariantMap release=response["release"].toMap();
if (release.contains("images")) {
QVariantList images=release["images"].toList();
foreach (const QVariant &i, images) {
QVariantMap im=i.toMap();
if (im.contains("uri") && im.contains("uri150")) {
QString thumbUrl=im["uri150"].toString();
QString largeUrl=im["uri"].toString();
if (!thumbUrl.isEmpty() && !largeUrl.isEmpty()) {
QNetworkReply *j=downloadImage(thumbUrl, DL_Thumbnail);
if (j) {
j->setProperty(constHostProperty, constDiscogsHost);
j->setProperty(constLargeProperty, largeUrl);
j->setProperty(constThumbProperty, thumbUrl);
j->setProperty(constWidthProperty, im["width"].toString().toInt());
j->setProperty(constHeightProperty, im["height"].toString().toInt());
}
}
}
}
}
}
}
}
void CoverDialog::slotButtonClicked(int button)
{

View File

@@ -122,10 +122,10 @@ private:
QNetworkReply * downloadImage(const QString &url, DownloadType dlType);
void clearTempFiles();
void sendQueryRequest(const QUrl &url);
void parseLstFmQueryResponse(const QString &resp);
void parseGoogleQueryResponse(const QString &resp);
// void parseYahooQueryResponse(const QString &resp);
// void parseDiscogsQueryResponse(const QString &resp);
void parseLstFmQueryResponse(const QByteArray &resp);
void parseGoogleQueryResponse(const QByteArray &resp);
// void parseYahooQueryResponse(const QByteArray &resp);
void parseDiscogsQueryResponse(const QByteArray &resp);
void slotButtonClicked(int button);
bool saveCover(const QString &src, const QImage &img);
void dragEnterEvent(QDragEnterEvent *event);