diff --git a/es-app/CMakeLists.txt b/es-app/CMakeLists.txt index 3cff331c2..60c5e5616 100644 --- a/es-app/CMakeLists.txt +++ b/es-app/CMakeLists.txt @@ -26,6 +26,9 @@ set(ES_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiGameScraper.h ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiGamelistOptions.h ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiScreensaverOptions.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiGeneralScreensaverOptions.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiVideoScreensaverOptions.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiSlideshowScreensaverOptions.h ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiMenu.h ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiSettings.h ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiScraperMulti.h @@ -79,6 +82,9 @@ set(ES_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiGameScraper.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiGamelistOptions.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiScreensaverOptions.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiGeneralScreensaverOptions.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiVideoScreensaverOptions.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiSlideshowScreensaverOptions.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiMenu.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiSettings.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiScraperMulti.cpp diff --git a/es-app/src/SystemScreenSaver.cpp b/es-app/src/SystemScreenSaver.cpp index 5078e9bd5..905ff8b57 100644 --- a/es-app/src/SystemScreenSaver.cpp +++ b/es-app/src/SystemScreenSaver.cpp @@ -3,6 +3,7 @@ #include "components/VideoPlayerComponent.h" #endif #include "components/VideoVlcComponent.h" +#include "components/ImageComponent.h" #include "platform.h" #include "PowerSaver.h" #include "Renderer.h" @@ -10,6 +11,8 @@ #include "SystemData.h" #include "Util.h" #include "Log.h" +#include "AudioManager.h" +#include "Sound.h" #include "views/ViewController.h" #include "views/gamelist/IGameListView.h" #include @@ -18,15 +21,19 @@ SystemScreenSaver::SystemScreenSaver(Window* window) : mVideoScreensaver(NULL), + mImageScreensaver(NULL), mWindow(window), - mCounted(false), + mVideosCounted(false), mVideoCount(0), + mImagesCounted(false), + mImageCount(0), mState(STATE_INACTIVE), mOpacity(0.0f), mTimer(0), mSystemName(""), mGameName(""), - mCurrentGame(NULL) + mCurrentGame(NULL), + mStopBackgroundAudio(true) { mWindow->setScreenSaver(this); std::string path = getTitleFolder(); @@ -42,12 +49,13 @@ SystemScreenSaver::~SystemScreenSaver() remove(getTitlePath().c_str()); mCurrentGame = NULL; delete mVideoScreensaver; + delete mImageScreensaver; } bool SystemScreenSaver::allowSleep() { //return false; - return (mVideoScreensaver == NULL); + return ((mVideoScreensaver == NULL) && (mImageScreensaver == NULL)); } bool SystemScreenSaver::isScreenSaverActive() @@ -57,7 +65,8 @@ bool SystemScreenSaver::isScreenSaverActive() void SystemScreenSaver::startScreenSaver() { - if (!mVideoScreensaver && (Settings::getInstance()->getString("ScreenSaverBehavior") == "random video")) + std::string screensaver_behavior = Settings::getInstance()->getString("ScreenSaverBehavior"); + if (!mVideoScreensaver && (screensaver_behavior == "random video")) { // Configure to fade out the windows, Skip Fading if Instant mode mState = PowerSaver::getMode() == PowerSaver::INSTANT @@ -79,9 +88,8 @@ void SystemScreenSaver::startScreenSaver() if (!path.empty() && boost::filesystem::exists(path)) { - // Create the correct type of video component - #ifdef _RPI_ + // Create the correct type of video component if (Settings::getInstance()->getBool("ScreenSaverOmxPlayer")) mVideoScreensaver = new VideoPlayerComponent(mWindow, getTitlePath()); else @@ -109,6 +117,64 @@ void SystemScreenSaver::startScreenSaver() return; } } + else if (screensaver_behavior == "slideshow") + { + // Configure to fade out the windows, Skip Fading if Instant mode + mState = PowerSaver::getMode() == PowerSaver::INSTANT + ? STATE_SCREENSAVER_ACTIVE + : STATE_FADE_OUT_WINDOW; + mVideoChangeTime = Settings::getInstance()->getInt("ScreenSaverSwapImageTimeout"); + mOpacity = 0.0f; + + // Load a random image + std::string path = ""; + if (Settings::getInstance()->getBool("SlideshowScreenSaverCustomImageSource")) + { + pickRandomCustomImage(path); + // Custom images are not tied to the game list + mCurrentGame = NULL; + } + else + { + pickRandomGameListImage(path); + } + + if (!mImageScreensaver) + { + mImageScreensaver = new ImageComponent(mWindow, false, false); + } + + mTimer = 0; + + mImageScreensaver->setImage(path); + mImageScreensaver->setOrigin(0.5f, 0.5f); + mImageScreensaver->setPosition(Renderer::getScreenWidth()/2, Renderer::getScreenHeight()/2); + + if (Settings::getInstance()->getBool("SlideshowScreenSaverStretch")) + { + mImageScreensaver->setResize((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight()); + } + else + { + mImageScreensaver->setMaxSize((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight()); + } + + std::string bg_audio_file = Settings::getInstance()->getString("SlideshowScreenSaverBackgroundAudioFile"); + if ((!mBackgroundAudio) && (bg_audio_file != "")) + { + if (boost::filesystem::exists(bg_audio_file)) + { + // paused PS so that the background audio keeps playing + PowerSaver::pause(); + mBackgroundAudio = Sound::get(bg_audio_file); + mBackgroundAudio->play(); + } + } + + PowerSaver::runningScreenSaver(true); + mTimer = 0; + return; + } // No videos. Just use a standard screensaver mState = STATE_SCREENSAVER_ACTIVE; mCurrentGame = NULL; @@ -116,8 +182,22 @@ void SystemScreenSaver::startScreenSaver() void SystemScreenSaver::stopScreenSaver() { + if ((mBackgroundAudio) && (mStopBackgroundAudio)) + { + mBackgroundAudio->stop(); + mBackgroundAudio.reset(); + // if we were playing audio, we paused PS + PowerSaver::resume(); + } + + // so that we stop the background audio next time, unless we're restarting the screensaver + mStopBackgroundAudio = true; + delete mVideoScreensaver; mVideoScreensaver = NULL; + delete mImageScreensaver; + mImageScreensaver = NULL; + // we need this to loop through different videos mState = STATE_INACTIVE; PowerSaver::runningScreenSaver(false); @@ -125,7 +205,8 @@ void SystemScreenSaver::stopScreenSaver() void SystemScreenSaver::renderScreenSaver() { - if (mVideoScreensaver && Settings::getInstance()->getString("ScreenSaverBehavior") == "random video") + std::string screensaver_behavior = Settings::getInstance()->getString("ScreenSaverBehavior"); + if (mVideoScreensaver && screensaver_behavior == "random video") { // Render black background Renderer::setMatrix(Eigen::Affine3f::Identity()); @@ -138,59 +219,49 @@ void SystemScreenSaver::renderScreenSaver() mVideoScreensaver->render(transform); } } + else if (mImageScreensaver && screensaver_behavior == "slideshow") + { + // Render black background + Renderer::setMatrix(Eigen::Affine3f::Identity()); + Renderer::drawRect(0, 0, Renderer::getScreenWidth(), Renderer::getScreenHeight(), (unsigned char)(255)); + + // Only render the video if the state requires it + if ((int)mState >= STATE_FADE_IN_VIDEO) + { + if (mImageScreensaver->hasImage()) + { + mImageScreensaver->setOpacity(255-mOpacity); + + Eigen::Affine3f transform = Eigen::Affine3f::Identity(); + mImageScreensaver->render(transform); + } + } + + // Check if we need to restart the background audio + if ((mBackgroundAudio) && (Settings::getInstance()->getString("SlideshowScreenSaverBackgroundAudioFile") != "")) + { + if (!mBackgroundAudio->isPlaying()) + { + mBackgroundAudio->play(); + } + } + } else if (mState != STATE_INACTIVE) { Renderer::setMatrix(Eigen::Affine3f::Identity()); - unsigned char opacity = Settings::getInstance()->getString("ScreenSaverBehavior") == "dim" ? 0xA0 : 0xFF; + unsigned char opacity = screensaver_behavior == "dim" ? 0xA0 : 0xFF; Renderer::drawRect(0, 0, Renderer::getScreenWidth(), Renderer::getScreenHeight(), 0x00000000 | opacity); } } -void SystemScreenSaver::countVideos() +unsigned long SystemScreenSaver::countGameListNodes(const char *nodeName) { - if (!mCounted) + unsigned long nodeCount = 0; + std::vector:: iterator it; + for (it = SystemData::sSystemVector.begin(); it != SystemData::sSystemVector.end(); ++it) { - mVideoCount = 0; - mCounted = true; - std::vector:: iterator it; - for (it = SystemData::sSystemVector.begin(); it != SystemData::sSystemVector.end(); ++it) - { - if (!(*it)->isCollection()) - { - pugi::xml_document doc; - pugi::xml_node root; - std::string xmlReadPath = (*it)->getGamelistPath(false); - - if(boost::filesystem::exists(xmlReadPath)) - { - pugi::xml_parse_result result = doc.load_file(xmlReadPath.c_str()); - if (!result) - continue; - root = doc.child("gameList"); - if (!root) - continue; - for(pugi::xml_node fileNode = root.child("game"); fileNode; fileNode = fileNode.next_sibling("game")) - { - pugi::xml_node videoNode = fileNode.child("video"); - if (videoNode) - ++mVideoCount; - } - } - } - } - } -} - -void SystemScreenSaver::pickRandomVideo(std::string& path) -{ - countVideos(); - mCurrentGame = NULL; - if (mVideoCount > 0) - { - int video = (int)(((float)rand() / float(RAND_MAX)) * (float)mVideoCount); - - std::vector:: iterator it; - for (it = SystemData::sSystemVector.begin(); it != SystemData::sSystemVector.end(); ++it) + // We only want images and videos from game systems that are not collections + if (!(*it)->isCollection() && (*it)->isGameSystem()) { pugi::xml_document doc; pugi::xml_node root; @@ -206,58 +277,109 @@ void SystemScreenSaver::pickRandomVideo(std::string& path) continue; for(pugi::xml_node fileNode = root.child("game"); fileNode; fileNode = fileNode.next_sibling("game")) { - pugi::xml_node videoNode = fileNode.child("video"); - if (videoNode) + pugi::xml_node node = fileNode.child(nodeName); + if (node) + ++nodeCount; + } + } + } + } + return nodeCount; +} + +void SystemScreenSaver::countVideos() +{ + if (!mVideosCounted) + { + mVideoCount = countGameListNodes("video"); + mVideosCounted = true; + } +} + +void SystemScreenSaver::countImages() +{ + if (!mImagesCounted) + { + mImageCount = countGameListNodes("image"); + mImagesCounted = true; + } +} + +void SystemScreenSaver::pickGameListNode(unsigned long index, const char *nodeName, std::string& path) +{ + std::vector:: iterator it; + for (it = SystemData::sSystemVector.begin(); it != SystemData::sSystemVector.end(); ++it) + { + pugi::xml_document doc; + pugi::xml_node root; + + // We only want nodes from game systems that are not collections + if (!(*it)->isGameSystem() || (*it)->isCollection()) + continue; + + std::string xmlReadPath = (*it)->getGamelistPath(false); + + if(boost::filesystem::exists(xmlReadPath)) + { + pugi::xml_parse_result result = doc.load_file(xmlReadPath.c_str()); + if (!result) + continue; + root = doc.child("gameList"); + if (!root) + continue; + for(pugi::xml_node fileNode = root.child("game"); fileNode; fileNode = fileNode.next_sibling("game")) + { + pugi::xml_node node = fileNode.child(nodeName); + if (node) + { + // See if this is the desired index + if (index-- == 0) { - // See if this is the randomly selected video - if (video-- == 0) + // Yes. Resolve to a full path + path = resolvePath(node.text().get(), (*it)->getStartPath(), true).generic_string(); + mSystemName = (*it)->getFullName(); + mGameName = fileNode.child("name").text().get(); + + // getting corresponding FileData + + // try the easy way. Should work for the majority of cases, unless in subfolders + FileData* rootFileData = (*it)->getRootFolder(); + std::string gamePath = resolvePath(fileNode.child("path").text().get(), (*it)->getStartPath(), false).string(); + + std::string shortPath = gamePath; + shortPath = shortPath.replace(0, (*it)->getStartPath().length()+1, ""); + + const std::unordered_map& children = rootFileData->getChildrenByFilename(); + std::unordered_map::const_iterator screenSaverGame = children.find(shortPath); + + if (screenSaverGame != children.end()) { - // Yes. Resolve to a full path - path = resolvePath(videoNode.text().get(), (*it)->getStartPath(), true).generic_string(); - mSystemName = (*it)->getFullName(); - mGameName = fileNode.child("name").text().get(); + // Found the corresponding FileData + mCurrentGame = screenSaverGame->second; + } + else + { + // Couldn't find FileData. Going for the full iteration. + // iterate on children + FileType type = GAME; + std::vector allFiles = rootFileData->getFilesRecursive(type); + std::vector::iterator itf; // declare an iterator to a vector of strings - // getting corresponding FileData - - // try the easy way. Should work for the majority of cases, unless in subfolders - FileData* rootFileData = (*it)->getRootFolder(); - std::string gamePath = resolvePath(fileNode.child("path").text().get(), (*it)->getStartPath(), false).string(); - - std::string shortPath = gamePath; - shortPath = shortPath.replace(0, (*it)->getStartPath().length()+1, ""); - - const std::unordered_map& children = rootFileData->getChildrenByFilename(); - std::unordered_map::const_iterator screenSaverGame = children.find(shortPath); - - if (screenSaverGame != children.end()) - { - // Found the corresponding FileData - mCurrentGame = screenSaverGame->second; - } - else - { - // Couldn't find FileData. Going for the full iteration. - // iterate on children - FileType type = GAME; - std::vector allFiles = rootFileData->getFilesRecursive(type); - std::vector::iterator itf; // declare an iterator to a vector of strings - - int i = 0; - for(itf=allFiles.begin() ; itf < allFiles.end(); itf++,i++ ) { - if ((*itf)->getPath() == gamePath) - { - mCurrentGame = (*itf); - break; - } + int i = 0; + for(itf=allFiles.begin() ; itf < allFiles.end(); itf++,i++ ) { + if ((*itf)->getPath() == gamePath) + { + mCurrentGame = (*itf); + break; } } - - // end of getting FileData - if (Settings::getInstance()->getString("ScreenSaverGameInfo") != "never") - writeSubtitle(mGameName.c_str(), mSystemName.c_str(), - (Settings::getInstance()->getString("ScreenSaverGameInfo") == "always")); - return; } + + // end of getting FileData + if (Settings::getInstance()->getString("ScreenSaverGameInfo") != "never") + writeSubtitle(mGameName.c_str(), mSystemName.c_str(), + (Settings::getInstance()->getString("ScreenSaverGameInfo") == "always")); + return; } } } @@ -265,6 +387,97 @@ void SystemScreenSaver::pickRandomVideo(std::string& path) } } +void SystemScreenSaver::pickRandomVideo(std::string& path) +{ + countVideos(); + mCurrentGame = NULL; + if (mVideoCount > 0) + { + int video = (int)(((float)rand() / float(RAND_MAX)) * (float)mVideoCount); + + pickGameListNode(video, "video", path); + } +} + +void SystemScreenSaver::pickRandomGameListImage(std::string& path) +{ + countImages(); + mCurrentGame = NULL; + if (mImageCount > 0) + { + int image = (int)(((float)rand() / float(RAND_MAX)) * (float)mImageCount); + + pickGameListNode(image, "image", path); + } +} + +void SystemScreenSaver::pickRandomCustomImage(std::string& path) +{ + std::string imageDir = Settings::getInstance()->getString("SlideshowScreenSaverImageDir"); + if ((imageDir != "") && (boost::filesystem::exists(imageDir))) + { + std::string imageFilter = Settings::getInstance()->getString("SlideshowScreenSaverImageFilter"); + + std::vector matchingFiles; + + if (Settings::getInstance()->getBool("SlideshowScreenSaverRecurse")) + { + boost::filesystem::recursive_directory_iterator end_iter; + boost::filesystem::recursive_directory_iterator iter(imageDir); + + // TODO: Figure out how to remove this duplication in the else block + for (iter; iter != end_iter; ++iter) + { + if (boost::filesystem::is_regular_file(iter->status())) + { + // If the image filter is empty, or the file extension is in the filter string, + // add it to the matching files list + if ((imageFilter.length() <= 0) || + (imageFilter.find(iter->path().extension().string()) != std::string::npos)) + { + matchingFiles.push_back(iter->path().string()); + } + } + } + } + else + { + boost::filesystem::directory_iterator end_iter; + boost::filesystem::directory_iterator iter(imageDir); + + for (iter; iter != end_iter; ++iter) + { + if (boost::filesystem::is_regular_file(iter->status())) + { + // If the image filter is empty, or the file extension is in the filter string, + // add it to the matching files list + if ((imageFilter.length() <= 0) || + (imageFilter.find(iter->path().extension().string()) != std::string::npos)) + { + matchingFiles.push_back(iter->path().string()); + } + } + } + } + + int fileCount = matchingFiles.size(); + if (fileCount > 0) + { + // get a random index in the range 0 to fileCount (exclusive) + int randomIndex = rand() % fileCount; + path = matchingFiles[randomIndex]; + } + else + { + LOG(LogError) << "Slideshow Screensaver - No image files found\n"; + } + } + else + { + LOG(LogError) << "Slideshow Screensaver - Image directory does not exist: " << imageDir << "\n"; + } +} + void SystemScreenSaver::update(int deltaTime) { // Use this to update the fade value for the current fade stage @@ -302,9 +515,12 @@ void SystemScreenSaver::update(int deltaTime) // If we have a loaded video then update it if (mVideoScreensaver) mVideoScreensaver->update(deltaTime); + if (mImageScreensaver) + mImageScreensaver->update(deltaTime); } void SystemScreenSaver::nextVideo() { + mStopBackgroundAudio = false; stopScreenSaver(); startScreenSaver(); mState = STATE_SCREENSAVER_ACTIVE; @@ -317,12 +533,15 @@ FileData* SystemScreenSaver::getCurrentGame() void SystemScreenSaver::launchGame() { - // launching Game - ViewController::get()->goToGameList(mCurrentGame->getSystem()); - IGameListView* view = ViewController::get()->getGameListView(mCurrentGame->getSystem()).get(); - view->setCursor(mCurrentGame); - if (Settings::getInstance()->getBool("ScreenSaverControls")) + if (mCurrentGame != NULL) { - view->launch(mCurrentGame); + // launching Game + ViewController::get()->goToGameList(mCurrentGame->getSystem()); + IGameListView* view = ViewController::get()->getGameListView(mCurrentGame->getSystem()).get(); + view->setCursor(mCurrentGame); + if (Settings::getInstance()->getBool("ScreenSaverControls")) + { + view->launch(mCurrentGame); + } } } diff --git a/es-app/src/SystemScreenSaver.h b/es-app/src/SystemScreenSaver.h index c1c2dc2b3..4ca3ae23b 100644 --- a/es-app/src/SystemScreenSaver.h +++ b/es-app/src/SystemScreenSaver.h @@ -3,6 +3,8 @@ #include "Window.h" class VideoComponent; +class ImageComponent; +class Sound; // Screensaver implementation for main window class SystemScreenSaver : public Window::ScreenSaver @@ -23,8 +25,13 @@ public: virtual void launchGame(); private: - void countVideos(); - void pickRandomVideo(std::string& path); + unsigned long countGameListNodes(const char *nodeName); + void countVideos(); + void countImages(); + void pickGameListNode(unsigned long index, const char *nodeName, std::string& path); + void pickRandomVideo(std::string& path); + void pickRandomGameListImage(std::string& path); + void pickRandomCustomImage(std::string& path); void input(InputConfig* config, Input input); @@ -36,9 +43,12 @@ private: }; private: - bool mCounted; - unsigned long mVideoCount; - VideoComponent* mVideoScreensaver; + bool mVideosCounted; + unsigned long mVideoCount; + VideoComponent* mVideoScreensaver; + bool mImagesCounted; + unsigned long mImageCount; + ImageComponent* mImageScreensaver; Window* mWindow; STATE mState; float mOpacity; @@ -47,4 +57,6 @@ private: std::string mGameName; std::string mSystemName; int mVideoChangeTime; + std::shared_ptr mBackgroundAudio; + bool mStopBackgroundAudio; }; diff --git a/es-app/src/guis/GuiGeneralScreensaverOptions.cpp b/es-app/src/guis/GuiGeneralScreensaverOptions.cpp new file mode 100644 index 000000000..758e78362 --- /dev/null +++ b/es-app/src/guis/GuiGeneralScreensaverOptions.cpp @@ -0,0 +1,77 @@ +#include "guis/GuiGeneralScreensaverOptions.h" +#include "Window.h" +#include "Settings.h" +#include "PowerSaver.h" +#include "views/ViewController.h" + +#include "components/ButtonComponent.h" +#include "components/SwitchComponent.h" +#include "components/SliderComponent.h" +#include "components/TextComponent.h" +//#include "components/TextEditComponent.h" +#include "components/OptionListComponent.h" +#include "components/MenuComponent.h" +#include "guis/GuiMsgBox.h" +#include "guis/GuiVideoScreensaverOptions.h" +#include "guis/GuiSlideshowScreensaverOptions.h" + +GuiGeneralScreensaverOptions::GuiGeneralScreensaverOptions(Window* window, const char* title) : GuiScreensaverOptions(window, title) +{ + // screensaver time + auto screensaver_time = std::make_shared(mWindow, 0.f, 30.f, 1.f, "m"); + screensaver_time->setValue((float)(Settings::getInstance()->getInt("ScreenSaverTime") / (1000 * 60))); + addWithLabel("SCREENSAVER AFTER", screensaver_time); + addSaveFunc([screensaver_time] { + Settings::getInstance()->setInt("ScreenSaverTime", (int)round(screensaver_time->getValue()) * (1000 * 60)); + PowerSaver::updateTimeouts(); + }); + + // screensaver behavior + auto screensaver_behavior = std::make_shared< OptionListComponent >(mWindow, "SCREENSAVER BEHAVIOR", false); + std::vector screensavers; + screensavers.push_back("dim"); + screensavers.push_back("black"); + screensavers.push_back("random video"); + screensavers.push_back("slideshow"); + for(auto it = screensavers.begin(); it != screensavers.end(); it++) + screensaver_behavior->add(*it, *it, Settings::getInstance()->getString("ScreenSaverBehavior") == *it); + addWithLabel("SCREENSAVER BEHAVIOR", screensaver_behavior); + addSaveFunc([this, screensaver_behavior] { + if (Settings::getInstance()->getString("ScreenSaverBehavior") != "random video" && screensaver_behavior->getSelected() == "random video") { + // if before it wasn't risky but now there's a risk of problems, show warning + mWindow->pushGui(new GuiMsgBox(mWindow, + "The \"Random Video\" screensaver shows videos from your gamelist.\n\nIf you do not have videos, or if in several consecutive attempts the games it selects don't have videos it will default to black.\n\nMore options in the \"UI Settings\" > \"Video Screensaver\" menu.", + "OK", [] { return; })); + } + Settings::getInstance()->setString("ScreenSaverBehavior", screensaver_behavior->getSelected()); + PowerSaver::updateTimeouts(); + }); + + ComponentListRow row; + + // show filtered menu + row.elements.clear(); + row.addElement(std::make_shared(mWindow, "VIDEO SCREENSAVER SETTINGS", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true); + row.addElement(makeArrow(mWindow), false); + row.makeAcceptInputHandler(std::bind(&GuiGeneralScreensaverOptions::openVideoScreensaverOptions, this)); + addRow(row); + + row.elements.clear(); + row.addElement(std::make_shared(mWindow, "SLIDESHOW SCREENSAVER SETTINGS", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true); + row.addElement(makeArrow(mWindow), false); + row.makeAcceptInputHandler(std::bind(&GuiGeneralScreensaverOptions::openSlideshowScreensaverOptions, this)); + addRow(row); +} + +GuiGeneralScreensaverOptions::~GuiGeneralScreensaverOptions() +{ +} + +void GuiGeneralScreensaverOptions::openVideoScreensaverOptions() { + mWindow->pushGui(new GuiVideoScreensaverOptions(mWindow, "VIDEO SCREENSAVER")); +} + +void GuiGeneralScreensaverOptions::openSlideshowScreensaverOptions() { + mWindow->pushGui(new GuiSlideshowScreensaverOptions(mWindow, "SLIDESHOW SCREENSAVER")); +} + diff --git a/es-app/src/guis/GuiGeneralScreensaverOptions.h b/es-app/src/guis/GuiGeneralScreensaverOptions.h new file mode 100644 index 000000000..a48eb890a --- /dev/null +++ b/es-app/src/guis/GuiGeneralScreensaverOptions.h @@ -0,0 +1,18 @@ +#ifndef _GUI_GENERAL_SCREENSAVER_OPTIONS_H_ +#define _GUI_GENERAL_SCREENSAVER_OPTIONS_H_ + +#include "components/MenuComponent.h" +#include "GuiScreensaverOptions.h" + +class GuiGeneralScreensaverOptions : public GuiScreensaverOptions +{ +public: + GuiGeneralScreensaverOptions(Window* window, const char* title); + virtual ~GuiGeneralScreensaverOptions(); + +private: + void openVideoScreensaverOptions(); + void openSlideshowScreensaverOptions(); +}; + +#endif // _GUI_GENERAL_SCREENSAVER_OPTIONS_H_ diff --git a/es-app/src/guis/GuiMenu.cpp b/es-app/src/guis/GuiMenu.cpp index 07298c06f..a9e19e268 100644 --- a/es-app/src/guis/GuiMenu.cpp +++ b/es-app/src/guis/GuiMenu.cpp @@ -7,7 +7,7 @@ #include "PowerSaver.h" #include "guis/GuiMsgBox.h" #include "guis/GuiSettings.h" -#include "guis/GuiScreensaverOptions.h" +#include "guis/GuiGeneralScreensaverOptions.h" #include "guis/GuiCollectionSystemsOptions.h" #include "guis/GuiScraperStart.h" #include "guis/GuiDetectDevice.h" @@ -132,42 +132,12 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MEN [this] { auto s = new GuiSettings(mWindow, "UI SETTINGS"); - // screensaver time - auto screensaver_time = std::make_shared(mWindow, 0.f, 30.f, 1.f, "m"); - screensaver_time->setValue((float)(Settings::getInstance()->getInt("ScreenSaverTime") / (1000 * 60))); - s->addWithLabel("SCREENSAVER AFTER", screensaver_time); - s->addSaveFunc([screensaver_time] { - Settings::getInstance()->setInt("ScreenSaverTime", (int)round(screensaver_time->getValue()) * (1000 * 60)); - PowerSaver::updateTimeouts(); - }); - - // screensaver behavior - auto screensaver_behavior = std::make_shared< OptionListComponent >(mWindow, "SCREENSAVER BEHAVIOR", false); - std::vector screensavers; - screensavers.push_back("dim"); - screensavers.push_back("black"); - screensavers.push_back("random video"); - for(auto it = screensavers.begin(); it != screensavers.end(); it++) - screensaver_behavior->add(*it, *it, Settings::getInstance()->getString("ScreenSaverBehavior") == *it); - s->addWithLabel("SCREENSAVER BEHAVIOR", screensaver_behavior); - s->addSaveFunc([this, screensaver_behavior] { - if (Settings::getInstance()->getString("ScreenSaverBehavior") != "random video" && screensaver_behavior->getSelected() == "random video") { - // if before it wasn't risky but now there's a risk of problems, show warning - mWindow->pushGui(new GuiMsgBox(mWindow, - "The \"Random Video\" screensaver shows videos from your gamelist.\n\nIf you do not have videos, or if in several consecutive attempts the games it selects don't have videos it will default to black.\n\nMore options in the \"UI Settings\" > \"Video Screensaver\" menu.", - "OK", [] { return; })); - } - Settings::getInstance()->setString("ScreenSaverBehavior", screensaver_behavior->getSelected()); - }); - - ComponentListRow row; - - // show filtered menu - row.elements.clear(); - row.addElement(std::make_shared(mWindow, "VIDEO SCREENSAVER SETTINGS", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true); - row.addElement(makeArrow(mWindow), false); - row.makeAcceptInputHandler(std::bind(&GuiMenu::openScreensaverOptions, this)); - s->addRow(row); + ComponentListRow screensaver_row; + screensaver_row.elements.clear(); + screensaver_row.addElement(std::make_shared(mWindow, "SCREENSAVER SETTINGS", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true); + screensaver_row.addElement(makeArrow(mWindow), false); + screensaver_row.makeAcceptInputHandler(std::bind(&GuiMenu::openScreensaverOptions, this)); + s->addRow(screensaver_row); // quick system select (left/right in game list view) auto quick_sys_select = std::make_shared(mWindow); @@ -431,7 +401,7 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MEN } void GuiMenu::openScreensaverOptions() { - mWindow->pushGui(new GuiScreensaverOptions(mWindow, "VIDEO SCREENSAVER")); + mWindow->pushGui(new GuiGeneralScreensaverOptions(mWindow, "SCREENSAVER SETTINGS")); } void GuiMenu::openCollectionSystemSettings() { diff --git a/es-app/src/guis/GuiScreensaverOptions.cpp b/es-app/src/guis/GuiScreensaverOptions.cpp index c057c959d..bfb15421b 100644 --- a/es-app/src/guis/GuiScreensaverOptions.cpp +++ b/es-app/src/guis/GuiScreensaverOptions.cpp @@ -4,63 +4,11 @@ #include "views/ViewController.h" #include "components/ButtonComponent.h" -#include "components/SwitchComponent.h" -#include "components/SliderComponent.h" -#include "components/TextComponent.h" -#include "components/OptionListComponent.h" -#include "components/MenuComponent.h" -#include "guis/GuiMsgBox.h" -#include "PowerSaver.h" GuiScreensaverOptions::GuiScreensaverOptions(Window* window, const char* title) : GuiComponent(window), mMenu(window, title) { addChild(&mMenu); - // timeout to swap videos - auto swap = std::make_shared(mWindow, 10.f, 1000.f, 1.f, "s"); - swap->setValue((float)(Settings::getInstance()->getInt("ScreenSaverSwapVideoTimeout") / (1000))); - addWithLabel("SWAP VIDEO AFTER (SECS)", swap); - addSaveFunc([swap] { - Settings::getInstance()->setInt("ScreenSaverSwapVideoTimeout", (int)round(swap->getValue()) * (1000)); - PowerSaver::updateTimeouts(); - }); - -#ifdef _RPI_ - auto ss_omx = std::make_shared(mWindow); - ss_omx->setState(Settings::getInstance()->getBool("ScreenSaverOmxPlayer")); - addWithLabel("USE OMX PLAYER FOR SCREENSAVER", ss_omx); - addSaveFunc([ss_omx, this] { Settings::getInstance()->setBool("ScreenSaverOmxPlayer", ss_omx->getState()); }); -#endif - - // Allow ScreenSaver Controls - ScreenSaverControls - auto ss_controls = std::make_shared(mWindow); - ss_controls->setState(Settings::getInstance()->getBool("ScreenSaverControls")); - addWithLabel("SCREENSAVER CONTROLS", ss_controls); - addSaveFunc([ss_controls] { Settings::getInstance()->setBool("ScreenSaverControls", ss_controls->getState()); }); - - // Render Video Game Name as subtitles - auto ss_info = std::make_shared< OptionListComponent >(mWindow, "SHOW GAME INFO", false); - std::vector info_type; - info_type.push_back("always"); - info_type.push_back("start & end"); - info_type.push_back("never"); - for(auto it = info_type.begin(); it != info_type.end(); it++) - ss_info->add(*it, *it, Settings::getInstance()->getString("ScreenSaverGameInfo") == *it); - addWithLabel("SHOW GAME INFO ON SCREENSAVER", ss_info); - addSaveFunc([ss_info, this] { Settings::getInstance()->setString("ScreenSaverGameInfo", ss_info->getSelected()); }); - -#ifndef _RPI_ - auto captions_compatibility = std::make_shared(mWindow); - captions_compatibility->setState(Settings::getInstance()->getBool("CaptionsCompatibility")); - addWithLabel("USE COMPATIBLE LOW RESOLUTION FOR CAPTIONS", captions_compatibility); - addSaveFunc([captions_compatibility] { Settings::getInstance()->setBool("CaptionsCompatibility", captions_compatibility->getState()); }); -#endif - - auto stretch_screensaver = std::make_shared(mWindow); - stretch_screensaver->setState(Settings::getInstance()->getBool("StretchVideoOnScreenSaver")); - addWithLabel("STRETCH VIDEO ON SCREENSAVER", stretch_screensaver); - addSaveFunc([stretch_screensaver] { Settings::getInstance()->setBool("StretchVideoOnScreenSaver", stretch_screensaver->getState()); }); - mMenu.addButton("BACK", "go back", [this] { delete this; }); setSize((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight()); @@ -77,24 +25,10 @@ void GuiScreensaverOptions::save() if(!mSaveFuncs.size()) return; -#ifdef _RPI_ - bool startingStatusNotRisky = (Settings::getInstance()->getString("ScreenSaverGameInfo") == "never" || !Settings::getInstance()->getBool("ScreenSaverOmxPlayer")); -#endif - for(auto it = mSaveFuncs.begin(); it != mSaveFuncs.end(); it++) (*it)(); Settings::getInstance()->saveFile(); - -#ifdef _RPI_ - bool endStatusRisky = (Settings::getInstance()->getString("ScreenSaverGameInfo") != "never" && Settings::getInstance()->getBool("ScreenSaverOmxPlayer")); - if (startingStatusNotRisky && endStatusRisky) { - // if before it wasn't risky but now there's a risk of problems, show warning - mWindow->pushGui(new GuiMsgBox(mWindow, - "Using OMX Player and displaying Game Info may result in the video flickering in some TV modes. If that happens, consider:\n\n• Disabling the \"Show Game Info\" option;\n• Disabling \"Overscan\" on the Pi configuration menu might help:\nRetroPie > Raspi-Config > Advanced Options > Overscan > \"No\".\n• Disabling the use of OMX Player for the screensaver.", - "GOT IT!", [] { return; })); - } -#endif } bool GuiScreensaverOptions::input(InputConfig* config, Input input) diff --git a/es-app/src/guis/GuiScreensaverOptions.h b/es-app/src/guis/GuiScreensaverOptions.h index e90dceee5..b7fd98fab 100644 --- a/es-app/src/guis/GuiScreensaverOptions.h +++ b/es-app/src/guis/GuiScreensaverOptions.h @@ -1,3 +1,6 @@ +#ifndef _GUI_SCREENSAVER_OPTIONS_H_ +#define _GUI_SCREENSAVER_OPTIONS_H_ + #include "GuiComponent.h" #include "components/MenuComponent.h" #include "SystemData.h" @@ -9,7 +12,7 @@ public: GuiScreensaverOptions(Window* window, const char* title); virtual ~GuiScreensaverOptions(); // just calls save(); - void save(); + virtual void save(); inline void addRow(const ComponentListRow& row) { mMenu.addRow(row); }; inline void addWithLabel(const std::string& label, const std::shared_ptr& comp) { mMenu.addWithLabel(label, comp); }; inline void addSaveFunc(const std::function& func) { mSaveFuncs.push_back(func); }; @@ -18,7 +21,9 @@ public: std::vector getHelpPrompts() override; HelpStyle getHelpStyle() override; -private: +protected: MenuComponent mMenu; std::vector< std::function > mSaveFuncs; -}; \ No newline at end of file +}; + +#endif // _GUI_SCREENSAVER_OPTIONS_H_ diff --git a/es-app/src/guis/GuiSlideshowScreensaverOptions.cpp b/es-app/src/guis/GuiSlideshowScreensaverOptions.cpp new file mode 100644 index 000000000..d13ce5374 --- /dev/null +++ b/es-app/src/guis/GuiSlideshowScreensaverOptions.cpp @@ -0,0 +1,115 @@ +#include "guis/GuiSlideshowScreensaverOptions.h" +#include "Window.h" +#include "Settings.h" +#include "views/ViewController.h" + +#include "components/SwitchComponent.h" +#include "components/SliderComponent.h" +#include "components/TextComponent.h" +#include "components/OptionListComponent.h" +#include "components/MenuComponent.h" +#include "guis/GuiMsgBox.h" +#include "guis/GuiTextEditPopup.h" +#include "PowerSaver.h" + +GuiSlideshowScreensaverOptions::GuiSlideshowScreensaverOptions(Window* window, const char* title) : GuiScreensaverOptions(window, title) +{ + ComponentListRow row; + + // image duration (seconds) + auto sss_image_sec = std::make_shared(mWindow, 1.f, 60.f, 1.f, "s"); + sss_image_sec->setValue((float)(Settings::getInstance()->getInt("ScreenSaverSwapImageTimeout") / (1000))); + addWithLabel(row, "SWAP IMAGE AFTER (SECS)", sss_image_sec); + addSaveFunc([sss_image_sec] { + int playNextTimeout = (int)round(sss_image_sec->getValue()) * (1000); + Settings::getInstance()->setInt("ScreenSaverSwapImageTimeout", playNextTimeout); + PowerSaver::updateTimeouts(); + }); + + // stretch + auto sss_stretch = std::make_shared(mWindow); + sss_stretch->setState(Settings::getInstance()->getBool("SlideshowScreenSaverStretch")); + addWithLabel(row, "STRETCH IMAGES", sss_stretch); + addSaveFunc([sss_stretch] { + Settings::getInstance()->setBool("SlideshowScreenSaverStretch", sss_stretch->getState()); + }); + + // background audio file + auto sss_bg_audio_file = std::make_shared(mWindow, "", Font::get(FONT_SIZE_SMALL), 0x777777FF); + addEditableTextComponent(row, "BACKGROUND AUDIO", sss_bg_audio_file, Settings::getInstance()->getString("SlideshowScreenSaverBackgroundAudioFile")); + addSaveFunc([sss_bg_audio_file] { + Settings::getInstance()->setString("SlideshowScreenSaverBackgroundAudioFile", sss_bg_audio_file->getValue()); + }); + + // image source + auto sss_custom_source = std::make_shared(mWindow); + sss_custom_source->setState(Settings::getInstance()->getBool("SlideshowScreenSaverCustomImageSource")); + addWithLabel(row, "USE CUSTOM IMAGES", sss_custom_source); + addSaveFunc([sss_custom_source] { Settings::getInstance()->setBool("SlideshowScreenSaverCustomImageSource", sss_custom_source->getState()); }); + + // custom image directory + auto sss_image_dir = std::make_shared(mWindow, "", Font::get(FONT_SIZE_SMALL), 0x777777FF); + addEditableTextComponent(row, "CUSTOM IMAGE DIR", sss_image_dir, Settings::getInstance()->getString("SlideshowScreenSaverImageDir")); + addSaveFunc([sss_image_dir] { + Settings::getInstance()->setString("SlideshowScreenSaverImageDir", sss_image_dir->getValue()); + }); + + // recurse custom image directory + auto sss_recurse = std::make_shared(mWindow); + sss_recurse->setState(Settings::getInstance()->getBool("SlideshowScreenSaverRecurse")); + addWithLabel(row, "CUSTOM IMAGE DIR RECURSIVE", sss_recurse); + addSaveFunc([sss_recurse] { + Settings::getInstance()->setBool("SlideshowScreenSaverRecurse", sss_recurse->getState()); + }); + + // custom image filter + auto sss_image_filter = std::make_shared(mWindow, "", Font::get(FONT_SIZE_SMALL), 0x777777FF); + addEditableTextComponent(row, "CUSTOM IMAGE FILTER", sss_image_filter, Settings::getInstance()->getString("SlideshowScreenSaverImageFilter")); + addSaveFunc([sss_image_filter] { + Settings::getInstance()->setString("SlideshowScreenSaverImageFilter", sss_image_filter->getValue()); + }); +} + +GuiSlideshowScreensaverOptions::~GuiSlideshowScreensaverOptions() +{ +} + +void GuiSlideshowScreensaverOptions::addWithLabel(ComponentListRow row, const std::string label, std::shared_ptr component) +{ + row.elements.clear(); + + auto lbl = std::make_shared(mWindow, strToUpper(label), Font::get(FONT_SIZE_MEDIUM), 0x777777FF); + row.addElement(lbl, true); // label + + row.addElement(component, false, true); + + addRow(row); +} + +void GuiSlideshowScreensaverOptions::addEditableTextComponent(ComponentListRow row, const std::string label, std::shared_ptr ed, std::string value) +{ + row.elements.clear(); + + auto lbl = std::make_shared(mWindow, strToUpper(label), Font::get(FONT_SIZE_MEDIUM), 0x777777FF); + row.addElement(lbl, true); // label + + row.addElement(ed, true); + + auto spacer = std::make_shared(mWindow); + spacer->setSize(Renderer::getScreenWidth() * 0.005f, 0); + row.addElement(spacer, false); + + auto bracket = std::make_shared(mWindow); + bracket->setImage(":/arrow.svg"); + bracket->setResize(Eigen::Vector2f(0, lbl->getFont()->getLetterHeight())); + row.addElement(bracket, false); + + auto updateVal = [ed](const std::string& newVal) { ed->setValue(newVal); }; // ok callback (apply new value to ed) + row.makeAcceptInputHandler([this, label, ed, updateVal] { + mWindow->pushGui(new GuiTextEditPopup(mWindow, label, ed->getValue(), updateVal, false)); + }); + + assert(ed); + addRow(row); + ed->setValue(value); +} diff --git a/es-app/src/guis/GuiSlideshowScreensaverOptions.h b/es-app/src/guis/GuiSlideshowScreensaverOptions.h new file mode 100644 index 000000000..c3f5a63bc --- /dev/null +++ b/es-app/src/guis/GuiSlideshowScreensaverOptions.h @@ -0,0 +1,18 @@ +#ifndef _GUI_SLIDESHOW_SCREENSAVER_OPTIONS_H_ +#define _GUI_SLIDESHOW_SCREENSAVER_OPTIONS_H_ + +#include "components/MenuComponent.h" +#include "GuiScreensaverOptions.h" + +class GuiSlideshowScreensaverOptions : public GuiScreensaverOptions +{ +public: + GuiSlideshowScreensaverOptions(Window* window, const char* title); + virtual ~GuiSlideshowScreensaverOptions(); + +private: + void addWithLabel(ComponentListRow row, const std::string label, std::shared_ptr component); + void addEditableTextComponent(ComponentListRow row, const std::string label, std::shared_ptr ed, std::string value); +}; + +#endif // _GUI_SLIDESHOW_SCREENSAVER_OPTIONS_H_ diff --git a/es-app/src/guis/GuiVideoScreensaverOptions.cpp b/es-app/src/guis/GuiVideoScreensaverOptions.cpp new file mode 100644 index 000000000..efa940cfc --- /dev/null +++ b/es-app/src/guis/GuiVideoScreensaverOptions.cpp @@ -0,0 +1,82 @@ +#include "guis/GuiVideoScreensaverOptions.h" +#include "Window.h" +#include "Settings.h" +#include "views/ViewController.h" + +#include "components/SwitchComponent.h" +#include "components/SliderComponent.h" +#include "components/OptionListComponent.h" +#include "components/MenuComponent.h" +#include "guis/GuiMsgBox.h" +#include "PowerSaver.h" + +GuiVideoScreensaverOptions::GuiVideoScreensaverOptions(Window* window, const char* title) : GuiScreensaverOptions(window, title) +{ + // timeout to swap videos + auto swap = std::make_shared(mWindow, 10.f, 1000.f, 1.f, "s"); + swap->setValue((float)(Settings::getInstance()->getInt("ScreenSaverSwapVideoTimeout") / (1000))); + addWithLabel("SWAP VIDEO AFTER (SECS)", swap); + addSaveFunc([swap] { + int playNextTimeout = (int)round(swap->getValue()) * (1000); + Settings::getInstance()->setInt("ScreenSaverSwapVideoTimeout", playNextTimeout); + PowerSaver::updateTimeouts(); + }); + +#ifdef _RPI_ + auto ss_omx = std::make_shared(mWindow); + ss_omx->setState(Settings::getInstance()->getBool("ScreenSaverOmxPlayer")); + addWithLabel("USE OMX PLAYER FOR SCREENSAVER", ss_omx); + addSaveFunc([ss_omx, this] { Settings::getInstance()->setBool("ScreenSaverOmxPlayer", ss_omx->getState()); }); +#endif + + // Allow ScreenSaver Controls - ScreenSaverControls + auto ss_controls = std::make_shared(mWindow); + ss_controls->setState(Settings::getInstance()->getBool("ScreenSaverControls")); + addWithLabel("SCREENSAVER CONTROLS", ss_controls); + addSaveFunc([ss_controls] { Settings::getInstance()->setBool("ScreenSaverControls", ss_controls->getState()); }); + + // Render Video Game Name as subtitles + auto ss_info = std::make_shared< OptionListComponent >(mWindow, "SHOW GAME INFO", false); + std::vector info_type; + info_type.push_back("always"); + info_type.push_back("start & end"); + info_type.push_back("never"); + for(auto it = info_type.begin(); it != info_type.end(); it++) + ss_info->add(*it, *it, Settings::getInstance()->getString("ScreenSaverGameInfo") == *it); + addWithLabel("SHOW GAME INFO ON SCREENSAVER", ss_info); + addSaveFunc([ss_info, this] { Settings::getInstance()->setString("ScreenSaverGameInfo", ss_info->getSelected()); }); + +#ifndef _RPI_ + auto captions_compatibility = std::make_shared(mWindow); + captions_compatibility->setState(Settings::getInstance()->getBool("CaptionsCompatibility")); + addWithLabel("USE COMPATIBLE LOW RESOLUTION FOR CAPTIONS", captions_compatibility); + addSaveFunc([captions_compatibility] { Settings::getInstance()->setBool("CaptionsCompatibility", captions_compatibility->getState()); }); +#endif + + auto stretch_screensaver = std::make_shared(mWindow); + stretch_screensaver->setState(Settings::getInstance()->getBool("StretchVideoOnScreenSaver")); + addWithLabel("STRETCH VIDEO ON SCREENSAVER", stretch_screensaver); + addSaveFunc([stretch_screensaver] { Settings::getInstance()->setBool("StretchVideoOnScreenSaver", stretch_screensaver->getState()); }); +} + +GuiVideoScreensaverOptions::~GuiVideoScreensaverOptions() +{ +} + +void GuiVideoScreensaverOptions::save() +{ +#ifdef _RPI_ + bool startingStatusNotRisky = (Settings::getInstance()->getString("ScreenSaverGameInfo") == "never" || !Settings::getInstance()->getBool("ScreenSaverOmxPlayer")); +#endif + GuiScreensaverOptions::save(); + +#ifdef _RPI_ + bool endStatusRisky = (Settings::getInstance()->getString("ScreenSaverGameInfo") != "never" && Settings::getInstance()->getBool("ScreenSaverOmxPlayer")); + if (startingStatusNotRisky && endStatusRisky) { + // if before it wasn't risky but now there's a risk of problems, show warning + mWindow->pushGui(new GuiMsgBox(mWindow, + "Using OMX Player and displaying Game Info may result in the video flickering in some TV modes. If that happens, consider:\n\n• Disabling the \"Show Game Info\" option;\n• Disabling \"Overscan\" on the Pi configuration menu might help:\nRetroPie > Raspi-Config > Advanced Options > Overscan > \"No\".\n• Disabling the use of OMX Player for the screensaver.", + "GOT IT!", [] { return; })); + } +#endif +} diff --git a/es-app/src/guis/GuiVideoScreensaverOptions.h b/es-app/src/guis/GuiVideoScreensaverOptions.h new file mode 100644 index 000000000..260c4fd16 --- /dev/null +++ b/es-app/src/guis/GuiVideoScreensaverOptions.h @@ -0,0 +1,16 @@ +#ifndef _GUI_VIDEO_SCREENSAVER_OPTIONS_H_ +#define _GUI_VIDEO_SCREENSAVER_OPTIONS_H_ + +#include "components/MenuComponent.h" +#include "GuiScreensaverOptions.h" + +class GuiVideoScreensaverOptions : public GuiScreensaverOptions +{ +public: + GuiVideoScreensaverOptions(Window* window, const char* title); + virtual ~GuiVideoScreensaverOptions(); + + void save() override; +}; + +#endif // _GUI_VIDEO_SCREENSAVER_OPTIONS_H_ diff --git a/es-core/src/PowerSaver.cpp b/es-core/src/PowerSaver.cpp index 5804d7cf3..cfa648856 100644 --- a/es-core/src/PowerSaver.cpp +++ b/es-core/src/PowerSaver.cpp @@ -27,6 +27,8 @@ void PowerSaver::loadWakeupTime() std::string behaviour = Settings::getInstance()->getString("ScreenSaverBehavior"); if (behaviour == "random video") mWakeupTimeout = Settings::getInstance()->getInt("ScreenSaverSwapVideoTimeout") - getMode(); + else if (behaviour == "slideshow") + mWakeupTimeout = Settings::getInstance()->getInt("ScreenSaverSwapImageTimeout") - getMode(); else // Dim and Blank mWakeupTimeout = -1; } diff --git a/es-core/src/Settings.cpp b/es-core/src/Settings.cpp index 6f36432a3..1397dee3b 100644 --- a/es-core/src/Settings.cpp +++ b/es-core/src/Settings.cpp @@ -88,6 +88,14 @@ void Settings::setDefaults() mBoolMap["StretchVideoOnScreenSaver"] = false; mStringMap["PowerSaverMode"] = "disabled"; + mIntMap["ScreenSaverSwapImageTimeout"] = 10000; + mBoolMap["SlideshowScreenSaverStretch"] = false; + mStringMap["SlideshowScreenSaverBackgroundAudioFile"] = getHomePath() + "/.emulationstation/slideshow/audio/slideshow_bg.wav"; + mBoolMap["SlideshowScreenSaverCustomImageSource"] = false; + mStringMap["SlideshowScreenSaverImageDir"] = getHomePath() + "/.emulationstation/slideshow/image"; + mStringMap["SlideshowScreenSaverImageFilter"] = ".png,.jpg"; + mBoolMap["SlideshowScreenSaverRecurse"] = false; + // This setting only applies to raspberry pi but set it for all platforms so // we don't get a warning if we encounter it on a different platform mBoolMap["VideoOmxPlayer"] = false;