Keep track of song -> cover filename mapping

This commit is contained in:
craig.p.drummond
2013-02-07 18:22:10 +00:00
committed by craig.p.drummond
parent 5677fd26a9
commit aed8d03e9a
4 changed files with 100 additions and 46 deletions

View File

@@ -637,7 +637,7 @@ void MtpConnection::putSong(const Song &s, bool fixVa, const DeviceOptions &opts
}
if (album) {
Covers::Image image=Covers::getImage(s);
Covers::Image image=Covers::self()->getImage(s);
if (!image.img.isNull()) {
// First check if album already has cover...
if (!albumsWithCovers.contains(album) && getCover(album).isNull()) {

View File

@@ -400,7 +400,7 @@ CoverDialog::~CoverDialog()
void CoverDialog::show(const Song &s)
{
song=s;
Covers::Image img=Covers::getImage(song);
Covers::Image img=Covers::self()->getImage(song);
if (!img.fileName.isEmpty() && !QFileInfo(img.fileName).isWritable()) {
MessageBox::error(parentWidget(), i18n("<p>A cover already exists for this album, and the file is not writeable.<p></p><i>%1</i></p>").arg(img.fileName));

View File

@@ -135,6 +135,16 @@ static QString save(const QString &mimeType, const QString &extension, const QSt
return QString();
}
static inline QString albumKey(const Song &s)
{
return "{"+s.albumArtist()+"}{"+s.album+"}";
}
static inline QString artistKey(const Song &s)
{
return "{"+s.albumArtist()+"}";
}
QString Covers::encodeName(QString name)
{
name.replace("/", "_");
@@ -171,36 +181,30 @@ static QString kdeHome()
}
#endif
struct AppCover
{
QImage img;
QString filename;
};
static AppCover otherAppCover(const Covers::Job &job)
static Covers::Image otherAppCover(const Covers::Job &job)
{
#ifdef ENABLE_KDE_SUPPORT
QString kdeDir=KGlobal::dirs()->localkdedir();
#else
QString kdeDir=kdeHome();
#endif
AppCover app;
app.filename=kdeDir+QLatin1String("/share/apps/amarok/albumcovers/large/")+
Covers::Image app;
app.fileName=kdeDir+QLatin1String("/share/apps/amarok/albumcovers/large/")+
QCryptographicHash::hash(job.song.albumArtist().toLower().toLocal8Bit()+job.song.album.toLower().toLocal8Bit(),
QCryptographicHash::Md5).toHex();
app.img=QImage(app.filename);
app.img=QImage(app.fileName);
if (app.img.isNull()) {
app.filename=xdgConfig()+QLatin1String("/Clementine/albumcovers/")+
app.fileName=xdgConfig()+QLatin1String("/Clementine/albumcovers/")+
QCryptographicHash::hash(job.song.albumArtist().toLower().toUtf8()+job.song.album.toLower().toUtf8(),
QCryptographicHash::Sha1).toHex()+QLatin1String(".jpg");
app.img=QImage(app.filename);
app.img=QImage(app.fileName);
}
if (!app.img.isNull() && saveInMpdDir && canSaveTo(job.dir)) {
QFile f(app.filename);
QFile f(app.fileName);
if (f.open(QIODevice::ReadOnly)) {
QByteArray raw=f.readAll();
if (!raw.isEmpty()) {
@@ -212,7 +216,7 @@ static AppCover otherAppCover(const Covers::Job &job)
}
savedName=save(mimeType, mimeType.isEmpty() ? constExtensions.at(0) : mimeType, job.dir+coverName, app.img, raw);
if (!savedName.isEmpty()) {
app.filename=savedName;
app.fileName=savedName;
}
}
}
@@ -358,8 +362,6 @@ static inline QString cacheKey(const Song &song, int size)
return song.albumArtist()+QChar(':')+song.album+QChar(':')+QChar(':')+QString::number(size);
}
static QSet<int> cacheSizes;
QPixmap * Covers::get(const Song &song, int size)
{
if (song.isUnknown()) {
@@ -424,8 +426,18 @@ void Covers::clearCache(const Song &song, const QImage &img, bool dummyEntriesOn
Covers::Image Covers::getImage(const Song &song)
{
QString songFile=song.file;
bool isArtistImage=isRequestingArtistImage(song);
QString prevFileName=getFilename(song, isArtistImage);
if (!prevFileName.isEmpty()) {
QImage img(prevFileName);
if (!img.isNull()) {
return Image(img, prevFileName);
}
}
QString songFile=song.file;
QString dirName;
bool haveAbsPath=song.file.startsWith('/');
@@ -433,7 +445,7 @@ Covers::Image Covers::getImage(const Song &song)
QUrl u(songFile);
songFile=u.hasQueryItem("file") ? u.queryItemValue("file") : QString();
}
if (!songFile.isEmpty() && ! song.file.startsWith(("http:/")) &&
if (!songFile.isEmpty() && !song.file.startsWith(("http:/")) &&
(haveAbsPath || (!MPDConnection::self()->getDetails().dir.isEmpty() && !MPDConnection::self()->getDetails().dir.startsWith(QLatin1String("http://")) ) ) ) {
dirName=songFile.endsWith('/') ? (haveAbsPath ? QString() : MPDConnection::self()->getDetails().dir)+songFile
: Utils::getDir((haveAbsPath ? QString() : MPDConnection::self()->getDetails().dir)+songFile);
@@ -445,7 +457,9 @@ Covers::Image Covers::getImage(const Song &song)
QImage img(dirName+fileName);
if (!img.isNull()) {
return Image(img, dirName+fileName);
Image i(img, dirName+fileName);
gotArtistImage(song, i, false);
return i;
}
}
}
@@ -477,7 +491,9 @@ Covers::Image Covers::getImage(const Song &song)
QImage img(dirName+fileName);
if (!img.isNull()) {
return Image(img, dirName+fileName);
Image i(img, dirName+fileName);
gotAlbumCover(song, i, false);
return i;
}
}
}
@@ -497,7 +513,9 @@ Covers::Image Covers::getImage(const Song &song)
QImage img(dirName+fileName);
if (!img.isNull()) {
return Image(img, dirName+fileName);
Image i(img, dirName+fileName);
gotAlbumCover(song, i, false);
return i;
}
}
}
@@ -511,7 +529,9 @@ Covers::Image Covers::getImage(const Song &song)
if (QFile::exists(dir+artist+ext)) {
QImage img(dir+artist+ext);
if (!img.isNull()) {
return Image(img, dir+artist+ext);
Image i(img, dir+artist+ext);
gotArtistImage(song, i, false);
return i;
}
}
}
@@ -523,7 +543,9 @@ Covers::Image Covers::getImage(const Song &song)
if (QFile::exists(dir+album+ext)) {
QImage img(dir+album+ext);
if (!img.isNull()) {
return Image(img, dir+album+ext);
Image i(img, dir+album+ext);
gotAlbumCover(song, i, false);
return i;
}
}
}
@@ -532,9 +554,10 @@ Covers::Image Covers::getImage(const Song &song)
#if !defined Q_OS_WIN
// See if amarok, or clementine, has it...
AppCover app=otherAppCover(job);
Image app=otherAppCover(job);
if (!app.img.isNull()) {
return Image(app.img, app.filename);
gotAlbumCover(song, app, false);
return app;
}
#endif
}
@@ -817,8 +840,7 @@ void Covers::lastFmCallFinished()
#if defined Q_OS_WIN
emit cover(job.song, QImage(), QString());
#else
AppCover app=otherAppCover(job);
emit cover(job.song, app.img, app.filename);
gotAlbumCover(job.song, otherAppCover(job));
#endif
}
}
@@ -839,41 +861,40 @@ void Covers::jobFinished()
if (it!=end) {
QByteArray data=QNetworkReply::NoError==reply->error() ? reply->readAll() : QByteArray();
QString url=reply->url().toString();
QImage img = data.isEmpty() ? QImage() : QImage::fromData(data, url.endsWith(".jpg") ? "JPG" : (url.endsWith(".png") ? "PNG" : 0));
QString fileName;
Image img;
img.img= data.isEmpty() ? QImage() : QImage::fromData(data, url.endsWith(".jpg") ? "JPG" : (url.endsWith(".png") ? "PNG" : 0));
Job job=it.value();
if (!img.isNull() && img.size().width()<32) {
img = QImage();
if (!img.img.isNull() && img.img.size().width()<32) {
img.img = QImage();
}
jobs.remove(it.key());
if (img.isNull() && JobLastFm!=job.type && JobOnline) {
if (img.img.isNull() && JobLastFm!=job.type && JobOnline) {
if (JobHttpJpg==job.type) {
downloadViaHttp(job, JobHttpPng);
} else {
downloadViaLastFm(job);
}
} else {
if (!img.isNull()) {
if (img.size().width()>constMaxSize.width() || img.size().height()>constMaxSize.height()) {
img=img.scaled(constMaxSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
if (!img.img.isNull()) {
if (img.img.size().width()>constMaxSize.width() || img.img.size().height()>constMaxSize.height()) {
img.img=img.img.scaled(constMaxSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
fileName=saveImg(job, img, data);
clearCache(job.song, img, true);
img.fileName=saveImg(job, img.img, data);
clearCache(job.song, img.img, true);
}
if (job.isArtist) {
emit artistImage(job.song, img);
} else if (img.isNull()) {
gotArtistImage(job.song, img);
} else if (img.img.isNull()) {
#if defined Q_OS_WIN
emit cover(job.song, QImage(), QString());
#else
AppCover app=otherAppCover(job);
emit cover(job.song, app.img, app.filename);
gotAlbumCover(job.song, otherAppCover(job));
#endif
} else {
emit cover(job.song, img, fileName);
gotAlbumCover(job.song, img);
}
}
}
@@ -952,3 +973,29 @@ QHash<QNetworkReply *, Covers::Job>::Iterator Covers::findJob(const Job &job)
return end;
}
void Covers::gotAlbumCover(const Song &song, const Image &img, bool emitResult)
{
if (!img.img.isNull() && !img.fileName.isEmpty() && !img.fileName.startsWith("http:/")) {
filenames.insert(albumKey(song), img.fileName);
}
if (emitResult) {
emit cover(song, img.img, img.fileName);
}
}
void Covers::gotArtistImage(const Song &song, const Image &img, bool emitResult)
{
if (!img.img.isNull() && !img.fileName.isEmpty() && !img.fileName.startsWith("http:/")) {
filenames.insert(artistKey(song), img.fileName);
}
if (emitResult) {
emit artistImage(song, img.img);
}
}
QString Covers::getFilename(const Song &s, bool isArtist)
{
QMap<QString, QString>::ConstIterator fileIt=filenames.find(isArtist ? artistKey(s) : albumKey(s));
return fileIt==filenames.end() ? QString() : fileIt.value();
}

View File

@@ -26,6 +26,8 @@
#include <QObject>
#include <QHash>
#include <QSet>
#include <QMap>
#include <QCache>
#include <QImage>
#include <QPixmap>
@@ -91,7 +93,7 @@ public:
struct Image
{
Image(const QImage &i, const QString &f)
Image(const QImage &i=QImage(), const QString &f=QString())
: img(i)
, fileName(f) {
}
@@ -115,7 +117,7 @@ public:
void stop();
QPixmap * get(const Song &song, int size);
static Image getImage(const Song &song);
Image getImage(const Song &song);
Image get(const Song &song);
void requestCover(const Song &song, bool urgent=false);
void setSaveInMpdDir(bool s);
@@ -143,10 +145,15 @@ private:
QString saveImg(const Job &job, const QImage &img, const QByteArray &raw);
QHash<QNetworkReply *, Job>::Iterator findJob(const Job &job);
void clearCache(const Song &song, const QImage &img, bool dummyEntriesOnly);
void gotAlbumCover(const Song &song, const Image &img, bool emitResult=true);
void gotArtistImage(const Song &song, const Image &img, bool emitResult=true);
QString getFilename(const Song &s, bool isArtist);
private:
QHash<QNetworkReply *, Job> jobs;
QSet<int> cacheSizes;
QCache<QString, QPixmap> cache;
QMap<QString, QString> filenames;
CoverQueue *queue;
QThread *queueThread;
};