File indexing completed on 2024-04-14 04:47:26

0001 /*
0002     SPDX-FileCopyrightText: 2017 Nicolas Carion
0003     SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 */
0005 
0006 #pragma once
0007 
0008 #include "definitions.h"
0009 #include <QDir>
0010 #include <QImage>
0011 #include <QMutex>
0012 #include <QUrl>
0013 #include <memory>
0014 #include <mutex>
0015 #include <unordered_map>
0016 #include <vector>
0017 
0018 /** @class ThumbnailCache
0019     @brief This class class is an interface to the caches that store thumbnails.
0020     In Kdenlive, we use two such caches, a persistent that is stored on disk to allow thumbnails to be reused when reopening.
0021     The other one is a volatile LRU cache that lives in memory.
0022     Note that for the volatile cache uses a custom implementation.
0023     QCache is not suitable since it operates on pointers and since the object is removed from the cache when accessed.
0024     KImageCache is not suitable since it lacks a way to remove objects from the cache.
0025  * Note that this class is a Singleton
0026  */
0027 class ThumbnailCache
0028 {
0029 
0030 public:
0031     // Returns the instance of the Singleton
0032     static std::unique_ptr<ThumbnailCache> &get();
0033 
0034     /** @brief Check whether a given thumbnail is in the cache
0035        @param binId is the id of the queried clip
0036        @param pos is the position where we query
0037        @param volatileOnly if true, we only check the volatile cache (no disk access)
0038      */
0039     bool hasThumbnail(const QString &binId, int pos, bool volatileOnly = false) const;
0040 
0041     /** @brief Get a given thumbnail from the cache
0042        @param binId is the id of the queried clip
0043        @param pos is the position where we query
0044        @param volatileOnly if true, we only check the volatile cache (no disk access)
0045     */
0046     QImage getThumbnail(QString hash, const QString &binId, int pos, bool volatileOnly = false) const;
0047     QImage getThumbnail(const QString &binId, int pos, bool volatileOnly = false) const;
0048     QImage getAudioThumbnail(const QString &binId, bool volatileOnly = false) const;
0049     const QList<QUrl> getAudioThumbPath(const QString &binId) const;
0050 
0051     /** @brief Get a given thumbnail from the cache
0052        @param binId is the id of the queried clip
0053        @param pos is the position where we query
0054        @param persistent if true, we store the image in the persistent cache, which generates a disk access
0055     */
0056     void storeThumbnail(const QString &binId, int pos, const QImage &img, bool persistent = false);
0057 
0058     /** @brief Removes all the thumbnails for a given clip */
0059     void invalidateThumbsForClip(const QString &binId);
0060 
0061     /** @brief Save all cached thumbs to disk */
0062     void saveCachedThumbs(const std::unordered_map<QString, std::vector<int>> &keys);
0063 
0064     /** @brief Reset cache (discarding all thumbs stored in memory) */
0065     void clearCache();
0066 
0067     /** @brief Ensure the cache is not corrupted */
0068     bool checkIntegrity() const;
0069 
0070 protected:
0071     // Constructor is protected because class is a Singleton
0072     ThumbnailCache();
0073 
0074     // Return the key associated to a thumbnail
0075     static QString getKey(const QString &binId, int pos, bool *ok);
0076     static QStringList getAudioKey(const QString &binId, bool *ok);
0077 
0078     // Return the dir where the persistent cache lives
0079     static const QDir getDir(bool audio, bool *ok);
0080 
0081     static std::unique_ptr<ThumbnailCache> instance;
0082     static std::once_flag m_onceFlag; // flag to create the repository only once;
0083 
0084     class Cache_t;
0085     std::unique_ptr<Cache_t> m_volatileCache;
0086     mutable QMutex m_mutex;
0087 
0088     // the following maps keeps track of the positions that we store for each clip in volatile caches.
0089     // Note that we don't track deletions due to items dropped from the cache. So the maps can contain more items that are currently stored.
0090     std::unordered_map<QString, std::vector<int>> m_storedVolatile;
0091     mutable std::unordered_map<QString, std::vector<int>> m_storedOnDisk;
0092 };