Fixed an issue where an invalid screensaver type entry in es_settings.xml could crash the application.

Also cleaned up and modernized the overall screensaver code.
This commit is contained in:
Leon Styhre 2022-09-16 19:18:43 +02:00
parent bee9cf0623
commit 0d6c4e02a6
3 changed files with 47 additions and 53 deletions

View file

@ -52,19 +52,17 @@ Screensaver::Screensaver()
mWindow->setScreensaver(this); mWindow->setScreensaver(this);
} }
Screensaver::~Screensaver()
{
mCurrentGame = nullptr;
delete mVideoScreensaver;
delete mImageScreensaver;
}
void Screensaver::startScreensaver(bool generateMediaList) void Screensaver::startScreensaver(bool generateMediaList)
{ {
ViewController::getInstance()->pauseViewVideos(); ViewController::getInstance()->pauseViewVideos();
std::string path = ""; mScreensaverType = Settings::getInstance()->getString("ScreensaverType");
std::string screensaverType = Settings::getInstance()->getString("ScreensaverType"); // In case there is an invalid entry in the es_settings.xml file.
if (mScreensaverType != "dim" && mScreensaverType != "black" &&
mScreensaverType != "slideshow" && mScreensaverType != "video") {
mScreensaverType = "dim";
}
std::string path;
mHasMediaFiles = false; mHasMediaFiles = false;
mFallbackScreensaver = false; mFallbackScreensaver = false;
mOpacity = 0.0f; mOpacity = 0.0f;
@ -78,10 +76,10 @@ void Screensaver::startScreensaver(bool generateMediaList)
// Set mPreviousGame which will be used to avoid showing the same game again during // Set mPreviousGame which will be used to avoid showing the same game again during
// the random selection. // the random selection.
if ((screensaverType == "slideshow" || screensaverType == "video") && mCurrentGame != nullptr) if ((mScreensaverType == "slideshow" || mScreensaverType == "video") && mCurrentGame != nullptr)
mPreviousGame = mCurrentGame; mPreviousGame = mCurrentGame;
if (screensaverType == "slideshow") { if (mScreensaverType == "slideshow") {
if (generateMediaList) { if (generateMediaList) {
mImageFiles.clear(); mImageFiles.clear();
mImageCustomFiles.clear(); mImageCustomFiles.clear();
@ -120,7 +118,7 @@ void Screensaver::startScreensaver(bool generateMediaList)
generateOverlayInfo(); generateOverlayInfo();
if (!mImageScreensaver) if (!mImageScreensaver)
mImageScreensaver = new ImageComponent(false, false); mImageScreensaver = std::make_unique<ImageComponent>(false, false);
mTimer = 0; mTimer = 0;
@ -139,7 +137,7 @@ void Screensaver::startScreensaver(bool generateMediaList)
mTimer = 0; mTimer = 0;
return; return;
} }
else if (!mVideoScreensaver && (screensaverType == "video")) { else if (!mVideoScreensaver && (mScreensaverType == "video")) {
if (generateMediaList) if (generateMediaList)
mVideoFiles.clear(); mVideoFiles.clear();
@ -160,7 +158,7 @@ void Screensaver::startScreensaver(bool generateMediaList)
if (Settings::getInstance()->getBool("ScreensaverVideoGameInfo")) if (Settings::getInstance()->getBool("ScreensaverVideoGameInfo"))
generateOverlayInfo(); generateOverlayInfo();
mVideoScreensaver = new VideoFFmpegComponent; mVideoScreensaver = std::make_unique<VideoFFmpegComponent>();
mVideoScreensaver->setOrigin(0.5f, 0.5f); mVideoScreensaver->setOrigin(0.5f, 0.5f);
mVideoScreensaver->setPosition(Renderer::getScreenWidth() / 2.0f, mVideoScreensaver->setPosition(Renderer::getScreenWidth() / 2.0f,
Renderer::getScreenHeight() / 2.0f); Renderer::getScreenHeight() / 2.0f);
@ -186,13 +184,10 @@ void Screensaver::startScreensaver(bool generateMediaList)
void Screensaver::stopScreensaver() void Screensaver::stopScreensaver()
{ {
delete mVideoScreensaver; mImageScreensaver.reset();
mVideoScreensaver = nullptr; mVideoScreensaver.reset();
delete mImageScreensaver;
mImageScreensaver = nullptr;
mState = STATE_INACTIVE; mState = STATE_INACTIVE;
mDimValue = 1.0f; mDimValue = 1.0f;
mRectangleFadeIn = 50; mRectangleFadeIn = 50;
mTextFadeIn = 0; mTextFadeIn = 0;
@ -268,11 +263,10 @@ void Screensaver::goToGame()
void Screensaver::renderScreensaver() void Screensaver::renderScreensaver()
{ {
std::string screensaverType = Settings::getInstance()->getString("ScreensaverType");
glm::mat4 trans {Renderer::getIdentity()}; glm::mat4 trans {Renderer::getIdentity()};
mRenderer->setMatrix(trans); mRenderer->setMatrix(trans);
if (mVideoScreensaver && screensaverType == "video") { if (mVideoScreensaver && mScreensaverType == "video") {
// Render a black background below the video. // Render a black background below the video.
mRenderer->drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(), mRenderer->drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(),
0x000000FF, 0x000000FF); 0x000000FF, 0x000000FF);
@ -281,7 +275,7 @@ void Screensaver::renderScreensaver()
if (static_cast<int>(mState) >= STATE_FADE_IN_VIDEO) if (static_cast<int>(mState) >= STATE_FADE_IN_VIDEO)
mVideoScreensaver->render(trans); mVideoScreensaver->render(trans);
} }
else if (mImageScreensaver && screensaverType == "slideshow") { else if (mImageScreensaver && mScreensaverType == "slideshow") {
// Render a black background below the image. // Render a black background below the image.
mRenderer->drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(), mRenderer->drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(),
0x000000FF, 0x000000FF); 0x000000FF, 0x000000FF);
@ -297,7 +291,7 @@ void Screensaver::renderScreensaver()
} }
if (isScreensaverActive()) { if (isScreensaverActive()) {
if (Settings::getInstance()->getString("ScreensaverType") == "slideshow") { if (mScreensaverType == "slideshow") {
if (mHasMediaFiles) { if (mHasMediaFiles) {
if (Settings::getInstance()->getBool("ScreensaverSlideshowScanlines")) if (Settings::getInstance()->getBool("ScreensaverSlideshowScanlines"))
mRenderer->shaderPostprocessing(Renderer::Shader::SCANLINES); mRenderer->shaderPostprocessing(Renderer::Shader::SCANLINES);
@ -323,7 +317,7 @@ void Screensaver::renderScreensaver()
mFallbackScreensaver = true; mFallbackScreensaver = true;
} }
} }
else if (Settings::getInstance()->getString("ScreensaverType") == "video") { else if (mScreensaverType == "video") {
if (mHasMediaFiles) { if (mHasMediaFiles) {
Renderer::postProcessingParams videoParameters; Renderer::postProcessingParams videoParameters;
unsigned int shaders {0}; unsigned int shaders {0};
@ -374,8 +368,7 @@ void Screensaver::renderScreensaver()
mFallbackScreensaver = true; mFallbackScreensaver = true;
} }
} }
if (mFallbackScreensaver || if (mFallbackScreensaver || mScreensaverType == "dim") {
Settings::getInstance()->getString("ScreensaverType") == "dim") {
Renderer::postProcessingParams dimParameters; Renderer::postProcessingParams dimParameters;
dimParameters.dimming = mDimValue; dimParameters.dimming = mDimValue;
dimParameters.saturation = mSaturationAmount; dimParameters.saturation = mSaturationAmount;
@ -385,7 +378,7 @@ void Screensaver::renderScreensaver()
if (mSaturationAmount > 0.0) if (mSaturationAmount > 0.0)
mSaturationAmount = glm::clamp(mSaturationAmount - 0.035f, 0.0f, 1.0f); mSaturationAmount = glm::clamp(mSaturationAmount - 0.035f, 0.0f, 1.0f);
} }
else if (Settings::getInstance()->getString("ScreensaverType") == "black") { else if (mScreensaverType == "black") {
Renderer::postProcessingParams blackParameters; Renderer::postProcessingParams blackParameters;
blackParameters.dimming = mDimValue; blackParameters.dimming = mDimValue;
mRenderer->shaderPostprocessing(Renderer::Shader::CORE, blackParameters); mRenderer->shaderPostprocessing(Renderer::Shader::CORE, blackParameters);
@ -451,7 +444,7 @@ void Screensaver::generateImageList()
if (UIModeController::getInstance()->isUIModeKid() && if (UIModeController::getInstance()->isUIModeKid() &&
(*it2)->metadata.get("kidgame") != "true") (*it2)->metadata.get("kidgame") != "true")
continue; continue;
std::string imagePath = (*it2)->getImagePath(); std::string imagePath {(*it2)->getImagePath()};
if (imagePath != "") if (imagePath != "")
mImageFiles.push_back((*it2)); mImageFiles.push_back((*it2));
} }
@ -472,7 +465,7 @@ void Screensaver::generateVideoList()
if (UIModeController::getInstance()->isUIModeKid() && if (UIModeController::getInstance()->isUIModeKid() &&
(*it2)->metadata.get("kidgame") != "true") (*it2)->metadata.get("kidgame") != "true")
continue; continue;
std::string videoPath = (*it2)->getVideoPath(); std::string videoPath {(*it2)->getVideoPath()};
if (videoPath != "") if (videoPath != "")
mVideoFiles.push_back((*it2)); mVideoFiles.push_back((*it2));
} }
@ -490,7 +483,7 @@ void Screensaver::generateCustomImageList()
imageDir = Utils::String::replace(imageDir, "%ROMPATH%", FileData::getROMDirectory()); imageDir = Utils::String::replace(imageDir, "%ROMPATH%", FileData::getROMDirectory());
if (imageDir != "" && Utils::FileSystem::isDirectory(imageDir)) { if (imageDir != "" && Utils::FileSystem::isDirectory(imageDir)) {
std::string imageFilter = ".jpg, .JPG, .png, .PNG"; std::string imageFilter {".jpg, .JPG, .png, .PNG"};
Utils::FileSystem::StringList dirContent = Utils::FileSystem::getDirContent( Utils::FileSystem::StringList dirContent = Utils::FileSystem::getDirContent(
imageDir, Settings::getInstance()->getBool("ScreensaverSlideshowRecurse")); imageDir, Settings::getInstance()->getBool("ScreensaverSlideshowRecurse"));
@ -529,8 +522,8 @@ void Screensaver::pickRandomImage(std::string& path)
std::random_device randDev; std::random_device randDev;
// Mersenne Twister pseudorandom number generator. // Mersenne Twister pseudorandom number generator.
std::mt19937 engine {randDev()}; std::mt19937 engine {randDev()};
std::uniform_int_distribution<int> uniform_dist(0, std::uniform_int_distribution<int> uniform_dist {0,
static_cast<int>(mImageFiles.size()) - 1); static_cast<int>(mImageFiles.size()) - 1};
index = uniform_dist(engine); index = uniform_dist(engine);
} while (mPreviousGame && mImageFiles.at(index) == mPreviousGame); } while (mPreviousGame && mImageFiles.at(index) == mPreviousGame);
@ -563,8 +556,8 @@ void Screensaver::pickRandomVideo(std::string& path)
std::random_device randDev; std::random_device randDev;
// Mersenne Twister pseudorandom number generator. // Mersenne Twister pseudorandom number generator.
std::mt19937 engine {randDev()}; std::mt19937 engine {randDev()};
std::uniform_int_distribution<int> uniform_dist(0, std::uniform_int_distribution<int> uniform_dist {0,
static_cast<int>(mVideoFiles.size()) - 1); static_cast<int>(mVideoFiles.size()) - 1};
index = uniform_dist(engine); index = uniform_dist(engine);
} while (mPreviousGame && mVideoFiles.at(index) == mPreviousGame); } while (mPreviousGame && mVideoFiles.at(index) == mPreviousGame);
@ -591,8 +584,8 @@ void Screensaver::pickRandomCustomImage(std::string& path)
std::random_device randDev; std::random_device randDev;
// Mersenne Twister pseudorandom number generator. // Mersenne Twister pseudorandom number generator.
std::mt19937 engine {randDev()}; std::mt19937 engine {randDev()};
std::uniform_int_distribution<int> uniform_dist( std::uniform_int_distribution<int> uniform_dist {
0, static_cast<int>(mImageCustomFiles.size()) - 1); 0, static_cast<int>(mImageCustomFiles.size()) - 1};
index = uniform_dist(engine); index = uniform_dist(engine);
} while (mPreviousCustomImage != "" && mImageCustomFiles.at(index) == mPreviousCustomImage); } while (mPreviousCustomImage != "" && mImageCustomFiles.at(index) == mPreviousCustomImage);
@ -612,17 +605,17 @@ void Screensaver::generateOverlayInfo()
std::string favoriteChar; std::string favoriteChar;
if (mCurrentGame && mCurrentGame->getFavorite()) if (mCurrentGame && mCurrentGame->getFavorite())
favoriteChar = " " + ViewController::FAVORITE_CHAR; favoriteChar.append(" ").append(ViewController::FAVORITE_CHAR);
const std::string gameName = Utils::String::toUpper(mGameName) + favoriteChar; const std::string gameName {Utils::String::toUpper(mGameName) + favoriteChar};
const std::string systemName = Utils::String::toUpper(mSystemName); const std::string systemName {Utils::String::toUpper(mSystemName)};
const std::string overlayText = gameName + "\n" + systemName; const std::string overlayText {gameName + "\n" + systemName};
mGameOverlay = std::unique_ptr<TextCache>( mGameOverlay = std::unique_ptr<TextCache>(
mGameOverlayFont.at(0)->buildTextCache(overlayText, posX, posY, 0xFFFFFFFF)); mGameOverlayFont.at(0)->buildTextCache(overlayText, posX, posY, 0xFFFFFFFF));
float textSizeX; float textSizeX {0.0f};
float textSizeY = mGameOverlayFont[0].get()->sizeText(overlayText).y; float textSizeY {mGameOverlayFont[0].get()->sizeText(overlayText).y};
// There is a weird issue with sizeText() where the X size value is returned // There is a weird issue with sizeText() where the X size value is returned
// as too large if there are two rows in a string and the second row is longer // as too large if there are two rows in a string and the second row is longer

View file

@ -21,7 +21,6 @@ class Screensaver : public Window::Screensaver
{ {
public: public:
Screensaver(); Screensaver();
virtual ~Screensaver();
virtual bool isScreensaverActive() { return (mState != STATE_INACTIVE); } virtual bool isScreensaverActive() { return (mState != STATE_INACTIVE); }
virtual bool isFallbackScreensaver() { return mFallbackScreensaver; } virtual bool isFallbackScreensaver() { return mFallbackScreensaver; }
@ -61,11 +60,12 @@ private:
std::vector<FileData*> mImageFiles; std::vector<FileData*> mImageFiles;
std::vector<FileData*> mVideoFiles; std::vector<FileData*> mVideoFiles;
std::vector<std::string> mImageCustomFiles; std::vector<std::string> mImageCustomFiles;
ImageComponent* mImageScreensaver; std::unique_ptr<ImageComponent> mImageScreensaver;
VideoComponent* mVideoScreensaver; std::unique_ptr<VideoComponent> mVideoScreensaver;
FileData* mCurrentGame; FileData* mCurrentGame;
FileData* mPreviousGame; FileData* mPreviousGame;
std::string mScreensaverType;
std::string mPreviousCustomImage; std::string mPreviousCustomImage;
std::string mGameName; std::string mGameName;
std::string mSystemName; std::string mSystemName;

View file

@ -37,14 +37,15 @@ GuiScreensaverOptions::GuiScreensaverOptions(const std::string& title)
// Screensaver type. // Screensaver type.
auto screensaverType = std::make_shared<OptionListComponent<std::string>>( auto screensaverType = std::make_shared<OptionListComponent<std::string>>(
getHelpStyle(), "SCREENSAVER TYPE", false); getHelpStyle(), "SCREENSAVER TYPE", false);
std::vector<std::string> screensavers; std::string selectedScreensaver {Settings::getInstance()->getString("ScreensaverType")};
screensavers.push_back("dim"); screensaverType->add("DIM", "dim", selectedScreensaver == "dim");
screensavers.push_back("black"); screensaverType->add("BLACK", "black", selectedScreensaver == "black");
screensavers.push_back("slideshow"); screensaverType->add("SLIDESHOW", "slideshow", selectedScreensaver == "slideshow");
screensavers.push_back("video"); screensaverType->add("VIDEO", "video", selectedScreensaver == "video");
for (auto it = screensavers.cbegin(); it != screensavers.cend(); ++it) // If there are no objects returned, then there must be a manually modified entry in the
screensaverType->add(*it, *it, // configuration file. Simply set the screensaver type to "dim" in this case.
Settings::getInstance()->getString("ScreensaverType") == *it); if (screensaverType->getSelectedObjects().size() == 0)
screensaverType->selectEntry(0);
addWithLabel("SCREENSAVER TYPE", screensaverType); addWithLabel("SCREENSAVER TYPE", screensaverType);
addSaveFunc([screensaverType, this] { addSaveFunc([screensaverType, this] {
if (screensaverType->getSelected() != if (screensaverType->getSelected() !=