diff --git a/es-app/src/EmulationStation.h b/es-app/src/EmulationStation.h index ba400e1ae..5e8cec120 100644 --- a/es-app/src/EmulationStation.h +++ b/es-app/src/EmulationStation.h @@ -1,3 +1,9 @@ +// +// EmulationStation.h +// +// Version and build information. +// + #pragma once #ifndef ES_APP_EMULATION_STATION_H #define ES_APP_EMULATION_STATION_H diff --git a/es-app/src/guis/GuiMenu.cpp b/es-app/src/guis/GuiMenu.cpp index 565d7a2b0..3af2da11b 100644 --- a/es-app/src/guis/GuiMenu.cpp +++ b/es-app/src/guis/GuiMenu.cpp @@ -117,17 +117,17 @@ void GuiMenu::openSoundSettings() setVolume((int)Math::round(volume->getValue())); }); if (UIModeController::getInstance()->isUIModeFull()) { -#if defined(__linux__) + #if defined(__linux__) // audio card auto audio_card = std::make_shared< OptionListComponent >(mWindow, "AUDIO CARD", false); std::vector audio_cards; -#ifdef _RPI_ + #ifdef _RPI_ // RPi Specific Audio Cards audio_cards.push_back("local"); audio_cards.push_back("hdmi"); audio_cards.push_back("both"); -#endif + #endif audio_cards.push_back("default"); audio_cards.push_back("sysdefault"); audio_cards.push_back("dmix"); @@ -172,7 +172,7 @@ void GuiMenu::openSoundSettings() VolumeControl::getInstance()->deinit(); VolumeControl::getInstance()->init(); }); -#endif + #endif // Video audio. auto video_audio = std::make_shared(mWindow); @@ -196,7 +196,7 @@ void GuiMenu::openSoundSettings() Settings::getInstance()->setBool("EnableSounds", sounds_enabled->getState()); }); -#ifdef _RPI_ + #ifdef _RPI_ // OMX player Audio Device auto omx_audio_dev = std::make_shared< OptionListComponent >(mWindow, "OMX PLAYER AUDIO DEVICE", false); @@ -220,7 +220,7 @@ void GuiMenu::openSoundSettings() if (Settings::getInstance()->getString("OMXAudioDev") != omx_audio_dev->getSelected()) Settings::getInstance()->setString("OMXAudioDev", omx_audio_dev->getSelected()); }); -#endif + #endif } mWindow->pushGui(s); @@ -490,6 +490,26 @@ void GuiMenu::openOtherSettings() PowerSaver::init(); }); + #ifdef _RPI_ + // Video Player - VideoOmxPlayer. + auto omx_player = std::make_shared(mWindow); + omx_player->setState(Settings::getInstance()->getBool("VideoOmxPlayer")); + s->addWithLabel("USE OMX PLAYER (HW ACCELERATED)", omx_player); + s->addSaveFunc([omx_player] + { + // Need to reload all views to re-create the right video components. + bool needReload = false; + if (Settings::getInstance()->getBool("VideoOmxPlayer") != omx_player->getState()) + needReload = true; + + Settings::getInstance()->setBool("VideoOmxPlayer", omx_player->getState()); + + if (needReload) + ViewController::get()->reloadAll(); + }); + + #endif + // When to save game metadata. auto gamelistsSaveMode = std::make_shared< OptionListComponent >(mWindow, "SAVE METADATA", false); @@ -522,7 +542,7 @@ void GuiMenu::openOtherSettings() auto local_art = std::make_shared(mWindow); local_art->setState(Settings::getInstance()->getBool("LocalArt")); - s->addWithLabel("SEARCH FOR GAME ART IN \'%ROM%/IMAGES\'", local_art); + s->addWithLabel("SEARCH FOR GAME ART IN ROM DIRECTORIES", local_art); s->addSaveFunc([local_art] { Settings::getInstance()-> setBool("LocalArt", local_art->getState()); }); @@ -554,26 +574,6 @@ void GuiMenu::openOtherSettings() s->addSaveFunc([show_poweroffsystem] { Settings::getInstance()->setBool("ShowPoweroffSystem", show_poweroffsystem->getState()); }); -#ifdef _RPI_ - // Video Player - VideoOmxPlayer. - auto omx_player = std::make_shared(mWindow); - omx_player->setState(Settings::getInstance()->getBool("VideoOmxPlayer")); - s->addWithLabel("USE OMX PLAYER (HW ACCELERATED)", omx_player); - s->addSaveFunc([omx_player] - { - // Need to reload all views to re-create the right video components. - bool needReload = false; - if (Settings::getInstance()->getBool("VideoOmxPlayer") != omx_player->getState()) - needReload = true; - - Settings::getInstance()->setBool("VideoOmxPlayer", omx_player->getState()); - - if (needReload) - ViewController::get()->reloadAll(); - }); - -#endif - mWindow->pushGui(s); } diff --git a/es-app/src/main.cpp b/es-app/src/main.cpp index 73759063e..4ced577d1 100644 --- a/es-app/src/main.cpp +++ b/es-app/src/main.cpp @@ -1,5 +1,18 @@ -//EmulationStation, a graphical front-end for ROM browsing. Created by Alec "Aloshi" Lofquist. -//http://www.aloshi.com +// +// EmulationStation Desktop Edition, an emulator front-end +// with controller navigation and theming support. +// +// Originally created by Alec "Aloshi" Lofquist. +// http://www.aloshi.com +// Improved and extended by the RetroPie community. +// Desktop Edition fork by Leon Styhre. +// +// main.cpp +// +// Main program loop. Interprets command-line arguments, checks for the +// home folder and es_settings.cfg configuration file, sets up the application +// environment and starts listening to SDL events. +// #include "guis/GuiDetectDevice.h" #include "guis/GuiMsgBox.h" @@ -33,29 +46,37 @@ bool parseArgs(int argc, char* argv[]) { Utils::FileSystem::setExePath(argv[0]); - // We need to process --home before any call to Settings::getInstance(), because settings are loaded from homepath - for(int i = 1; i < argc; i++) - { - if(strcmp(argv[i], "--home") == 0) - { - if(i >= argc - 1) - { - std::cerr << "Invalid home path supplied."; + // We need to process --home before any call to Settings::getInstance(), + // because settings are loaded from the home path. + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "--home") == 0) { + if (i >= argc - 1) { + std::cerr << "Error: No home path supplied with \'--home'.\n"; return false; } - + if(!Utils::FileSystem::exists(argv[i + 1])) { + std::cerr << "Error: Home path \'" << argv[i + 1] << "\' does not exist.\n"; + return false; + } + if(Utils::FileSystem::isRegularFile(argv[i + 1])) { + std::cerr << "Error: Home path \'" << argv[i + 1] << + "\' is a file and not a directory.\n"; + return false; + } Utils::FileSystem::setHomePath(argv[i + 1]); break; } } - for(int i = 1; i < argc; i++) - { - if(strcmp(argv[i], "--resolution") == 0) - { - if(i >= argc - 2) - { - std::cerr << "Invalid resolution supplied."; + for(int i = 1; i < argc; i++) { + // Skip past --home flag as we already processed it. + if (strcmp(argv[i], "--home") == 0) { + i++; + continue; + } + if (strcmp(argv[i], "--resolution") == 0) { + if (i >= argc - 2) { + std::cerr << "Error: Invalid resolution values supplied.\n"; return false; } @@ -64,11 +85,10 @@ bool parseArgs(int argc, char* argv[]) i += 2; // skip the argument value Settings::getInstance()->setInt("WindowWidth", width); Settings::getInstance()->setInt("WindowHeight", height); - }else if(strcmp(argv[i], "--screensize") == 0) - { - if(i >= argc - 2) - { - std::cerr << "Invalid screensize supplied."; + } + else if (strcmp(argv[i], "--screensize") == 0) { + if (i >= argc - 2) { + std::cerr << "Error: Invalid screensize values supplied.\n"; return false; } @@ -77,11 +97,10 @@ bool parseArgs(int argc, char* argv[]) i += 2; // skip the argument value Settings::getInstance()->setInt("ScreenWidth", width); Settings::getInstance()->setInt("ScreenHeight", height); - }else if(strcmp(argv[i], "--screenoffset") == 0) - { - if(i >= argc - 2) - { - std::cerr << "Invalid screenoffset supplied."; + } + else if (strcmp(argv[i], "--screenoffset") == 0) { + if (i >= argc - 2) { + std::cerr << "Error: Invalid screenoffset values supplied.\n"; return false; } @@ -90,117 +109,126 @@ bool parseArgs(int argc, char* argv[]) i += 2; // skip the argument value Settings::getInstance()->setInt("ScreenOffsetX", x); Settings::getInstance()->setInt("ScreenOffsetY", y); - }else if (strcmp(argv[i], "--screenrotate") == 0) - { - if (i >= argc - 1) - { - std::cerr << "Invalid screenrotate supplied."; + } + else if (strcmp(argv[i], "--screenrotate") == 0) { + if (i >= argc - 1) { + std::cerr << "Error: Invalid screenrotate value supplied.\n"; return false; } int rotate = atoi(argv[i + 1]); ++i; // skip the argument value Settings::getInstance()->setInt("ScreenRotate", rotate); - }else if(strcmp(argv[i], "--gamelist-only") == 0) - { + } + else if (strcmp(argv[i], "--max-vram") == 0) { + if (i >= argc - 1) { + std::cerr << "Error: Invalid VRAM value supplied.\n"; + return false; + } + int maxVRAM = atoi(argv[i + 1]); + Settings::getInstance()->setInt("MaxVRAM", maxVRAM); + ++i; // skip the argument value + } + else if (strcmp(argv[i], "--gamelist-only") == 0) { Settings::getInstance()->setBool("ParseGamelistOnly", true); - }else if(strcmp(argv[i], "--ignore-gamelist") == 0) - { + } + else if (strcmp(argv[i], "--ignore-gamelist") == 0) { Settings::getInstance()->setBool("IgnoreGamelist", true); - }else if(strcmp(argv[i], "--show-hidden-files") == 0) - { + } + else if (strcmp(argv[i], "--show-hidden-files") == 0) { Settings::getInstance()->setBool("ShowHiddenFiles", true); - }else if(strcmp(argv[i], "--draw-framerate") == 0) - { + } + else if (strcmp(argv[i], "--draw-framerate") == 0) { Settings::getInstance()->setBool("DrawFramerate", true); - }else if(strcmp(argv[i], "--no-exit") == 0) - { + } + else if (strcmp(argv[i], "--no-exit") == 0) { Settings::getInstance()->setBool("ShowExit", false); - }else if(strcmp(argv[i], "--no-splash") == 0) - { + } + else if (strcmp(argv[i], "--no-splash") == 0) { Settings::getInstance()->setBool("SplashScreen", false); - }else if(strcmp(argv[i], "--debug") == 0) - { + } + else if (strcmp(argv[i], "--debug") == 0) { Settings::getInstance()->setBool("Debug", true); Settings::getInstance()->setBool("HideConsole", false); Log::setReportingLevel(LogDebug); - }else if(strcmp(argv[i], "--fullscreen-normal") == 0) - { - Settings::getInstance()->setString("FullscreenMode", "normal"); - }else if(strcmp(argv[i], "--fullscreen-borderless") == 0) - { - Settings::getInstance()->setString("FullscreenMode", "borderless"); - }else if(strcmp(argv[i], "--windowed") == 0) - { - Settings::getInstance()->setBool("Windowed", true); - }else if(strcmp(argv[i], "--vsync") == 0) - { - bool vsync = (strcmp(argv[i + 1], "on") == 0 || strcmp(argv[i + 1], "1") == 0) ? true : false; - Settings::getInstance()->setBool("VSync", vsync); - i++; // skip vsync value -// }else if(strcmp(argv[i], "--scrape") == 0) -// { -// scrape_cmdline = true; - }else if(strcmp(argv[i], "--max-vram") == 0) - { - int maxVRAM = atoi(argv[i + 1]); - Settings::getInstance()->setInt("MaxVRAM", maxVRAM); } - else if (strcmp(argv[i], "--force-kiosk") == 0) - { + else if (strcmp(argv[i], "--fullscreen-normal") == 0) { + Settings::getInstance()->setString("FullscreenMode", "normal"); + } + else if (strcmp(argv[i], "--fullscreen-borderless") == 0) { + Settings::getInstance()->setString("FullscreenMode", "borderless"); + } + else if (strcmp(argv[i], "--windowed") == 0) { + Settings::getInstance()->setBool("Windowed", true); + } + else if (strcmp(argv[i], "--vsync") == 0) { + bool vsync = (strcmp(argv[i + 1], "on") == 0 || + strcmp(argv[i + 1], "1") == 0) ? true : false; + Settings::getInstance()->setBool("VSync", vsync); + i++; // Skip vsync value. +// } +// else if (strcmp(argv[i], "--scrape") == 0) { +// scrape_cmdline = true; + } + else if (strcmp(argv[i], "--force-kiosk") == 0) { Settings::getInstance()->setBool("ForceKiosk", true); } - else if (strcmp(argv[i], "--force-kid") == 0) - { + else if (strcmp(argv[i], "--force-kid") == 0) { Settings::getInstance()->setBool("ForceKid", true); } - else if (strcmp(argv[i], "--force-disable-filters") == 0) - { + else if (strcmp(argv[i], "--force-disable-filters") == 0) { Settings::getInstance()->setBool("ForceDisableFilters", true); } - else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) - { + else if (strcmp(argv[i], "--version") == 0 || strcmp(argv[i], "-v") == 0) { + std::cout << + "EmulationStation Desktop Edition v" << PROGRAM_VERSION_STRING << "\n"; + return false; + } + else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { #ifdef WIN32 - // This is a bit of a hack, but otherwise output will go to nowhere - // when the application is compiled with the "WINDOWS" subsystem (which we usually are). + // This is a bit of a hack, but otherwise output will go to nowhere when the + // application is compiled with the "WINDOWS" subsystem (which we usually are). // If you're an experienced Windows programmer and know how to do this // the right way, please submit a pull request! AttachConsole(ATTACH_PARENT_PROCESS); freopen("CONOUT$", "wb", stdout); #endif std::cout << - "EmulationStation Desktop Edition, an emulator front-end with controller navigation and theming support.\n" - "Version " << PROGRAM_VERSION_STRING << ", built " << PROGRAM_BUILT_STRING << "\n\n" - "Command line arguments:\n" - "--resolution [width] [height] Try and force a particular resolution\n" - "--gamelist-only Skip automatic game search, only read from gamelist.xml\n" - "--ignore-gamelist Ignore the gamelist (useful for troubleshooting)\n" - "--draw-framerate Display the framerate\n" - "--no-exit Don't show the exit option in the menu\n" - "--no-splash Don't show the splash screen\n" - "--debug More logging, show console on Windows\n" -// "--scrape Scrape using command line interface\n" - "--windowed Not fullscreen, should be used with --resolution\n" - "--fullscreen-normal Run in normal fullscreen mode\n" - "--fullscreen-borderless Run in borderless fullscreen mode (always on top)\n" - "--vsync [1/on or 0/off] Turn vsync on or off (default is on)\n" - "--max-vram [size] Max VRAM to use in Mb before swapping. 0 for unlimited\n" - "--force-kid Force the UI mode to be Kid\n" - "--force-kiosk Force the UI mode to be Kiosk\n" - "--force-disable-filters Force the UI to ignore applied filters in gamelist\n" - "--home [path] Directory to use as home path\n" - "--help, -h Summon a sentient, angry tuba\n\n" - "More information available in README.md.\n"; - return false; //exit after printing help +"EmulationStation Desktop Edition\n" +"An Emulator Front-end\n\n" +"Options:\n" +"--resolution [width] [height] Try to force a particular resolution\n" +"--gamelist-only Skip automatic game ROM search, only read from gamelist.xml\n" +"--ignore-gamelist Ignore the gamelist files (useful for troubleshooting)\n" +"--draw-framerate Display the framerate\n" +"--no-exit Don't show the exit option in the menu\n" +"--no-splash Don't show the splash screen\n" +#ifdef WIN32 +"--debug Show console and print debug information\n" +#else +"--debug Print debug information\n" +#endif +//"--scrape Scrape using command line interface\n" +"--windowed Windowed mode, should be combined with --resolution\n" +"--fullscreen-normal Normal fullscreen mode\n" +"--fullscreen-borderless Borderless fullscreen mode (always on top)\n" +"--vsync [1/on or 0/off] Turn vsync on or off (default is on)\n" +"--max-vram [size] Max VRAM to use in Mb before swapping\n" +" Set to at least 20 to avoid unpredictable behavior\n" +"--force-kid Force the UI mode to Kid\n" +"--force-kiosk Force the UI mode to Kiosk\n" +"--force-disable-filters Force the UI to ignore applied filters in gamelist\n" +"--home [path] Directory to use as home path\n" +"--version, -v Displays version information\n" +"--help, -h Summon a sentient, angry tuba\n"; + return false; // Exit after printing help. } - else - { + else { std::string argv_unknown = argv[i]; - std::cout << "Invalid command line argument '" << argv_unknown << "'\n"; + std::cout << "Unknown option '" << argv_unknown << "'.\n"; std::cout << "Try 'emulationstation --help' for more information.\n"; - return false; // exit after printing message + return false; // Exit after printing message. } - } return true; @@ -208,15 +236,13 @@ bool parseArgs(int argc, char* argv[]) bool verifyHomeFolderExists() { - //make sure the config directory exists + // Make sure the config directory exists. std::string home = Utils::FileSystem::getHomePath(); std::string configDir = home + "/.emulationstation"; - if(!Utils::FileSystem::exists(configDir)) - { + if (!Utils::FileSystem::exists(configDir)) { std::cout << "Creating config directory \"" << configDir << "\"\n"; Utils::FileSystem::createDirectory(configDir); - if(!Utils::FileSystem::exists(configDir)) - { + if (!Utils::FileSystem::exists(configDir)) { std::cerr << "Config directory could not be created!\n"; return false; } @@ -225,22 +251,23 @@ bool verifyHomeFolderExists() return true; } -// Returns true if everything is OK, +// Returns true if everything is OK. bool loadSystemConfigFile(const char** errorString) { *errorString = NULL; - if(!SystemData::loadConfig()) - { + if (!SystemData::loadConfig()) { LOG(LogError) << "Error while parsing systems configuration file!"; - *errorString = "IT LOOKS LIKE YOUR SYSTEMS CONFIGURATION FILE HAS NOT BEEN SET UP OR IS INVALID. YOU'LL NEED TO DO THIS BY HAND, UNFORTUNATELY.\n\n" + *errorString = "IT LOOKS LIKE YOUR SYSTEMS CONFIGURATION FILE HAS NOT BEEN SET UP " + "OR IS INVALID. YOU'LL NEED TO DO THIS BY HAND, UNFORTUNATELY.\n\n" "VISIT EMULATIONSTATION.ORG FOR MORE INFORMATION."; return false; } - if(SystemData::sSystemVector.size() == 0) + if (SystemData::sSystemVector.size() == 0) { - LOG(LogError) << "No systems found! Does at least one system have a game present? (check that extensions match!)\n(Also, make sure you've updated your es_systems.cfg for XML!)"; + LOG(LogError) << "No systems found! Does at least one system have a game present? (check " + "that extensions match!)\n(Also, make sure you've updated your es_systems.cfg for XML!)"; *errorString = "WE CAN'T FIND ANY SYSTEMS!\n" "CHECK THAT YOUR PATHS ARE CORRECT IN THE SYSTEMS CONFIGURATION FILE, " "AND YOUR GAME DIRECTORY HAS AT LEAST ONE GAME WITH THE CORRECT EXTENSION.\n\n" @@ -251,7 +278,7 @@ bool loadSystemConfigFile(const char** errorString) return true; } -//called on exit, assuming we get far enough to have the log initialized +// Called on exit, assuming we get far enough to have the log initialized. void onExit() { Log::close(); @@ -263,10 +290,10 @@ int main(int argc, char* argv[]) std::locale::global(std::locale("C")); - if(!parseArgs(argc, argv)) + if (!parseArgs(argc, argv)) return 0; - // only show the console on Windows if HideConsole is false + // Only show the console on Windows if HideConsole is false. #ifdef WIN32 // MSVC has a "SubSystem" option, with two primary options: "WINDOWS" and "CONSOLE". // In "WINDOWS" mode, no console is automatically created for us. This is good, @@ -277,43 +304,43 @@ int main(int argc, char* argv[]) // will leave a brief flash. // TL;DR: You should compile ES under the "WINDOWS" subsystem. // I have no idea how this works with non-MSVC compilers. - if(!Settings::getInstance()->getBool("HideConsole")) - { - // we want to show the console - // if we're compiled in "CONSOLE" mode, this is already done. - // if we're compiled in "WINDOWS" mode, no console is created for us automatically; - // the user asked for one, so make one and then hook stdin/stdout/sterr up to it - if(AllocConsole()) // should only pass in "WINDOWS" mode - { + if (!Settings::getInstance()->getBool("HideConsole")) { + // We want to show the console. + // If we're compiled in "CONSOLE" mode, this is already done. + // If we're compiled in "WINDOWS" mode, no console is created for us automatically; + // the user asked for one, so make one and then hook stdin/stdout/sterr up to it. + if (AllocConsole()) { // Should only pass in "WINDOWS" mode. freopen("CONIN$", "r", stdin); freopen("CONOUT$", "wb", stdout); freopen("CONOUT$", "wb", stderr); } - }else{ - // we want to hide the console - // if we're compiled with the "WINDOWS" subsystem, this is already done. - // if we're compiled with the "CONSOLE" subsystem, a console is already created; - // it'll flash open, but we hide it nearly immediately - if(GetConsoleWindow()) // should only pass in "CONSOLE" mode + } + else { + // We want to hide the console. + // If we're compiled with the "WINDOWS" subsystem, this is already done. + // If we're compiled with the "CONSOLE" subsystem, a console is already created; + // it'll flash open, but we hide it nearly immediately. + if (GetConsoleWindow()) // Should only pass in "CONSOLE" mode. ShowWindow(GetConsoleWindow(), SW_HIDE); } #endif - // call this ONLY when linking with FreeImage as a static library + // Call this ONLY when linking with FreeImage as a static library. #ifdef FREEIMAGE_LIB FreeImage_Initialise(); #endif - //if ~/.emulationstation doesn't exist and cannot be created, bail - if(!verifyHomeFolderExists()) + // If ~/.emulationstation doesn't exist and cannot be created, bail. + if (!verifyHomeFolderExists()) return 1; - //start the logger + // Start the logger. Log::init(); Log::open(); - LOG(LogInfo) << "EmulationStation - v" << PROGRAM_VERSION_STRING << ", built " << PROGRAM_BUILT_STRING; + LOG(LogInfo) << "EmulationStation - v" << PROGRAM_VERSION_STRING << + ", built " << PROGRAM_BUILT_STRING; - //always close the log on exit + // Always close the log on exit. atexit(&onExit); Window window; @@ -327,16 +354,13 @@ int main(int argc, char* argv[]) bool splashScreen = Settings::getInstance()->getBool("SplashScreen"); bool splashScreenProgress = Settings::getInstance()->getBool("SplashScreenProgress"); - if(!scrape_cmdline) - { - if(!window.init()) - { + if (!scrape_cmdline) { + if (!window.init()) { LOG(LogError) << "Window failed to initialize!"; return 1; } - - if(splashScreen) - { + + if (splashScreen) { std::string progressText = "Loading..."; if (splashScreenProgress) progressText = "Loading system config..."; @@ -345,18 +369,18 @@ int main(int argc, char* argv[]) } const char* errorMsg = NULL; - if(!loadSystemConfigFile(&errorMsg)) - { - // something went terribly wrong - if(errorMsg == NULL) + if (!loadSystemConfigFile(&errorMsg)) { + // Something went terribly wrong. + if (errorMsg == NULL) { LOG(LogError) << "Unknown error occured while parsing system config file."; - if(!scrape_cmdline) + if (!scrape_cmdline) Renderer::deinit(); return 1; } - // we can't handle es_systems.cfg file problems inside ES itself, so display the error message then quit + // We can't handle es_systems.cfg file problems inside ES itself, + // so display the error message and then quit. window.pushGui(new GuiMsgBox(&window, errorMsg, "QUIT", [] { @@ -366,34 +390,36 @@ int main(int argc, char* argv[]) })); } - //run the command line scraper then quit - if(scrape_cmdline) + // Run the command line scraper then quit. + if (scrape_cmdline) { return run_scraper_cmdline(); } - //dont generate joystick events while we're loading (hopefully fixes "automatically started emulator" bug) + // Dont generate joystick events while we're loading. + // (Hopefully fixes "automatically started emulator" bug.) SDL_JoystickEventState(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 + // 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::get()->preload(); - if(splashScreen && splashScreenProgress) + if (splashScreen && splashScreenProgress) window.renderLoadingScreen("Done."); - //choose which GUI to open depending on if an input configuration already exists - if(errorMsg == NULL) - { - if(Utils::FileSystem::exists(InputManager::getConfigPath()) && InputManager::getInstance()->getNumConfiguredDevices() > 0) - { + // Choose which GUI to open depending on if an input configuration already exists. + if (errorMsg == NULL) { + if (Utils::FileSystem::exists(InputManager::getConfigPath()) && + InputManager::getInstance()->getNumConfiguredDevices() > 0) { ViewController::get()->goToStart(); - }else{ - window.pushGui(new GuiDetectDevice(&window, true, [] { ViewController::get()->goToStart(); })); + } + else { + window.pushGui(new GuiDetectDevice(&window, true, [] { + ViewController::get()->goToStart(); })); } } - //generate joystick events since we're done loading + // Generate joystick events since we're done loading. SDL_JoystickEventState(SDL_ENABLE); int lastTime = SDL_GetTicks(); @@ -401,49 +427,49 @@ int main(int argc, char* argv[]) bool running = true; - while(running) - { + while (running) { SDL_Event event; - bool ps_standby = PowerSaver::getState() && (int) SDL_GetTicks() - ps_time > PowerSaver::getMode(); + bool ps_standby = PowerSaver::getState() && (int) SDL_GetTicks() - + ps_time > PowerSaver::getMode(); - if(ps_standby ? SDL_WaitEventTimeout(&event, PowerSaver::getTimeout()) : SDL_PollEvent(&event)) - { - do - { + if (ps_standby ? SDL_WaitEventTimeout(&event, PowerSaver::getTimeout()) + : SDL_PollEvent(&event)) { + do { InputManager::getInstance()->parseEvent(event, &window); - if(event.type == SDL_QUIT) + if (event.type == SDL_QUIT) running = false; - } while(SDL_PollEvent(&event)); + } + while (SDL_PollEvent(&event)); - // triggered if exiting from SDL_WaitEvent due to event + // Triggered if exiting from SDL_WaitEvent due to event. if (ps_standby) - // show as if continuing from last event + // Show as if continuing from last event. lastTime = SDL_GetTicks(); - // reset counter + // Reset counter. ps_time = SDL_GetTicks(); } - else if (ps_standby) - { - // If exitting SDL_WaitEventTimeout due to timeout. Trail considering - // timeout as an event + else if (ps_standby) { + // If exiting SDL_WaitEventTimeout due to timeout. + // Trail considering timeout as an event. ps_time = SDL_GetTicks(); } - if(window.isSleeping()) - { + if (window.isSleeping()) { lastTime = SDL_GetTicks(); - SDL_Delay(1); // this doesn't need to be accurate, we're just giving up our CPU time until something wakes us up + // This doesn't need to be accurate, we're just giving up + // our CPU time until something wakes us up. continue; + SDL_Delay(1); } int curTime = SDL_GetTicks(); int deltaTime = curTime - lastTime; lastTime = curTime; - // cap deltaTime if it ever goes negative - if(deltaTime < 0) + // Cap deltaTime if it ever goes negative. + if (deltaTime < 0) deltaTime = 1000; window.update(deltaTime); @@ -453,7 +479,7 @@ int main(int argc, char* argv[]) Log::flush(); } - while(window.peekGui() != ViewController::get()) + while (window.peekGui() != ViewController::get()) delete window.peekGui(); window.deinit(); @@ -461,7 +487,7 @@ int main(int argc, char* argv[]) CollectionSystemManager::deinit(); SystemData::deleteSystems(); - // call this ONLY when linking with FreeImage as a static library + // Call this ONLY when linking with FreeImage as a static library. #ifdef FREEIMAGE_LIB FreeImage_DeInitialise(); #endif diff --git a/es-core/src/Settings.cpp b/es-core/src/Settings.cpp index b257e5e75..fd8b8a1ee 100644 --- a/es-core/src/Settings.cpp +++ b/es-core/src/Settings.cpp @@ -1,3 +1,11 @@ +// +// Settings.cpp +// +// Functions to read from and write to the configuration file es_settings.cfg +// are included here. The default values for the application settings are +// defined here as well. +// + #include "Settings.h" #include "utils/FileSystemUtil.h" @@ -10,29 +18,37 @@ Settings* Settings::sInstance = NULL; -// these values are NOT saved to es_settings.xml -// since they're set through command-line arguments, and not the in-program settings menu +// These values are NOT saved to es_settings.cfg since they're not set via +// the in-program settings menu. Most can be set using command-line arguments, +// but some are debug flags that are either hardcoded or set by internal debug +// functions. std::vector settings_dont_save { - { "Debug" }, + // These options can be set using command-line arguments: + { "Debug" }, // --debug + { "HideConsole" }, // Implicitly set via the --debug flag. + { "ForceKid" }, // --force-kid + { "ForceKiosk" }, // --force-kiosk + { "IgnoreGamelist" }, // --ignore-gamelist + { "ShowExit" }, // --no-exit + { "SplashScreen" }, // --no-splash + { "VSync" }, // --vsync [1/on or 0/off] + { "Windowed" }, // --windowed + { "WindowWidth" }, // Set via --resolution [width] [height] + { "WindowHeight" }, // set via --resolution [width] [height] + + // These options are not shown in the --help text and are intended + // for debugging and testing purposes: + { "ScreenWidth" }, // Set via --screensize [width] [height] + { "ScreenHeight" }, // set via --screensize [width] [height] + { "ScreenOffsetX" }, // Set via --screenoffset [X] [Y] + { "ScreenOffsetY" }, // Set via --screenoffset [X] [Y] + { "ScreenRotate" }, // --screenrotate [0-3] + + // These options are not configurable from the command-line: { "DebugGrid" }, { "DebugText" }, { "DebugImage" }, - { "ForceKid" }, - { "ForceKiosk" }, - { "IgnoreGamelist" }, - { "HideConsole" }, - { "ShowExit" }, - { "SplashScreen" }, - { "SplashScreenProgress" }, - { "VSync" }, - { "Windowed" }, - { "WindowWidth" }, - { "WindowHeight" }, - { "ScreenWidth" }, - { "ScreenHeight" }, - { "ScreenOffsetX" }, - { "ScreenOffsetY" }, - { "ScreenRotate" } + { "SplashScreenProgress" } }; Settings::Settings() @@ -44,7 +60,7 @@ Settings::Settings() Settings* Settings::getInstance() { - if(sInstance == NULL) + if (sInstance == NULL) sInstance = new Settings(); return sInstance; @@ -55,129 +71,148 @@ void Settings::setDefaults() mBoolMap.clear(); mIntMap.clear(); - mBoolMap["BackgroundJoystickInput"] = false; - mBoolMap["ParseGamelistOnly"] = false; - mBoolMap["ShowHiddenFiles"] = false; - mBoolMap["DrawFramerate"] = false; - mBoolMap["ShowExit"] = true; - mBoolMap["ShowRebootSystem"] = true; - mBoolMap["ShowPoweroffSystem"] = true; - mBoolMap["Windowed"] = false; - mBoolMap["SplashScreen"] = true; - mBoolMap["SplashScreenProgress"] = true; + // + // Settings configured via the in-program settings menu. + // + + // UI settings. mStringMap["StartupSystem"] = ""; - mBoolMap["DisableKidStartMenu"] = true; - mStringMap["MediaDirectory"] = ""; - mStringMap["DefaultSortOrder"] = ""; - - mBoolMap["VSync"] = true; - - mBoolMap["EnableSounds"] = true; - mBoolMap["ShowHelpPrompts"] = true; - mBoolMap["ScrapeRatings"] = true; - mBoolMap["IgnoreGamelist"] = false; - mBoolMap["HideConsole"] = true; - mBoolMap["QuickSystemSelect"] = true; - mBoolMap["MoveCarousel"] = true; - - mBoolMap["Debug"] = false; - mBoolMap["DebugGrid"] = false; - mBoolMap["DebugText"] = false; - mBoolMap["DebugImage"] = false; - - mIntMap["ScreenSaverTime"] = 5*60*1000; // 5 minutes - mIntMap["ScraperResizeWidth"] = 400; - mIntMap["ScraperResizeHeight"] = 0; - #ifdef _RPI_ - mIntMap["MaxVRAM"] = 80; - #else - mIntMap["MaxVRAM"] = 100; - #endif - - mStringMap["FullscreenMode"] = "normal"; + mStringMap["GamelistViewStyle"] = "automatic"; mStringMap["TransitionStyle"] = "instant"; mStringMap["ThemeSet"] = ""; - mStringMap["ScreenSaverBehavior"] = "dim"; - mStringMap["Scraper"] = "ScreenScraper"; - mStringMap["GamelistViewStyle"] = "automatic"; - mStringMap["SaveGamelistsMode"] = "always"; + mStringMap["UIMode"] = "Full"; + mBoolMap["FavoritesFirst"] = true; + mBoolMap["ForceDisableFilters"] = false; + mBoolMap["QuickSystemSelect"] = true; + mBoolMap["MoveCarousel"] = true; + mBoolMap["DisableKidStartMenu"] = true; + mBoolMap["ShowHelpPrompts"] = true; + // UI settings -> scrensaver settings. + mIntMap["ScreenSaverTime"] = 5*60*1000; // 5 minutes mBoolMap["ScreenSaverControls"] = true; - mStringMap["ScreenSaverGameInfo"] = "never"; - mBoolMap["StretchVideoOnScreenSaver"] = false; - mStringMap["PowerSaverMode"] = "disabled"; + mStringMap["ScreenSaverBehavior"] = "dim"; + // UI settings -> screensaver settings -> video screensaver settings. + mIntMap["ScreenSaverSwapVideoTimeout"] = 30000; + mBoolMap["StretchVideoOnScreenSaver"] = false; + mStringMap["ScreenSaverGameInfo"] = "never"; + mBoolMap["ScreenSaverVideoMute"] = false; // Raspberry Pi only + mBoolMap["CaptionsCompatibility"] = true; + + // UI settings -> screensaver settings -> slideshow screensaver settings. mIntMap["ScreenSaverSwapImageTimeout"] = 10000; mBoolMap["SlideshowScreenSaverStretch"] = false; - mStringMap["SlideshowScreenSaverBackgroundAudioFile"] = Utils::FileSystem::getHomePath() + "/.emulationstation/slideshow/audio/slideshow_bg.wav"; + mStringMap["SlideshowScreenSaverBackgroundAudioFile"] = Utils::FileSystem::getHomePath() + + "/.emulationstation/slideshow/audio/slideshow_bg.wav"; mBoolMap["SlideshowScreenSaverCustomImageSource"] = false; - mStringMap["SlideshowScreenSaverImageDir"] = Utils::FileSystem::getHomePath() + "/.emulationstation/slideshow/image"; - mStringMap["SlideshowScreenSaverImageFilter"] = ".png,.jpg"; + mStringMap["SlideshowScreenSaverImageDir"] = Utils::FileSystem::getHomePath() + + "/.emulationstation/slideshow/image"; mBoolMap["SlideshowScreenSaverRecurse"] = false; + mStringMap["SlideshowScreenSaverImageFilter"] = ".png,.jpg"; - // 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; - #ifdef _RPI_ - // we're defaulting to OMX Player for full screen video on the Pi - mBoolMap["ScreenSaverOmxPlayer"] = true; - // use OMX Player defaults - mStringMap["SubtitleFont"] = "/usr/share/fonts/truetype/freefont/FreeSans.ttf"; - mStringMap["SubtitleItalicFont"] = "/usr/share/fonts/truetype/freefont/FreeSansOblique.ttf"; - mIntMap["SubtitleSize"] = 55; - mStringMap["SubtitleAlignment"] = "left"; - #else - mBoolMap["ScreenSaverOmxPlayer"] = false; - #endif - - mIntMap["ScreenSaverSwapVideoTimeout"] = 30000; - - mBoolMap["VideoAudio"] = true; - mBoolMap["ScreenSaverVideoMute"] = false; - mBoolMap["CaptionsCompatibility"] = true; - // Audio out device for Video playback using OMX player. - mStringMap["OMXAudioDev"] = "both"; - mStringMap["CollectionSystemsAuto"] = ""; - mStringMap["CollectionSystemsCustom"] = ""; - mBoolMap["CollectionShowSystemInfo"] = true; - mBoolMap["UseCustomCollectionsSystem"] = true; - - mBoolMap["FavFirstCustom"] = true; - mBoolMap["FavoritesFirst"] = true; - mBoolMap["LaunchstringOverride"] = true; - - mBoolMap["LocalArt"] = false; - - // Audio out device for volume control + // Sound settings. + mStringMap["AudioCard"] = "default"; + // Audio out device for volume control. #ifdef _RPI_ mStringMap["AudioDevice"] = "PCM"; #else mStringMap["AudioDevice"] = "Master"; #endif + mBoolMap["VideoAudio"] = true; + mBoolMap["EnableSounds"] = true; + // Audio out device for Video playback using OMX player. + mStringMap["OMXAudioDev"] = "both"; - mStringMap["AudioCard"] = "default"; - mStringMap["UIMode"] = "Full"; - mStringMap["UIMode_passkey"] = "uuddlrlrba"; - mBoolMap["ForceKiosk"] = false; + // Game collection settings. + mStringMap["CollectionSystemsAuto"] = ""; + mStringMap["CollectionSystemsCustom"] = ""; + mBoolMap["UseCustomCollectionsSystem"] = true; + mBoolMap["FavFirstCustom"] = true; + mBoolMap["CollectionShowSystemInfo"] = true; + + // Scraper. + mStringMap["Scraper"] = "ScreenScraper"; + mBoolMap["ScrapeRatings"] = true; + + // Other settings. + #ifdef _RPI_ + mIntMap["MaxVRAM"] = 80; + #else + mIntMap["MaxVRAM"] = 100; + #endif + mStringMap["FullscreenMode"] = "normal"; + mStringMap["PowerSaverMode"] = "disabled"; + // 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; + #ifdef _RPI_ + // We're defaulting to OMX Player for full screen video on the Pi. + mBoolMap["ScreenSaverOmxPlayer"] = true; + // Use OMX Player defaults. + mStringMap["SubtitleFont"] = "/usr/share/fonts/truetype/freefont/FreeSans.ttf"; + mStringMap["SubtitleItalicFont"] = "/usr/share/fonts/truetype/freefont/FreeSansOblique.ttf"; + mIntMap["SubtitleSize"] = 55; + mStringMap["SubtitleAlignment"] = "left"; + #else + mBoolMap["ScreenSaverOmxPlayer"] = false; + #endif + mStringMap["SaveGamelistsMode"] = "always"; + mBoolMap["LaunchstringOverride"] = true; + mBoolMap["ParseGamelistOnly"] = false; + mBoolMap["LocalArt"] = false; + mBoolMap["ShowHiddenFiles"] = false; + mBoolMap["DrawFramerate"] = false; + mBoolMap["ShowRebootSystem"] = true; + mBoolMap["ShowPoweroffSystem"] = true; + + // + // Settings configured via command-line arguments. + // + + // Options listed using --help + mBoolMap["Debug"] = false; + mBoolMap["HideConsole"] = true; // Implicitly set via the --debug flag. mBoolMap["ForceKid"] = false; - mBoolMap["ForceDisableFilters"] = false; - + mBoolMap["ForceKiosk"] = false; + mBoolMap["IgnoreGamelist"] = false; + mBoolMap["ShowExit"] = true; + mBoolMap["SplashScreen"] = true; + mBoolMap["VSync"] = true; + mBoolMap["Windowed"] = false; mIntMap["WindowWidth"] = 0; mIntMap["WindowHeight"] = 0; mIntMap["ScreenWidth"] = 0; + + // Undocumented options. mIntMap["ScreenHeight"] = 0; mIntMap["ScreenOffsetX"] = 0; mIntMap["ScreenOffsetY"] = 0; mIntMap["ScreenRotate"] = 0; + + // + // Hardcoded or program-internal settings. + // + + mBoolMap["BackgroundJoystickInput"] = false; + mBoolMap["DebugGrid"] = false; + mBoolMap["DebugText"] = false; + mBoolMap["DebugImage"] = false; + mStringMap["DefaultSortOrder"] = "filename, ascending"; + mStringMap["MediaDirectory"] = ""; + mIntMap["ScraperResizeWidth"] = 400; + mIntMap["ScraperResizeHeight"] = 0; + mBoolMap["SplashScreenProgress"] = true; + mStringMap["UIMode_passkey"] = "uuddlrlrba"; } template void saveMap(pugi::xml_document& doc, std::map& map, const char* type) { - for(auto iter = map.cbegin(); iter != map.cend(); iter++) - { - // key is on the "don't save" list, so don't save it - if(std::find(settings_dont_save.cbegin(), settings_dont_save.cend(), iter->first) != settings_dont_save.cend()) + for (auto iter = map.cbegin(); iter != map.cend(); iter++) { + // Key is on the "don't save" list, so don't save it. + if (std::find(settings_dont_save.cbegin(), settings_dont_save.cend(), + iter->first) != settings_dont_save.cend()) continue; pugi::xml_node node = doc.append_child(type); @@ -189,7 +224,8 @@ void saveMap(pugi::xml_document& doc, std::map& map, const char* type) void Settings::saveFile() { LOG(LogDebug) << "Settings::saveFile() : Saving Settings to file."; - const std::string path = Utils::FileSystem::getHomePath() + "/.emulationstation/es_settings.cfg"; + const std::string path = Utils::FileSystem::getHomePath() + + "/.emulationstation/es_settings.cfg"; pugi::xml_document doc; @@ -198,8 +234,7 @@ void Settings::saveFile() saveMap(doc, mFloatMap, "float"); //saveMap(doc, mStringMap, "string"); - for(auto iter = mStringMap.cbegin(); iter != mStringMap.cend(); iter++) - { + for (auto iter = mStringMap.cbegin(); iter != mStringMap.cend(); iter++) { pugi::xml_node node = doc.append_child("string"); node.append_attribute("name").set_value(iter->first.c_str()); node.append_attribute("value").set_value(iter->second.c_str()); @@ -213,47 +248,35 @@ void Settings::saveFile() void Settings::loadFile() { - const std::string path = Utils::FileSystem::getHomePath() + "/.emulationstation/es_settings.cfg"; + const std::string path = Utils::FileSystem::getHomePath() + + "/.emulationstation/es_settings.cfg"; - if(!Utils::FileSystem::exists(path)) + if (!Utils::FileSystem::exists(path)) return; pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file(path.c_str()); - if(!result) - { + if (!result) { LOG(LogError) << "Could not parse Settings file!\n " << result.description(); return; } - for(pugi::xml_node node = doc.child("bool"); node; node = node.next_sibling("bool")) + for (pugi::xml_node node = doc.child("bool"); node; node = node.next_sibling("bool")) setBool(node.attribute("name").as_string(), node.attribute("value").as_bool()); - for(pugi::xml_node node = doc.child("int"); node; node = node.next_sibling("int")) + for (pugi::xml_node node = doc.child("int"); node; node = node.next_sibling("int")) setInt(node.attribute("name").as_string(), node.attribute("value").as_int()); - for(pugi::xml_node node = doc.child("float"); node; node = node.next_sibling("float")) + for (pugi::xml_node node = doc.child("float"); node; node = node.next_sibling("float")) setFloat(node.attribute("name").as_string(), node.attribute("value").as_float()); - for(pugi::xml_node node = doc.child("string"); node; node = node.next_sibling("string")) + for (pugi::xml_node node = doc.child("string"); node; node = node.next_sibling("string")) setString(node.attribute("name").as_string(), node.attribute("value").as_string()); - - processBackwardCompatibility(); } -void Settings::processBackwardCompatibility() -{ - { // SaveGamelistsOnExit -> SaveGamelistsMode - std::map::const_iterator it = mBoolMap.find("SaveGamelistsOnExit"); - if (it != mBoolMap.end()) { - mStringMap["SaveGamelistsMode"] = it->second ? "on exit" : "never"; - mBoolMap.erase(it); - } - } -} - -//Print a warning message if the setting we're trying to get doesn't already exist in the map, then return the value in the map. -#define SETTINGS_GETSET(type, mapName, getMethodName, setMethodName) type Settings::getMethodName(const std::string& name) \ +// Print a warning message if the setting we're trying to get doesn't already exist in +// the map. Then return the value in the map. +#define SETTINGS_GETSET(type, mapName, getMethodName, setMethodName) \ + type Settings::getMethodName(const std::string& name) \ { \ - if(mapName.find(name) == mapName.cend()) \ - { \ + if (mapName.find(name) == mapName.cend()) { \ LOG(LogError) << "Tried to use unset setting " << name << "!"; \ } \ return mapName[name]; \ @@ -263,7 +286,8 @@ bool Settings::setMethodName(const std::string& name, type value) \ if (mapName.count(name) == 0 || mapName[name] != value) { \ mapName[name] = value; \ \ - if (std::find(settings_dont_save.cbegin(), settings_dont_save.cend(), name) == settings_dont_save.cend()) \ + if (std::find(settings_dont_save.cbegin(), settings_dont_save.cend(), name) \ + == settings_dont_save.cend()) \ mWasChanged = true; \ \ return true; \ diff --git a/es-core/src/Settings.h b/es-core/src/Settings.h index 0a21e85cf..a3240cb5f 100644 --- a/es-core/src/Settings.h +++ b/es-core/src/Settings.h @@ -1,10 +1,18 @@ +// +// Settings.h +// +// Functions to read from and write to the configuration file es_settings.cfg +// are included here. The default values for the application settings are +// defined here as well. +// + #pragma once #ifndef ES_CORE_SETTINGS_H #define ES_CORE_SETTINGS_H #include -//This is a singleton for storing settings. +// This is a singleton for storing settings. class Settings { public: @@ -13,7 +21,7 @@ public: void loadFile(); void saveFile(); - //You will get a warning if you try a get on a key that is not already present. + // You will get a warning if you try a get on a key that is not already present. bool getBool(const std::string& name); int getInt(const std::string& name); float getFloat(const std::string& name); @@ -29,12 +37,11 @@ private: Settings(); - //Clear everything and load default values. + // Clear everything and load default values. void setDefaults(); - void processBackwardCompatibility(); bool mWasChanged; - + std::map mBoolMap; std::map mIntMap; std::map mFloatMap;