00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <qapplication.h>
00023 #include <qimage.h>
00024 #include <qobject.h>
00025 #include <qfileinfo.h>
00026 #include <qdir.h>
00027
00028 #include "config.h"
00029 #include "mythtv/mythcontext.h"
00030 #include "mythtv/util.h"
00031
00032 #include "thumbgenerator.h"
00033 #include "constants.h"
00034 #include "galleryutil.h"
00035
00036 #ifdef EXIF_SUPPORT
00037 #include <libexif/exif-data.h>
00038 #include <libexif/exif-entry.h>
00039 #endif
00040
00041 ThumbGenerator::ThumbGenerator(QObject *parent, int w, int h)
00042 {
00043 m_parent = parent;
00044 m_width = w;
00045 m_height = h;
00046 m_isGallery = false;
00047 }
00048
00049 ThumbGenerator::~ThumbGenerator()
00050 {
00051 cancel();
00052 wait();
00053 }
00054
00055 void ThumbGenerator::setSize(int w, int h)
00056 {
00057 m_width = w;
00058 m_height = h;
00059 }
00060
00061 void ThumbGenerator::setDirectory(const QString& directory, bool isGallery)
00062 {
00063 m_mutex.lock();
00064 m_directory = directory;
00065 m_isGallery = isGallery;
00066 m_mutex.unlock();
00067 }
00068
00069 void ThumbGenerator::addFile(const QString& filePath)
00070 {
00071
00072
00073 m_mutex.lock();
00074 m_fileList.append(filePath);
00075 m_mutex.unlock();
00076 }
00077
00078 void ThumbGenerator::cancel()
00079 {
00080 m_mutex.lock();
00081 m_fileList.clear();
00082 m_mutex.unlock();
00083 }
00084
00085 void ThumbGenerator::run()
00086 {
00087
00088 while (moreWork()) {
00089
00090 QString file, dir;
00091 bool isGallery;
00092
00093 m_mutex.lock();
00094 dir = m_directory;
00095 isGallery = m_isGallery;
00096 file = m_fileList.first();
00097 if (!m_fileList.isEmpty())
00098 m_fileList.pop_front();
00099 m_mutex.unlock();
00100
00101 if (file.isEmpty())
00102 continue;
00103
00104 QString filePath = dir + QString("/") + file;
00105 QFileInfo fileInfo(filePath);
00106 if (!fileInfo.exists())
00107 continue;
00108
00109 if (isGallery) {
00110
00111 if (fileInfo.isDir())
00112 isGallery = checkGalleryDir(fileInfo);
00113 else
00114 isGallery = checkGalleryFile(fileInfo);
00115 }
00116
00117 if (!isGallery) {
00118
00119 QString cachePath = getThumbcacheDir(dir) + file;
00120 QFileInfo cacheInfo(cachePath);
00121
00122 if (cacheInfo.exists() &&
00123 cacheInfo.lastModified() >= fileInfo.lastModified()) {
00124 continue;
00125 }
00126 else {
00127
00128
00129 QImage image;
00130
00131 if (cacheInfo.exists()) {
00132
00133 QFile::remove(cachePath);
00134 }
00135
00136 if (fileInfo.isDir())
00137 loadDir(image, fileInfo);
00138 else
00139 loadFile(image, fileInfo);
00140
00141 if (image.isNull())
00142 continue;
00143
00144 image = image.smoothScale(m_width,m_height,QImage::ScaleMin);
00145 image.save(cachePath, "JPEG");
00146
00147
00148 ThumbData *td = new ThumbData;
00149 td->directory = dir;
00150 td->fileName = file;
00151 td->thumb = image.copy();
00152
00153
00154 QApplication::postEvent(m_parent,
00155 new QCustomEvent(QEvent::User, td));
00156
00157 }
00158 }
00159 }
00160 }
00161
00162 bool ThumbGenerator::moreWork()
00163 {
00164 bool result;
00165 m_mutex.lock();
00166 result = !m_fileList.isEmpty();
00167 m_mutex.unlock();
00168 return result;
00169 }
00170
00171 bool ThumbGenerator::checkGalleryDir(const QFileInfo& fi)
00172 {
00173
00174 QDir subdir(fi.absFilePath(), "*.highlight.*", QDir::Name,
00175 QDir::Files);
00176
00177
00178 if (subdir.count() > 0) {
00179
00180 QString path(subdir.entryInfoList()->getFirst()->absFilePath());
00181 return (QImageIO::imageFormat(path) != 0);
00182 }
00183 else
00184 return false;
00185 }
00186
00187 bool ThumbGenerator::checkGalleryFile(const QFileInfo& fi)
00188 {
00189
00190
00191 QString fn = fi.fileName();
00192 int firstDot = fn.find('.');
00193 if (firstDot > 0)
00194 {
00195 fn.insert(firstDot, ".thumb");
00196 QFileInfo galThumb(fi.dirPath(true) + "/" + fn);
00197 if (galThumb.exists())
00198 return (QImageIO::imageFormat(galThumb.absFilePath()) != 0);
00199 else
00200 return false;
00201 }
00202 return false;
00203 }
00204
00205 void ThumbGenerator::loadDir(QImage& image, const QFileInfo& fi)
00206 {
00207 QDir dir(fi.absFilePath());
00208 dir.setFilter(QDir::Files);
00209 const QFileInfoList *list = dir.entryInfoList();
00210 if (!list)
00211 return;
00212
00213 QFileInfoListIterator it( *list );
00214 QFileInfo *f;
00215
00216 bool found = false;
00217 while ( (f = it.current()) != 0 ) {
00218 if (QImage::imageFormat(f->absFilePath()) != 0) {
00219 found = true;
00220 break;
00221 }
00222 ++it;
00223 }
00224
00225 if (found) {
00226 loadFile(image, *f);
00227 return;
00228 }
00229 else {
00230
00231
00232
00233 dir.setFilter(QDir::Dirs);
00234 const QFileInfoList *dirList = dir.entryInfoList();
00235 if (!dirList)
00236 return;
00237
00238 QFileInfoListIterator it( *dirList );
00239 QFileInfo *f;
00240
00241 while ( ((f = it.current()) != 0) && image.isNull() ) {
00242
00243 ++it;
00244
00245 if (f->fileName() == "." || f->fileName() == "..")
00246 continue;
00247
00248 loadDir(image, *f);
00249 }
00250 }
00251 }
00252
00253 void ThumbGenerator::loadFile(QImage& image, const QFileInfo& fi)
00254 {
00255 if (GalleryUtil::isMovie(fi.filePath()))
00256 {
00257 bool thumbnailCreated = false;
00258 QDir tmpDir("/tmp/mythgallery");
00259 if (!tmpDir.exists())
00260 {
00261 if (!tmpDir.mkdir(tmpDir.absPath()))
00262 {
00263 std::cerr << "Unable to create temp dir for movie thumbnail creation: "
00264 << tmpDir.absPath() << endl;
00265 }
00266 }
00267
00268 if (tmpDir.exists())
00269 {
00270 QString cmd = "cd \"" + tmpDir.absPath() +
00271 "\"; mplayer -nosound -frames 1 -vo png \"" +
00272 fi.absFilePath() + "\"";
00273 if (myth_system(cmd) == 0)
00274 {
00275 QFileInfo thumb(tmpDir.filePath("00000001.png"));
00276 if (thumb.exists())
00277 {
00278 QImage img(thumb.absFilePath());
00279 image = img;
00280 thumbnailCreated = true;
00281 }
00282 }
00283 }
00284
00285 if (!thumbnailCreated)
00286 {
00287 QImage *img = gContext->LoadScaleImage("gallery-moviethumb.png");
00288 if (img)
00289 {
00290 image = *img;
00291 }
00292 }
00293 }
00294 else
00295 {
00296 #ifdef EXIF_SUPPORT
00297
00298 ExifData *ed = exif_data_new_from_file(fi.absFilePath());
00299 if (ed && ed->data)
00300 {
00301 image.loadFromData(ed->data, ed->size);
00302 }
00303
00304 if (ed)
00305 exif_data_free(ed);
00306
00307 if (image.width() > 0 && image.height() > 0)
00308 return;
00309 #endif
00310
00311 image.load(fi.absFilePath());
00312 }
00313 }
00314
00315 QString ThumbGenerator::getThumbcacheDir(const QString& inDir)
00316 {
00317 QString galleryDir = gContext->GetSetting("GalleryDir");
00318
00319
00320
00321 QString aPath = inDir + QString("/.thumbcache/");
00322 if (gContext->GetNumSetting("GalleryThumbnailLocation") &&
00323 !QDir(aPath).exists() &&
00324 inDir.startsWith(galleryDir))
00325 {
00326 mkpath(aPath);
00327 }
00328 if (!gContext->GetNumSetting("GalleryThumbnailLocation") ||
00329 !QDir(aPath).exists() ||
00330 !inDir.startsWith(galleryDir))
00331 {
00332
00333
00334 int prefixLen = gContext->GetSetting("GalleryDir").length();
00335 aPath = gContext->GetConfDir() + "/MythGallery";
00336 aPath += inDir.right(inDir.length() - prefixLen);
00337 aPath += QString("/.thumbcache/");
00338 mkpath(aPath);
00339 }
00340
00341 return aPath;
00342 }
00343
00344 bool ThumbGenerator::mkpath(const QString& inPath)
00345 {
00346
00347
00348 int i = 0;
00349 QString absPath = QDir(inPath).absPath() + "/";
00350 QDir parent("/");
00351 do
00352 {
00353 i = absPath.find('/', i + 1);
00354 if (i == -1)
00355 return true;
00356
00357 QString subPath(absPath.left(i));
00358 if (!QDir(subPath).exists())
00359 {
00360 if (!parent.mkdir(subPath.right(subPath.length() -
00361 parent.absPath().length() - 1)))
00362 {
00363 return false;
00364 }
00365 }
00366 parent = QDir(subPath);
00367 } while(1);
00368 }