Some code cleanup and code documentation. Improvements to handling of command line arguments.

This commit is contained in:
Leon Styhre 2020-05-25 21:34:42 +02:00
parent 76c8b5f121
commit da946279de
5 changed files with 427 additions and 364 deletions

View file

@ -1,3 +1,9 @@
//
// EmulationStation.h
//
// Version and build information.
//
#pragma once #pragma once
#ifndef ES_APP_EMULATION_STATION_H #ifndef ES_APP_EMULATION_STATION_H
#define ES_APP_EMULATION_STATION_H #define ES_APP_EMULATION_STATION_H

View file

@ -117,17 +117,17 @@ void GuiMenu::openSoundSettings()
setVolume((int)Math::round(volume->getValue())); }); setVolume((int)Math::round(volume->getValue())); });
if (UIModeController::getInstance()->isUIModeFull()) { if (UIModeController::getInstance()->isUIModeFull()) {
#if defined(__linux__) #if defined(__linux__)
// audio card // audio card
auto audio_card = std::make_shared< OptionListComponent<std::string> auto audio_card = std::make_shared< OptionListComponent<std::string>
>(mWindow, "AUDIO CARD", false); >(mWindow, "AUDIO CARD", false);
std::vector<std::string> audio_cards; std::vector<std::string> audio_cards;
#ifdef _RPI_ #ifdef _RPI_
// RPi Specific Audio Cards // RPi Specific Audio Cards
audio_cards.push_back("local"); audio_cards.push_back("local");
audio_cards.push_back("hdmi"); audio_cards.push_back("hdmi");
audio_cards.push_back("both"); audio_cards.push_back("both");
#endif #endif
audio_cards.push_back("default"); audio_cards.push_back("default");
audio_cards.push_back("sysdefault"); audio_cards.push_back("sysdefault");
audio_cards.push_back("dmix"); audio_cards.push_back("dmix");
@ -172,7 +172,7 @@ void GuiMenu::openSoundSettings()
VolumeControl::getInstance()->deinit(); VolumeControl::getInstance()->deinit();
VolumeControl::getInstance()->init(); VolumeControl::getInstance()->init();
}); });
#endif #endif
// Video audio. // Video audio.
auto video_audio = std::make_shared<SwitchComponent>(mWindow); auto video_audio = std::make_shared<SwitchComponent>(mWindow);
@ -196,7 +196,7 @@ void GuiMenu::openSoundSettings()
Settings::getInstance()->setBool("EnableSounds", sounds_enabled->getState()); Settings::getInstance()->setBool("EnableSounds", sounds_enabled->getState());
}); });
#ifdef _RPI_ #ifdef _RPI_
// OMX player Audio Device // OMX player Audio Device
auto omx_audio_dev = std::make_shared< OptionListComponent<std::string> auto omx_audio_dev = std::make_shared< OptionListComponent<std::string>
>(mWindow, "OMX PLAYER AUDIO DEVICE", false); >(mWindow, "OMX PLAYER AUDIO DEVICE", false);
@ -220,7 +220,7 @@ void GuiMenu::openSoundSettings()
if (Settings::getInstance()->getString("OMXAudioDev") != omx_audio_dev->getSelected()) if (Settings::getInstance()->getString("OMXAudioDev") != omx_audio_dev->getSelected())
Settings::getInstance()->setString("OMXAudioDev", omx_audio_dev->getSelected()); Settings::getInstance()->setString("OMXAudioDev", omx_audio_dev->getSelected());
}); });
#endif #endif
} }
mWindow->pushGui(s); mWindow->pushGui(s);
@ -490,6 +490,26 @@ void GuiMenu::openOtherSettings()
PowerSaver::init(); PowerSaver::init();
}); });
#ifdef _RPI_
// Video Player - VideoOmxPlayer.
auto omx_player = std::make_shared<SwitchComponent>(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. // When to save game metadata.
auto gamelistsSaveMode = std::make_shared< OptionListComponent<std::string> auto gamelistsSaveMode = std::make_shared< OptionListComponent<std::string>
>(mWindow, "SAVE METADATA", false); >(mWindow, "SAVE METADATA", false);
@ -522,7 +542,7 @@ void GuiMenu::openOtherSettings()
auto local_art = std::make_shared<SwitchComponent>(mWindow); auto local_art = std::make_shared<SwitchComponent>(mWindow);
local_art->setState(Settings::getInstance()->getBool("LocalArt")); 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()-> s->addSaveFunc([local_art] { Settings::getInstance()->
setBool("LocalArt", local_art->getState()); }); setBool("LocalArt", local_art->getState()); });
@ -554,26 +574,6 @@ void GuiMenu::openOtherSettings()
s->addSaveFunc([show_poweroffsystem] { Settings::getInstance()->setBool("ShowPoweroffSystem", s->addSaveFunc([show_poweroffsystem] { Settings::getInstance()->setBool("ShowPoweroffSystem",
show_poweroffsystem->getState()); }); show_poweroffsystem->getState()); });
#ifdef _RPI_
// Video Player - VideoOmxPlayer.
auto omx_player = std::make_shared<SwitchComponent>(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); mWindow->pushGui(s);
} }

View file

@ -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/GuiDetectDevice.h"
#include "guis/GuiMsgBox.h" #include "guis/GuiMsgBox.h"
@ -33,29 +46,37 @@ bool parseArgs(int argc, char* argv[])
{ {
Utils::FileSystem::setExePath(argv[0]); Utils::FileSystem::setExePath(argv[0]);
// We need to process --home before any call to Settings::getInstance(), because settings are loaded from homepath // We need to process --home before any call to Settings::getInstance(),
for(int i = 1; i < argc; i++) // because settings are loaded from the home path.
{ for (int i = 1; i < argc; i++) {
if(strcmp(argv[i], "--home") == 0) if (strcmp(argv[i], "--home") == 0) {
{ if (i >= argc - 1) {
if(i >= argc - 1) std::cerr << "Error: No home path supplied with \'--home'.\n";
{
std::cerr << "Invalid home path supplied.";
return false; 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]); Utils::FileSystem::setHomePath(argv[i + 1]);
break; break;
} }
} }
for(int i = 1; i < argc; i++) for(int i = 1; i < argc; i++) {
{ // Skip past --home flag as we already processed it.
if(strcmp(argv[i], "--resolution") == 0) if (strcmp(argv[i], "--home") == 0) {
{ i++;
if(i >= argc - 2) continue;
{ }
std::cerr << "Invalid resolution supplied."; if (strcmp(argv[i], "--resolution") == 0) {
if (i >= argc - 2) {
std::cerr << "Error: Invalid resolution values supplied.\n";
return false; return false;
} }
@ -64,11 +85,10 @@ bool parseArgs(int argc, char* argv[])
i += 2; // skip the argument value i += 2; // skip the argument value
Settings::getInstance()->setInt("WindowWidth", width); Settings::getInstance()->setInt("WindowWidth", width);
Settings::getInstance()->setInt("WindowHeight", height); Settings::getInstance()->setInt("WindowHeight", height);
}else if(strcmp(argv[i], "--screensize") == 0) }
{ else if (strcmp(argv[i], "--screensize") == 0) {
if(i >= argc - 2) if (i >= argc - 2) {
{ std::cerr << "Error: Invalid screensize values supplied.\n";
std::cerr << "Invalid screensize supplied.";
return false; return false;
} }
@ -77,11 +97,10 @@ bool parseArgs(int argc, char* argv[])
i += 2; // skip the argument value i += 2; // skip the argument value
Settings::getInstance()->setInt("ScreenWidth", width); Settings::getInstance()->setInt("ScreenWidth", width);
Settings::getInstance()->setInt("ScreenHeight", height); Settings::getInstance()->setInt("ScreenHeight", height);
}else if(strcmp(argv[i], "--screenoffset") == 0) }
{ else if (strcmp(argv[i], "--screenoffset") == 0) {
if(i >= argc - 2) if (i >= argc - 2) {
{ std::cerr << "Error: Invalid screenoffset values supplied.\n";
std::cerr << "Invalid screenoffset supplied.";
return false; return false;
} }
@ -90,117 +109,126 @@ bool parseArgs(int argc, char* argv[])
i += 2; // skip the argument value i += 2; // skip the argument value
Settings::getInstance()->setInt("ScreenOffsetX", x); Settings::getInstance()->setInt("ScreenOffsetX", x);
Settings::getInstance()->setInt("ScreenOffsetY", y); Settings::getInstance()->setInt("ScreenOffsetY", y);
}else if (strcmp(argv[i], "--screenrotate") == 0) }
{ else if (strcmp(argv[i], "--screenrotate") == 0) {
if (i >= argc - 1) if (i >= argc - 1) {
{ std::cerr << "Error: Invalid screenrotate value supplied.\n";
std::cerr << "Invalid screenrotate supplied.";
return false; return false;
} }
int rotate = atoi(argv[i + 1]); int rotate = atoi(argv[i + 1]);
++i; // skip the argument value ++i; // skip the argument value
Settings::getInstance()->setInt("ScreenRotate", rotate); 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); 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); 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); 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); 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); 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); 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("Debug", true);
Settings::getInstance()->setBool("HideConsole", false); Settings::getInstance()->setBool("HideConsole", false);
Log::setReportingLevel(LogDebug); 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); 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); 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); 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 #ifdef WIN32
// This is a bit of a hack, but otherwise output will go to nowhere // This is a bit of a hack, but otherwise output will go to nowhere when the
// when the application is compiled with the "WINDOWS" subsystem (which we usually are). // application is compiled with the "WINDOWS" subsystem (which we usually are).
// If you're an experienced Windows programmer and know how to do this // If you're an experienced Windows programmer and know how to do this
// the right way, please submit a pull request! // the right way, please submit a pull request!
AttachConsole(ATTACH_PARENT_PROCESS); AttachConsole(ATTACH_PARENT_PROCESS);
freopen("CONOUT$", "wb", stdout); freopen("CONOUT$", "wb", stdout);
#endif #endif
std::cout << std::cout <<
"EmulationStation Desktop Edition, an emulator front-end with controller navigation and theming support.\n" "EmulationStation Desktop Edition\n"
"Version " << PROGRAM_VERSION_STRING << ", built " << PROGRAM_BUILT_STRING << "\n\n" "An Emulator Front-end\n\n"
"Command line arguments:\n" "Options:\n"
"--resolution [width] [height] Try and force a particular resolution\n" "--resolution [width] [height] Try to force a particular resolution\n"
"--gamelist-only Skip automatic game search, only read from gamelist.xml\n" "--gamelist-only Skip automatic game ROM search, only read from gamelist.xml\n"
"--ignore-gamelist Ignore the gamelist (useful for troubleshooting)\n" "--ignore-gamelist Ignore the gamelist files (useful for troubleshooting)\n"
"--draw-framerate Display the framerate\n" "--draw-framerate Display the framerate\n"
"--no-exit Don't show the exit option in the menu\n" "--no-exit Don't show the exit option in the menu\n"
"--no-splash Don't show the splash screen\n" "--no-splash Don't show the splash screen\n"
"--debug More logging, show console on Windows\n" #ifdef WIN32
// "--scrape Scrape using command line interface\n" "--debug Show console and print debug information\n"
"--windowed Not fullscreen, should be used with --resolution\n" #else
"--fullscreen-normal Run in normal fullscreen mode\n" "--debug Print debug information\n"
"--fullscreen-borderless Run in borderless fullscreen mode (always on top)\n" #endif
"--vsync [1/on or 0/off] Turn vsync on or off (default is on)\n" //"--scrape Scrape using command line interface\n"
"--max-vram [size] Max VRAM to use in Mb before swapping. 0 for unlimited\n" "--windowed Windowed mode, should be combined with --resolution\n"
"--force-kid Force the UI mode to be Kid\n" "--fullscreen-normal Normal fullscreen mode\n"
"--force-kiosk Force the UI mode to be Kiosk\n" "--fullscreen-borderless Borderless fullscreen mode (always on top)\n"
"--force-disable-filters Force the UI to ignore applied filters in gamelist\n" "--vsync [1/on or 0/off] Turn vsync on or off (default is on)\n"
"--home [path] Directory to use as home path\n" "--max-vram [size] Max VRAM to use in Mb before swapping\n"
"--help, -h Summon a sentient, angry tuba\n\n" " Set to at least 20 to avoid unpredictable behavior\n"
"More information available in README.md.\n"; "--force-kid Force the UI mode to Kid\n"
return false; //exit after printing help "--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::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"; std::cout << "Try 'emulationstation --help' for more information.\n";
return false; // exit after printing message return false; // Exit after printing message.
} }
} }
return true; return true;
@ -208,15 +236,13 @@ bool parseArgs(int argc, char* argv[])
bool verifyHomeFolderExists() bool verifyHomeFolderExists()
{ {
//make sure the config directory exists // Make sure the config directory exists.
std::string home = Utils::FileSystem::getHomePath(); std::string home = Utils::FileSystem::getHomePath();
std::string configDir = home + "/.emulationstation"; std::string configDir = home + "/.emulationstation";
if(!Utils::FileSystem::exists(configDir)) if (!Utils::FileSystem::exists(configDir)) {
{
std::cout << "Creating config directory \"" << configDir << "\"\n"; std::cout << "Creating config directory \"" << configDir << "\"\n";
Utils::FileSystem::createDirectory(configDir); Utils::FileSystem::createDirectory(configDir);
if(!Utils::FileSystem::exists(configDir)) if (!Utils::FileSystem::exists(configDir)) {
{
std::cerr << "Config directory could not be created!\n"; std::cerr << "Config directory could not be created!\n";
return false; return false;
} }
@ -225,22 +251,23 @@ bool verifyHomeFolderExists()
return true; return true;
} }
// Returns true if everything is OK, // Returns true if everything is OK.
bool loadSystemConfigFile(const char** errorString) bool loadSystemConfigFile(const char** errorString)
{ {
*errorString = NULL; *errorString = NULL;
if(!SystemData::loadConfig()) if (!SystemData::loadConfig()) {
{
LOG(LogError) << "Error while parsing systems configuration file!"; 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."; "VISIT EMULATIONSTATION.ORG FOR MORE INFORMATION.";
return false; 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" *errorString = "WE CAN'T FIND ANY SYSTEMS!\n"
"CHECK THAT YOUR PATHS ARE CORRECT IN THE SYSTEMS CONFIGURATION FILE, " "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" "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; 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() void onExit()
{ {
Log::close(); Log::close();
@ -263,10 +290,10 @@ int main(int argc, char* argv[])
std::locale::global(std::locale("C")); std::locale::global(std::locale("C"));
if(!parseArgs(argc, argv)) if (!parseArgs(argc, argv))
return 0; return 0;
// only show the console on Windows if HideConsole is false // Only show the console on Windows if HideConsole is false.
#ifdef WIN32 #ifdef WIN32
// MSVC has a "SubSystem" option, with two primary options: "WINDOWS" and "CONSOLE". // 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, // 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. // will leave a brief flash.
// TL;DR: You should compile ES under the "WINDOWS" subsystem. // TL;DR: You should compile ES under the "WINDOWS" subsystem.
// I have no idea how this works with non-MSVC compilers. // I have no idea how this works with non-MSVC compilers.
if(!Settings::getInstance()->getBool("HideConsole")) if (!Settings::getInstance()->getBool("HideConsole")) {
{ // We want to show the console.
// we want to show the console // If we're compiled in "CONSOLE" mode, this is already done.
// 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;
// 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.
// 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(AllocConsole()) // should only pass in "WINDOWS" mode
{
freopen("CONIN$", "r", stdin); freopen("CONIN$", "r", stdin);
freopen("CONOUT$", "wb", stdout); freopen("CONOUT$", "wb", stdout);
freopen("CONOUT$", "wb", stderr); freopen("CONOUT$", "wb", stderr);
} }
}else{ }
// we want to hide the console else {
// if we're compiled with the "WINDOWS" subsystem, this is already done. // We want to hide the console.
// if we're compiled with the "CONSOLE" subsystem, a console is already created; // If we're compiled with the "WINDOWS" subsystem, this is already done.
// it'll flash open, but we hide it nearly immediately // If we're compiled with the "CONSOLE" subsystem, a console is already created;
if(GetConsoleWindow()) // should only pass in "CONSOLE" mode // it'll flash open, but we hide it nearly immediately.
if (GetConsoleWindow()) // Should only pass in "CONSOLE" mode.
ShowWindow(GetConsoleWindow(), SW_HIDE); ShowWindow(GetConsoleWindow(), SW_HIDE);
} }
#endif #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 #ifdef FREEIMAGE_LIB
FreeImage_Initialise(); FreeImage_Initialise();
#endif #endif
//if ~/.emulationstation doesn't exist and cannot be created, bail // If ~/.emulationstation doesn't exist and cannot be created, bail.
if(!verifyHomeFolderExists()) if (!verifyHomeFolderExists())
return 1; return 1;
//start the logger // Start the logger.
Log::init(); Log::init();
Log::open(); 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); atexit(&onExit);
Window window; Window window;
@ -327,16 +354,13 @@ int main(int argc, char* argv[])
bool splashScreen = Settings::getInstance()->getBool("SplashScreen"); bool splashScreen = Settings::getInstance()->getBool("SplashScreen");
bool splashScreenProgress = Settings::getInstance()->getBool("SplashScreenProgress"); bool splashScreenProgress = Settings::getInstance()->getBool("SplashScreenProgress");
if(!scrape_cmdline) if (!scrape_cmdline) {
{ if (!window.init()) {
if(!window.init())
{
LOG(LogError) << "Window failed to initialize!"; LOG(LogError) << "Window failed to initialize!";
return 1; return 1;
} }
if(splashScreen) if (splashScreen) {
{
std::string progressText = "Loading..."; std::string progressText = "Loading...";
if (splashScreenProgress) if (splashScreenProgress)
progressText = "Loading system config..."; progressText = "Loading system config...";
@ -345,18 +369,18 @@ int main(int argc, char* argv[])
} }
const char* errorMsg = NULL; const char* errorMsg = NULL;
if(!loadSystemConfigFile(&errorMsg)) if (!loadSystemConfigFile(&errorMsg)) {
{ // Something went terribly wrong.
// something went terribly wrong if (errorMsg == NULL)
if(errorMsg == NULL)
{ {
LOG(LogError) << "Unknown error occured while parsing system config file."; LOG(LogError) << "Unknown error occured while parsing system config file.";
if(!scrape_cmdline) if (!scrape_cmdline)
Renderer::deinit(); Renderer::deinit();
return 1; 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, window.pushGui(new GuiMsgBox(&window,
errorMsg, errorMsg,
"QUIT", [] { "QUIT", [] {
@ -366,34 +390,36 @@ int main(int argc, char* argv[])
})); }));
} }
//run the command line scraper then quit // Run the command line scraper then quit.
if(scrape_cmdline) if (scrape_cmdline)
{ {
return run_scraper_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); SDL_JoystickEventState(SDL_DISABLE);
// preload what we can right away instead of waiting for the user to select it // 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 // This makes for no delays when accessing content, but a longer startup time.
ViewController::get()->preload(); ViewController::get()->preload();
if(splashScreen && splashScreenProgress) if (splashScreen && splashScreenProgress)
window.renderLoadingScreen("Done."); window.renderLoadingScreen("Done.");
//choose which GUI to open depending on if an input configuration already exists // Choose which GUI to open depending on if an input configuration already exists.
if(errorMsg == NULL) if (errorMsg == NULL) {
{ if (Utils::FileSystem::exists(InputManager::getConfigPath()) &&
if(Utils::FileSystem::exists(InputManager::getConfigPath()) && InputManager::getInstance()->getNumConfiguredDevices() > 0) InputManager::getInstance()->getNumConfiguredDevices() > 0) {
{
ViewController::get()->goToStart(); 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); SDL_JoystickEventState(SDL_ENABLE);
int lastTime = SDL_GetTicks(); int lastTime = SDL_GetTicks();
@ -401,49 +427,49 @@ int main(int argc, char* argv[])
bool running = true; bool running = true;
while(running) while (running) {
{
SDL_Event event; 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)) if (ps_standby ? SDL_WaitEventTimeout(&event, PowerSaver::getTimeout())
{ : SDL_PollEvent(&event)) {
do do {
{
InputManager::getInstance()->parseEvent(event, &window); InputManager::getInstance()->parseEvent(event, &window);
if(event.type == SDL_QUIT) if (event.type == SDL_QUIT)
running = false; 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) if (ps_standby)
// show as if continuing from last event // Show as if continuing from last event.
lastTime = SDL_GetTicks(); lastTime = SDL_GetTicks();
// reset counter // Reset counter.
ps_time = SDL_GetTicks(); ps_time = SDL_GetTicks();
} }
else if (ps_standby) else if (ps_standby) {
{ // If exiting SDL_WaitEventTimeout due to timeout.
// If exitting SDL_WaitEventTimeout due to timeout. Trail considering // Trail considering timeout as an event.
// timeout as an event
ps_time = SDL_GetTicks(); ps_time = SDL_GetTicks();
} }
if(window.isSleeping()) if (window.isSleeping()) {
{
lastTime = SDL_GetTicks(); 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; continue;
SDL_Delay(1);
} }
int curTime = SDL_GetTicks(); int curTime = SDL_GetTicks();
int deltaTime = curTime - lastTime; int deltaTime = curTime - lastTime;
lastTime = curTime; lastTime = curTime;
// cap deltaTime if it ever goes negative // Cap deltaTime if it ever goes negative.
if(deltaTime < 0) if (deltaTime < 0)
deltaTime = 1000; deltaTime = 1000;
window.update(deltaTime); window.update(deltaTime);
@ -453,7 +479,7 @@ int main(int argc, char* argv[])
Log::flush(); Log::flush();
} }
while(window.peekGui() != ViewController::get()) while (window.peekGui() != ViewController::get())
delete window.peekGui(); delete window.peekGui();
window.deinit(); window.deinit();
@ -461,7 +487,7 @@ int main(int argc, char* argv[])
CollectionSystemManager::deinit(); CollectionSystemManager::deinit();
SystemData::deleteSystems(); 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 #ifdef FREEIMAGE_LIB
FreeImage_DeInitialise(); FreeImage_DeInitialise();
#endif #endif

View file

@ -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 "Settings.h"
#include "utils/FileSystemUtil.h" #include "utils/FileSystemUtil.h"
@ -10,29 +18,37 @@
Settings* Settings::sInstance = NULL; Settings* Settings::sInstance = NULL;
// these values are NOT saved to es_settings.xml // These values are NOT saved to es_settings.cfg since they're not set via
// since they're set through command-line arguments, and not the in-program settings menu // 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<const char*> settings_dont_save { std::vector<const char*> 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" }, { "DebugGrid" },
{ "DebugText" }, { "DebugText" },
{ "DebugImage" }, { "DebugImage" },
{ "ForceKid" }, { "SplashScreenProgress" }
{ "ForceKiosk" },
{ "IgnoreGamelist" },
{ "HideConsole" },
{ "ShowExit" },
{ "SplashScreen" },
{ "SplashScreenProgress" },
{ "VSync" },
{ "Windowed" },
{ "WindowWidth" },
{ "WindowHeight" },
{ "ScreenWidth" },
{ "ScreenHeight" },
{ "ScreenOffsetX" },
{ "ScreenOffsetY" },
{ "ScreenRotate" }
}; };
Settings::Settings() Settings::Settings()
@ -44,7 +60,7 @@ Settings::Settings()
Settings* Settings::getInstance() Settings* Settings::getInstance()
{ {
if(sInstance == NULL) if (sInstance == NULL)
sInstance = new Settings(); sInstance = new Settings();
return sInstance; return sInstance;
@ -55,129 +71,148 @@ void Settings::setDefaults()
mBoolMap.clear(); mBoolMap.clear();
mIntMap.clear(); mIntMap.clear();
mBoolMap["BackgroundJoystickInput"] = false; //
mBoolMap["ParseGamelistOnly"] = false; // Settings configured via the in-program settings menu.
mBoolMap["ShowHiddenFiles"] = false; //
mBoolMap["DrawFramerate"] = false;
mBoolMap["ShowExit"] = true; // UI settings.
mBoolMap["ShowRebootSystem"] = true;
mBoolMap["ShowPoweroffSystem"] = true;
mBoolMap["Windowed"] = false;
mBoolMap["SplashScreen"] = true;
mBoolMap["SplashScreenProgress"] = true;
mStringMap["StartupSystem"] = ""; mStringMap["StartupSystem"] = "";
mBoolMap["DisableKidStartMenu"] = true; mStringMap["GamelistViewStyle"] = "automatic";
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["TransitionStyle"] = "instant"; mStringMap["TransitionStyle"] = "instant";
mStringMap["ThemeSet"] = ""; mStringMap["ThemeSet"] = "";
mStringMap["ScreenSaverBehavior"] = "dim"; mStringMap["UIMode"] = "Full";
mStringMap["Scraper"] = "ScreenScraper"; mBoolMap["FavoritesFirst"] = true;
mStringMap["GamelistViewStyle"] = "automatic"; mBoolMap["ForceDisableFilters"] = false;
mStringMap["SaveGamelistsMode"] = "always"; 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; mBoolMap["ScreenSaverControls"] = true;
mStringMap["ScreenSaverGameInfo"] = "never"; mStringMap["ScreenSaverBehavior"] = "dim";
mBoolMap["StretchVideoOnScreenSaver"] = false;
mStringMap["PowerSaverMode"] = "disabled";
// 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; mIntMap["ScreenSaverSwapImageTimeout"] = 10000;
mBoolMap["SlideshowScreenSaverStretch"] = false; 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; mBoolMap["SlideshowScreenSaverCustomImageSource"] = false;
mStringMap["SlideshowScreenSaverImageDir"] = Utils::FileSystem::getHomePath() + "/.emulationstation/slideshow/image"; mStringMap["SlideshowScreenSaverImageDir"] = Utils::FileSystem::getHomePath() +
mStringMap["SlideshowScreenSaverImageFilter"] = ".png,.jpg"; "/.emulationstation/slideshow/image";
mBoolMap["SlideshowScreenSaverRecurse"] = false; mBoolMap["SlideshowScreenSaverRecurse"] = false;
mStringMap["SlideshowScreenSaverImageFilter"] = ".png,.jpg";
// This setting only applies to raspberry pi but set it for all platforms so // Sound settings.
// we don't get a warning if we encounter it on a different platform mStringMap["AudioCard"] = "default";
mBoolMap["VideoOmxPlayer"] = false; // Audio out device for volume control.
#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
#ifdef _RPI_ #ifdef _RPI_
mStringMap["AudioDevice"] = "PCM"; mStringMap["AudioDevice"] = "PCM";
#else #else
mStringMap["AudioDevice"] = "Master"; mStringMap["AudioDevice"] = "Master";
#endif #endif
mBoolMap["VideoAudio"] = true;
mBoolMap["EnableSounds"] = true;
// Audio out device for Video playback using OMX player.
mStringMap["OMXAudioDev"] = "both";
mStringMap["AudioCard"] = "default"; // Game collection settings.
mStringMap["UIMode"] = "Full"; mStringMap["CollectionSystemsAuto"] = "";
mStringMap["UIMode_passkey"] = "uuddlrlrba"; mStringMap["CollectionSystemsCustom"] = "";
mBoolMap["ForceKiosk"] = false; 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["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["WindowWidth"] = 0;
mIntMap["WindowHeight"] = 0; mIntMap["WindowHeight"] = 0;
mIntMap["ScreenWidth"] = 0; mIntMap["ScreenWidth"] = 0;
// Undocumented options.
mIntMap["ScreenHeight"] = 0; mIntMap["ScreenHeight"] = 0;
mIntMap["ScreenOffsetX"] = 0; mIntMap["ScreenOffsetX"] = 0;
mIntMap["ScreenOffsetY"] = 0; mIntMap["ScreenOffsetY"] = 0;
mIntMap["ScreenRotate"] = 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 <typename K, typename V> template <typename K, typename V>
void saveMap(pugi::xml_document& doc, std::map<K, V>& map, const char* type) void saveMap(pugi::xml_document& doc, std::map<K, V>& map, const char* type)
{ {
for(auto iter = map.cbegin(); iter != map.cend(); iter++) for (auto iter = map.cbegin(); iter != map.cend(); iter++) {
{ // Key is on the "don't save" list, so don't save it.
// key is on the "don't save" list, so don't save it if (std::find(settings_dont_save.cbegin(), settings_dont_save.cend(),
if(std::find(settings_dont_save.cbegin(), settings_dont_save.cend(), iter->first) != settings_dont_save.cend()) iter->first) != settings_dont_save.cend())
continue; continue;
pugi::xml_node node = doc.append_child(type); pugi::xml_node node = doc.append_child(type);
@ -189,7 +224,8 @@ void saveMap(pugi::xml_document& doc, std::map<K, V>& map, const char* type)
void Settings::saveFile() void Settings::saveFile()
{ {
LOG(LogDebug) << "Settings::saveFile() : Saving Settings to file."; 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; pugi::xml_document doc;
@ -198,8 +234,7 @@ void Settings::saveFile()
saveMap<std::string, float>(doc, mFloatMap, "float"); saveMap<std::string, float>(doc, mFloatMap, "float");
//saveMap<std::string, std::string>(doc, mStringMap, "string"); //saveMap<std::string, std::string>(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"); pugi::xml_node node = doc.append_child("string");
node.append_attribute("name").set_value(iter->first.c_str()); node.append_attribute("name").set_value(iter->first.c_str());
node.append_attribute("value").set_value(iter->second.c_str()); node.append_attribute("value").set_value(iter->second.c_str());
@ -213,47 +248,35 @@ void Settings::saveFile()
void Settings::loadFile() 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; return;
pugi::xml_document doc; pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file(path.c_str()); 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(); LOG(LogError) << "Could not parse Settings file!\n " << result.description();
return; 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()); 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()); 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()); 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()); setString(node.attribute("name").as_string(), node.attribute("value").as_string());
processBackwardCompatibility();
} }
void Settings::processBackwardCompatibility() // 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.
{ // SaveGamelistsOnExit -> SaveGamelistsMode #define SETTINGS_GETSET(type, mapName, getMethodName, setMethodName) \
std::map<std::string, bool>::const_iterator it = mBoolMap.find("SaveGamelistsOnExit"); type Settings::getMethodName(const std::string& name) \
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) \
{ \ { \
if(mapName.find(name) == mapName.cend()) \ if (mapName.find(name) == mapName.cend()) { \
{ \
LOG(LogError) << "Tried to use unset setting " << name << "!"; \ LOG(LogError) << "Tried to use unset setting " << name << "!"; \
} \ } \
return mapName[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) { \ if (mapName.count(name) == 0 || mapName[name] != value) { \
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; \ mWasChanged = true; \
\ \
return true; \ return true; \

View file

@ -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 #pragma once
#ifndef ES_CORE_SETTINGS_H #ifndef ES_CORE_SETTINGS_H
#define ES_CORE_SETTINGS_H #define ES_CORE_SETTINGS_H
#include <map> #include <map>
//This is a singleton for storing settings. // This is a singleton for storing settings.
class Settings class Settings
{ {
public: public:
@ -13,7 +21,7 @@ public:
void loadFile(); void loadFile();
void saveFile(); 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); bool getBool(const std::string& name);
int getInt(const std::string& name); int getInt(const std::string& name);
float getFloat(const std::string& name); float getFloat(const std::string& name);
@ -29,9 +37,8 @@ private:
Settings(); Settings();
//Clear everything and load default values. // Clear everything and load default values.
void setDefaults(); void setDefaults();
void processBackwardCompatibility();
bool mWasChanged; bool mWasChanged;