#pragma once #include "../include/Storage.hpp" #include "../include/MessageQueue.hpp" #include "../include/FileAnalyzer.hpp" #include #include #include #include #include #include namespace QuickMedia { enum class LoadingState { NOT_LOADED, LOADING, FINISHED_LOADING, APPLIED_TO_TEXTURE }; struct ThumbnailData { bool referenced = false; LoadingState loading_state = LoadingState::NOT_LOADED; sf::Texture texture; std::unique_ptr image; // Set in another thread. This should be .reset after loading it into |texture|, to save memory sf::Clock texture_applied_time; }; // This function is async bool create_thumbnail(const Path &thumbnail_path, const Path &thumbnail_path_resized, sf::Vector2i resize_target_size, ContentType content_type); constexpr int NUM_IMAGE_LOAD_THREADS = 4; class AsyncImageLoader { public: static AsyncImageLoader& get_instance(); // Returns false if the image loader is already loading an image. In that case, this function should be called again later. // set |resize_target_size| to {0, 0} to disable resizing. // Note: this method is not thread-safe void load_thumbnail(const std::string &url, bool local, sf::Vector2i resize_target_size, std::shared_ptr thumbnail_data); private: AsyncImageLoader(); ~AsyncImageLoader(); AsyncImageLoader(AsyncImageLoader &other) = delete; AsyncImageLoader& operator=(AsyncImageLoader &other) = delete; struct ThumbnailLoadData { Path path; Path thumbnail_path; bool local; std::shared_ptr thumbnail_data; sf::Vector2i resize_target_size; }; // Returns -1 if all threads are busy int get_free_load_index() const; private: bool loading_image[NUM_IMAGE_LOAD_THREADS]; // TODO: Use curl single-threaded multi-download feature instead std::thread download_image_thread[NUM_IMAGE_LOAD_THREADS]; std::thread load_image_thread; MessageQueue image_load_queue; }; }