Fixed minor bug with 'More' button
[someplayer] / src / coverfinder.cpp
1 /*
2  * SomePlayer - An alternate music player for Maemo 5
3  * Copyright (C) 2010 Nikolay (somebody) Tischenko <niktischenko@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  */
19
20
21 #include "coverfinder.h"
22 #include <QDebug>
23 #include <QDir>
24 #include <QFileInfo>
25 #include <QtConcurrentRun>
26 #include <mpegfile.h>
27 #include <flacfile.h>
28 #include <oggfile.h>
29 #include <id3v2tag.h>
30 #include <mpeg/id3v2/frames/attachedpictureframe.h>
31
32 CoverFinder::CoverFinder(QObject *parent) :
33                 QObject(parent)
34 {
35         _defaultCover = QImage(":/images/defaultcover.png");
36         SUFFIXES << "png" << "jpg" << "jpeg" << "bmp" << "gif";
37         NAMES << "cover" << "folder" << "album";
38         DIRS << "cover" << "folder" << ".cover" << ".folder";
39 }
40
41 bool CoverFinder::_find(QString path) {
42         QDir dir(path);
43         QFileInfoList items = dir.entryInfoList(QDir::Files);
44         QFileInfoList dirs = dir.entryInfoList(QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Hidden);
45         QFileInfoList pics;
46         foreach (QFileInfo item, items) {
47                 if (SUFFIXES.contains(item.suffix().toLower())) {
48                         pics << item;
49                         if (NAMES.contains(item.baseName().toLower())) {
50                                 emit found(QImage(item.absoluteFilePath()));
51                                 return true;
52                         }
53                 }
54         }
55         foreach (QFileInfo item, pics) {
56                 QImage i(item.absoluteFilePath());
57                 if (0.8 <= (i.width()*1.0/(i.height()+1.0)) <= 1.2) {
58                         emit found(i);
59                         return true;
60                 }
61         }
62         foreach(QFileInfo item, dirs) {
63                 if (DIRS.contains(item.fileName().toLower())) {
64                         if (_find(item.absoluteFilePath())) {
65                                 return true;
66                         }
67                 }
68         }
69         emit found(_defaultCover);
70         return false;
71 }
72
73 QImage &CoverFinder::defaultCover() {
74         return _defaultCover;
75 }
76
77 bool CoverFinder::_extract(QString file) {
78         QFileInfo info(file);
79         QString suffix = info.suffix().toLower();
80         TagLib::ID3v2::Tag *tag = NULL;
81         bool todo = false;
82         TagLib::File *f = NULL;
83         if (suffix == "mp3") {
84                 f = new TagLib::MPEG::File(QFile::encodeName(file).data(), true, TagLib::AudioProperties::Fast);
85                 if (f == NULL) return false;
86                 tag = ((TagLib::MPEG::File*)f)->ID3v2Tag();
87                 todo = f->isValid();
88         } else if (suffix == "flac") {
89                 f = new TagLib::FLAC::File(QFile::encodeName(file).data(), true, TagLib::AudioProperties::Fast);
90                 if (f == NULL) return false;
91                 tag = ((TagLib::FLAC::File*)f)->ID3v2Tag();
92                 todo = f->isValid();
93         }
94         if (todo && tag != NULL) {
95                 TagLib::ID3v2::FrameList l = tag->frameList("APIC");
96                 if (l.isEmpty())
97                         return false;
98                 TagLib::ID3v2::AttachedPictureFrame *pic = static_cast<TagLib::ID3v2::AttachedPictureFrame *>(l.front());
99                 QImage img;
100                 img.loadFromData((const uchar *) pic->picture().data(), pic->picture().size());
101                 emit found(img);
102                 return true;
103         }
104         if (f != NULL) delete f;
105         return false;
106 }
107
108 void CoverFinder::find(QFileInfo filePath) {
109         QtConcurrent::run(this, &CoverFinder::_async_find, filePath);
110 }
111
112 bool CoverFinder::_async_find(QFileInfo filePath) {
113         if (!_find(filePath.absolutePath()))
114                 return _extract(filePath.absoluteFilePath());
115         return true;
116 }