Dramatically improved start times for the video and slideshow screensavers on devices with poor disk I/O performance

This commit is contained in:
Leon Styhre 2024-07-09 21:42:24 +02:00
parent a5c07b5b38
commit ab39b3759e
2 changed files with 85 additions and 9 deletions

View file

@ -154,6 +154,10 @@ public:
const std::string& getSortTypeString() const { return mSortTypeString; }
const FileData::SortType& getSortTypeFromString(const std::string& desc) const;
static inline std::vector<std::string> sImageExtensions {".png", ".jpg"};
static inline std::vector<std::string> sVideoExtensions {".mp4", ".mkv", ".avi",
".mp4", ".wmv", ".mov"};
protected:
FileData* mSourceFileData;
FileData* mParent;
@ -171,9 +175,7 @@ private:
std::vector<FileData*> mChildrenLastPlayed;
std::vector<FileData*> mChildrenMostPlayed;
std::function<void()> mUpdateListCallback;
static inline std::vector<std::string> sImageExtensions {".png", ".jpg"};
static inline std::vector<std::string> sVideoExtensions {".mp4", ".mkv", ".avi",
".mp4", ".wmv", ".mov"};
// The pair includes all games, and favorite games.
std::pair<unsigned int, unsigned int> mGameCount;
bool mOnlyFolders;

View file

@ -418,6 +418,32 @@ void Screensaver::generateImageList()
if (!(*it)->isGameSystem() || (*it)->isCollection())
continue;
// This method of building an inventory of all image files isn't pretty, but to use the
// FileData::getImagePath() function leads to unacceptable performance issues on some
// platforms like Android that offer very poor disk I/O performance. To instead list
// all files recursively is much faster as this avoids stat() function calls which are
// very expensive on such problematic platforms.
const std::string mediaDirMiximages {
FileData::getMediaDirectory() + (*it)->getRootFolder()->getSystemName() + "/miximages"};
const std::string mediaDirScreenshots {FileData::getMediaDirectory() +
(*it)->getRootFolder()->getSystemName() +
"/screenshots"};
const std::string mediaDirTitlescreens {FileData::getMediaDirectory() +
(*it)->getRootFolder()->getSystemName() +
"/titlescreens"};
const std::string mediaDirCovers {FileData::getMediaDirectory() +
(*it)->getRootFolder()->getSystemName() + "/covers"};
const Utils::FileSystem::StringList dirContentMiximages {
Utils::FileSystem::getDirContent(mediaDirMiximages, true)};
const Utils::FileSystem::StringList dirContentScreenshots {
Utils::FileSystem::getDirContent(mediaDirScreenshots, true)};
const Utils::FileSystem::StringList dirContentTitlescreens {
Utils::FileSystem::getDirContent(mediaDirTitlescreens, true)};
const Utils::FileSystem::StringList dirContentCovers {
Utils::FileSystem::getDirContent(mediaDirCovers, true)};
std::string subFolders;
std::vector<FileData*> allFiles {(*it)->getRootFolder()->getFilesRecursive(GAME, true)};
for (auto it2 = allFiles.cbegin(); it2 != allFiles.cend(); ++it2) {
// Only include games suitable for children if we're in Kid UI mode.
@ -426,9 +452,36 @@ void Screensaver::generateImageList()
continue;
if (favoritesOnly && (*it2)->metadata.get("favorite") != "true")
continue;
std::string imagePath {(*it2)->getImagePath()};
if (imagePath != "")
mImageFiles.push_back((*it2));
subFolders = Utils::String::replace(Utils::FileSystem::getParent((*it2)->getPath()),
(*it)->getStartPath(), "");
const std::string gamePath {subFolders + "/" + (*it2)->getDisplayName()};
for (auto& extension : FileData::sImageExtensions) {
if (std::find(dirContentMiximages.cbegin(), dirContentMiximages.cend(),
mediaDirMiximages + gamePath + extension) !=
dirContentMiximages.cend()) {
mImageFiles.push_back((*it2));
break;
}
if (std::find(dirContentScreenshots.cbegin(), dirContentScreenshots.cend(),
mediaDirScreenshots + gamePath + extension) !=
dirContentScreenshots.cend()) {
mImageFiles.push_back((*it2));
break;
}
if (std::find(dirContentTitlescreens.cbegin(), dirContentTitlescreens.cend(),
mediaDirTitlescreens + gamePath + extension) !=
dirContentTitlescreens.cend()) {
mImageFiles.push_back((*it2));
break;
}
if (std::find(dirContentCovers.cbegin(), dirContentCovers.cend(),
mediaDirCovers + gamePath + extension) != dirContentCovers.cend()) {
mImageFiles.push_back((*it2));
break;
}
}
}
}
@ -445,6 +498,18 @@ void Screensaver::generateVideoList()
if (!(*it)->isGameSystem() || (*it)->isCollection())
continue;
// This method of building an inventory of all video files isn't pretty, but to use the
// FileData::getVideoPath() function leads to unacceptable performance issues on some
// platforms like Android that offer very poor disk I/O performance. To instead list
// all files recursively is much faster as this avoids stat() function calls which are
// very expensive on such problematic platforms.
const std::string mediaDir {FileData::getMediaDirectory() +
(*it)->getRootFolder()->getSystemName() + "/videos"};
const Utils::FileSystem::StringList dirContent {
Utils::FileSystem::getDirContent(mediaDir, true)};
std::string subFolders;
std::vector<FileData*> allFiles {(*it)->getRootFolder()->getFilesRecursive(GAME, true)};
for (auto it2 = allFiles.cbegin(); it2 != allFiles.cend(); ++it2) {
// Only include games suitable for children if we're in Kid UI mode.
@ -453,9 +518,18 @@ void Screensaver::generateVideoList()
continue;
if (favoritesOnly && (*it2)->metadata.get("favorite") != "true")
continue;
std::string videoPath {(*it2)->getVideoPath()};
if (videoPath != "")
mVideoFiles.push_back((*it2));
subFolders = Utils::String::replace(Utils::FileSystem::getParent((*it2)->getPath()),
(*it)->getStartPath(), "");
const std::string gamePath {subFolders + "/" + (*it2)->getDisplayName()};
for (auto& extension : FileData::sVideoExtensions) {
if (std::find(dirContent.cbegin(), dirContent.cend(),
mediaDir + gamePath + extension) != dirContent.cend()) {
mVideoFiles.push_back((*it2));
break;
}
}
}
}