From cf8ce151ddae0bf823937d34f0e7a553abd3b668 Mon Sep 17 00:00:00 2001 From: Leon Styhre Date: Tue, 7 Feb 2023 18:14:16 +0100 Subject: [PATCH] The application startup can now be aborted via an OS signal or using the configured keyboard quit shortcut. --- es-app/src/SystemData.cpp | 12 ++-- es-app/src/SystemData.h | 5 +- es-app/src/main.cpp | 106 +++++++++++++++------------- es-app/src/views/ViewController.cpp | 8 ++- 4 files changed, 75 insertions(+), 56 deletions(-) diff --git a/es-app/src/SystemData.cpp b/es-app/src/SystemData.cpp index 6696c2245..8d598770d 100644 --- a/es-app/src/SystemData.cpp +++ b/es-app/src/SystemData.cpp @@ -15,6 +15,7 @@ #include "FileFilterIndex.h" #include "FileSorts.h" #include "GamelistFileParser.h" +#include "InputManager.h" #include "Log.h" #include "Settings.h" #include "ThemeData.h" @@ -32,9 +33,6 @@ #include #include -std::vector SystemData::sSystemVector; -std::unique_ptr SystemData::sFindRules; - FindRules::FindRules() { LOG(LogInfo) << "Loading emulator find rules..."; @@ -544,7 +542,13 @@ bool SystemData::loadConfig() system = system.next_sibling("system")) { // Poll events so that the OS doesn't think the application is hanging on startup, // this is required as the main application loop hasn't started yet. - while (SDL_PollEvent(&event)) {}; + while (SDL_PollEvent(&event)) { + InputManager::getInstance().parseEvent(event); + if (event.type == SDL_QUIT) { + sStartupExitSignal = true; + return true; + } + }; std::string name; std::string fullname; diff --git a/es-app/src/SystemData.h b/es-app/src/SystemData.h index 41b0e4011..33d7cdfee 100644 --- a/es-app/src/SystemData.h +++ b/es-app/src/SystemData.h @@ -114,8 +114,9 @@ public: // Generates the game system directories and information files based on es_systems.xml. static bool createSystemDirectories(); - static std::vector sSystemVector; - static std::unique_ptr sFindRules; + static inline std::vector sSystemVector; + static inline std::unique_ptr sFindRules; + static inline bool sStartupExitSignal {false}; const bool isCollection() const { return mIsCollectionSystem; } const bool isCustomCollection() const { return mIsCustomCollectionSystem; } diff --git a/es-app/src/main.cpp b/es-app/src/main.cpp index a544770d6..9c42380d3 100644 --- a/es-app/src/main.cpp +++ b/es-app/src/main.cpp @@ -704,70 +704,78 @@ int main(int argc, char* argv[]) ThemeData::populateThemeSets(); loadSystemsReturnCode loadSystemsStatus {loadSystemConfigFile()}; - if (loadSystemsStatus) { - // If there was an issue parsing the es_systems.xml file, display an error message. - // If there were no game files found, give the option to the user to quit or to - // configure a different ROM directory as well as to generate the game systems - // directory structure. - if (loadSystemsStatus == INVALID_FILE) { - ViewController::getInstance()->invalidSystemsFileDialog(); + if (!SystemData::sStartupExitSignal) { + if (loadSystemsStatus) { + // If there was an issue parsing the es_systems.xml file, display an error message. + // If there were no game files found, give the option to the user to quit or to + // configure a different ROM directory as well as to generate the game systems + // directory structure. + if (loadSystemsStatus == INVALID_FILE) { + ViewController::getInstance()->invalidSystemsFileDialog(); + } + else if (loadSystemsStatus == NO_ROMS) { + ViewController::getInstance()->noGamesDialog(); + } } - else if (loadSystemsStatus == NO_ROMS) { - ViewController::getInstance()->noGamesDialog(); + + // Check if any of the enabled systems have an invalid alternative emulator entry, + // which means that a label is present in the gamelist.xml file which is not matching + // any command tag in es_systems.xml. + for (auto system : SystemData::sSystemVector) { + if (system->getAlternativeEmulator().substr(0, 9) == "") { + ViewController::getInstance()->invalidAlternativeEmulatorDialog(); + break; + } } + + // Don't generate controller events while we're loading. + SDL_GameControllerEventState(SDL_DISABLE); + + // Preload system view and all gamelist views. + ViewController::getInstance()->preload(); } - // Check if any of the enabled systems has an invalid alternative emulator entry, - // which means that a label is present in the gamelist.xml file which is not matching - // any command tag in es_systems.xml. - for (auto system : SystemData::sSystemVector) { - if (system->getAlternativeEmulator().substr(0, 9) == "") { - ViewController::getInstance()->invalidAlternativeEmulatorDialog(); - break; + if (!SystemData::sStartupExitSignal) { + if (loadSystemsStatus == loadSystemsReturnCode::LOADING_OK) { + LOG(LogInfo) << "Finished loading theme set \"" << ThemeData::getCurrentThemeSetName() + << "\""; } - } - // Don't generate controller events while we're loading. - SDL_GameControllerEventState(SDL_DISABLE); - - // Preload what we can right away instead of waiting for the user to select it. - // This makes for no delays when accessing content, but a longer startup time. - ViewController::getInstance()->preload(); - - if (loadSystemsStatus == loadSystemsReturnCode::LOADING_OK) { - LOG(LogInfo) << "Finished loading theme set \"" << ThemeData::getCurrentThemeSetName() - << "\""; - } - - // Open the input configuration GUI if the flag to force this was passed from the command line. - if (!loadSystemsStatus) { - if (forceInputConfig) { - window->pushGui(new GuiDetectDevice( - false, true, [] { ViewController::getInstance()->goToStart(true); })); + // Open the input configuration GUI if the force flag was passed from the command line. + if (!loadSystemsStatus) { + if (forceInputConfig) { + window->pushGui(new GuiDetectDevice( + false, true, [] { ViewController::getInstance()->goToStart(true); })); + } + else { + ViewController::getInstance()->goToStart(true); + } } - else { - ViewController::getInstance()->goToStart(true); - } - } - // Generate controller events since we're done loading. - SDL_GameControllerEventState(SDL_ENABLE); + // Generate controller events since we're done loading. + SDL_GameControllerEventState(SDL_ENABLE); - lastTime = SDL_GetTicks(); + lastTime = SDL_GetTicks(); - LOG(LogInfo) << "Application startup time: " - << std::chrono::duration_cast( - std::chrono::system_clock::now() - applicationStartTime) - .count() - << " ms"; + LOG(LogInfo) << "Application startup time: " + << std::chrono::duration_cast( + std::chrono::system_clock::now() - applicationStartTime) + .count() + << " ms"; - // Main application loop. + // Main application loop. + if (!SystemData::sStartupExitSignal) { #if defined(__EMSCRIPTEN__) - emscripten_set_main_loop(&applicationLoop, 0, 1); + emscripten_set_main_loop(&applicationLoop, 0, 1); #else - applicationLoop(); + applicationLoop(); #endif + } + } + else { + LOG(LogInfo) << "Exit signal received, aborting application startup"; + } while (window->peekGui() != ViewController::getInstance()) delete window->peekGui(); diff --git a/es-app/src/views/ViewController.cpp b/es-app/src/views/ViewController.cpp index 879e1f02e..049a06b48 100644 --- a/es-app/src/views/ViewController.cpp +++ b/es-app/src/views/ViewController.cpp @@ -1101,7 +1101,13 @@ void ViewController::preload() it != SystemData::sSystemVector.cend(); ++it) { // Poll events so that the OS doesn't think the application is hanging on startup, // this is required as the main application loop hasn't started yet. - while (SDL_PollEvent(&event)) {}; + while (SDL_PollEvent(&event)) { + InputManager::getInstance().parseEvent(event); + if (event.type == SDL_QUIT) { + SystemData::sStartupExitSignal = true; + return; + } + }; const std::string entryType {(*it)->isCustomCollection() ? "custom collection" : "system"}; LOG(LogDebug) << "ViewController::preload(): Populating gamelist for " << entryType << " \""