| 36 | namespace tev { |
| 37 | |
| 38 | void BackgroundImagesLoader::enqueue(const fs::path& path, string_view channelSelector, bool shallSelect, const shared_ptr<Image>& toReplace) { |
| 39 | // If we're trying to open a directory, try loading all the images inside of that directory |
| 40 | if (fs::exists(path) && fs::is_directory(path)) { |
| 41 | tlog::info("Loading images {}from directory {}", mRecursiveDirectories ? "recursively " : "", path); |
| 42 | |
| 43 | const fs::path canonicalPath = fs::canonical(path); |
| 44 | mDirectories[canonicalPath].emplace(channelSelector); |
| 45 | |
| 46 | vector<fs::directory_entry> entries; |
| 47 | forEachFileInDir(mRecursiveDirectories, canonicalPath, [&](const auto& entry) { |
| 48 | if (!entry.is_directory()) { |
| 49 | mFilesFoundInDirectories.emplace(entry, string{channelSelector}); |
| 50 | entries.emplace_back(entry); |
| 51 | } |
| 52 | }); |
| 53 | |
| 54 | // Open directory entries in natural order (e.g. "file1.exr", "file2.exr", "file10.exr" instead of "file1.exr", "file10.exr"), |
| 55 | // selecting the first one. |
| 56 | sort(begin(entries), end(entries), [](const auto& a, const auto& b) { return naturalCompare(a.path().string(), b.path().string()); }); |
| 57 | |
| 58 | for (size_t i = 0; i < entries.size(); ++i) { |
| 59 | enqueue(entries[i], channelSelector, i == 0 ? shallSelect : false); |
| 60 | } |
| 61 | |
| 62 | return; |
| 63 | } |
| 64 | |
| 65 | // We want to measure the time it takes to load a whole batch of images. Start measuring when the loader queue goes from empty to |
| 66 | // non-empty and stop measuring when the queue goes from non-empty to empty again. |
| 67 | if (mUnsortedLoadCounter == mLoadCounter) { |
| 68 | mLoadStartTime = chrono::system_clock::now(); |
| 69 | mLoadStartCounter = mUnsortedLoadCounter; |
| 70 | } |
| 71 | |
| 72 | const int loadId = mUnsortedLoadCounter++; |
| 73 | invokeTaskDetached([loadId, path, cs = string{channelSelector}, shallSelect, toReplace, this]() -> Task<void> { |
| 74 | const int taskPriority = -Image::drawId(); |
| 75 | |
| 76 | co_await ThreadPool::global().enqueueCoroutine(taskPriority); |
| 77 | const auto images = co_await tryLoadImage(taskPriority, path, cs, mImageLoaderSettings, mGroupChannels); |
| 78 | |
| 79 | { |
| 80 | const lock_guard lock{mPendingLoadedImagesMutex}; |
| 81 | mPendingLoadedImages.push({.images = images, .toReplace = toReplace, .loadId = loadId, .shallSelect = shallSelect}); |
| 82 | } |
| 83 | |
| 84 | if (publishSortedLoads()) { |
| 85 | redrawWindow(); |
| 86 | } |
| 87 | }); |
| 88 | } |
| 89 | |
| 90 | void BackgroundImagesLoader::checkDirectoriesForNewFilesAndLoadThose() { |
| 91 | for (const auto& [dir, channelSelectors] : mDirectories) { |
no test coverage detected