File indexing completed on 2024-04-21 04:49:07

0001 /*
0002  * SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
0003  *
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  */
0006 
0007 #include "worker.h"
0008 
0009 #include "application.h"
0010 #include "framedecoder.h"
0011 #include "generalsettings.h"
0012 
0013 #include <QCryptographicHash>
0014 #include <QDir>
0015 #include <QFileInfo>
0016 #include <QImage>
0017 #include <QQuickWindow>
0018 #include <QThread>
0019 
0020 #include <KConfig>
0021 #include <KConfigGroup>
0022 #include <KFileMetaData/ExtractorCollection>
0023 #include <KFileMetaData/SimpleExtractionResult>
0024 #include <KWindowConfig>
0025 
0026 Worker *Worker::instance()
0027 {
0028     static Worker w;
0029     return &w;
0030 }
0031 
0032 void Worker::getMetaData(int index, const QString &path)
0033 {
0034     auto url = QUrl::fromUserInput(path);
0035     if (url.scheme() != QStringLiteral("file")) {
0036         return;
0037     }
0038     QString mimeType = Application::mimeType(url);
0039     KFileMetaData::ExtractorCollection exCol;
0040     QList<KFileMetaData::Extractor *> extractors = exCol.fetchExtractors(mimeType);
0041     KFileMetaData::SimpleExtractionResult result(path, mimeType, KFileMetaData::ExtractionResult::ExtractMetaData);
0042     if (extractors.size() == 0) {
0043         return;
0044     }
0045     KFileMetaData::Extractor *ex = extractors.first();
0046     ex->extract(&result);
0047 
0048     auto properties = result.properties();
0049 
0050     Q_EMIT metaDataReady(index, properties);
0051 }
0052 
0053 void Worker::makePlaylistThumbnail(const QString &path, int width)
0054 {
0055     QImage image;
0056 
0057     auto file = QUrl::fromUserInput(path);
0058 
0059     // figure out absolute path of the thumbnail
0060     auto md5Hash = QCryptographicHash::hash(file.toString().toUtf8(), QCryptographicHash::Md5);
0061     QString cacheDir(QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation));
0062     QString appDir(QStringLiteral("haruna"));
0063     QString fileDir(QString::fromUtf8(md5Hash.toHex()));
0064     QString filename(QString::fromUtf8(md5Hash.toHex()).append(QStringLiteral(".png")));
0065     QString separator(QStringLiteral("/"));
0066     QString cachedFilePath = cacheDir + separator + appDir + separator + fileDir + separator + filename;
0067 
0068     // load existing thumbnail if there is one
0069     if (QFileInfo::exists(cachedFilePath) && image.load(cachedFilePath)) {
0070         Q_EMIT thumbnailSuccess(path, image);
0071         return;
0072     }
0073 
0074     image = frameToImage(path, width);
0075 
0076     if (image.isNull()) {
0077         qDebug() << QStringLiteral("Failed to create thumbnail for file: %1").arg(path);
0078         return;
0079     }
0080     Q_EMIT thumbnailSuccess(path, image);
0081 
0082     QFileInfo fi(cachedFilePath);
0083     // create folders where the file will be saved
0084     if (QDir().mkpath(fi.absolutePath())) {
0085         if (!image.save(cachedFilePath)) {
0086             qDebug() << QStringLiteral("Failed to save thumbnail for file: %1").arg(path);
0087         }
0088     }
0089 }
0090 
0091 QImage Worker::frameToImage(const QString &path, int width)
0092 {
0093     QImage image;
0094     FrameDecoder frameDecoder(path, nullptr);
0095     if (!frameDecoder.getInitialized()) {
0096         return image;
0097     }
0098     // before seeking, a frame has to be decoded
0099     if (!frameDecoder.decodeVideoFrame()) {
0100         return image;
0101     }
0102 
0103     int secondToSeekTo = frameDecoder.getDuration() * 20 / 100;
0104     frameDecoder.seek(secondToSeekTo);
0105     frameDecoder.getScaledVideoFrame(width, true, image);
0106 
0107     return image;
0108 }
0109 
0110 void Worker::mprisThumbnail(const QString &path, int width)
0111 {
0112     QImage image;
0113     FrameDecoder frameDecoder(path, nullptr);
0114     if (!frameDecoder.getInitialized()) {
0115         return;
0116     }
0117     // before seeking, a frame has to be decoded
0118     if (!frameDecoder.decodeVideoFrame()) {
0119         return;
0120     }
0121 
0122     int secondToSeekTo = frameDecoder.getDuration() * 20 / 100;
0123     frameDecoder.seek(secondToSeekTo);
0124     frameDecoder.getScaledVideoFrame(width, true, image);
0125 
0126     Q_EMIT mprisThumbnailSuccess(image);
0127 }
0128 
0129 void Worker::syncConfigValue(QString path, QString group, QString key, QVariant value)
0130 {
0131     if (!m_cachedConf || m_cachedConf->name() != path) {
0132         m_cachedConf.reset(new KConfig(path));
0133     }
0134 
0135     m_cachedConf->group(group).writeEntry(key, value);
0136     m_cachedConf->sync();
0137 }
0138 
0139 void Worker::saveWindowGeometry(QQuickWindow *window) const
0140 {
0141     if (!GeneralSettings::rememberWindowGeometry()) {
0142         return;
0143     }
0144     KConfig dataResource(QStringLiteral("data"), KConfig::SimpleConfig, QStandardPaths::AppDataLocation);
0145     KConfigGroup windowGroup(&dataResource, QStringLiteral("Window"));
0146     KWindowConfig::saveWindowPosition(window, windowGroup);
0147     KWindowConfig::saveWindowSize(window, windowGroup);
0148     dataResource.sync();
0149 }
0150 
0151 #include "moc_worker.cpp"