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
#ifndef 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())); });
if (UIModeController::getInstance()->isUIModeFull()) {
#if defined(__linux__)
#if defined(__linux__)
// audio card
auto audio_card = std::make_shared< OptionListComponent<std::string>
>(mWindow, "AUDIO CARD", false);
std::vector<std::string> 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<SwitchComponent>(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<std::string>
>(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<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.
auto gamelistsSaveMode = std::make_shared< OptionListComponent<std::string>
>(mWindow, "SAVE METADATA", false);
@ -522,7 +542,7 @@ void GuiMenu::openOtherSettings()
auto local_art = std::make_shared<SwitchComponent>(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<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);
}

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/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

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 "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<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" },
{ "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 <typename K, typename V>
void saveMap(pugi::xml_document& doc, std::map<K, V>& 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<K, V>& 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<std::string, float>(doc, mFloatMap, "float");
//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");
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<std::string, bool>::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; \

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
#ifndef ES_CORE_SETTINGS_H
#define ES_CORE_SETTINGS_H
#include <map>
//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<std::string, bool> mBoolMap;
std::map<std::string, int> mIntMap;
std::map<std::string, float> mFloatMap;