mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-24 23:25:38 +00:00
Added proper error handling for resource files and improved overall logging.
This commit is contained in:
parent
04d4658fc9
commit
5a7fb828a6
1
NEWS.md
1
NEWS.md
|
@ -24,6 +24,7 @@ v1.0.0
|
||||||
* Moved all resources to a subdirectory structure and enabled the CMake install prefix variable to generate the resources search path
|
* Moved all resources to a subdirectory structure and enabled the CMake install prefix variable to generate the resources search path
|
||||||
* Changed theme directory to the install prefix (e.g. /usr/local/share/emulationstation/themes) with themes in the home directory taking precedence
|
* Changed theme directory to the install prefix (e.g. /usr/local/share/emulationstation/themes) with themes in the home directory taking precedence
|
||||||
* No more attempts to open files directly under /etc, instead only the install prefix directory and the home directory are used
|
* No more attempts to open files directly under /etc, instead only the install prefix directory and the home directory are used
|
||||||
|
* Added proper error handling for missing resource files and improved overall logging
|
||||||
* Refactoring, cleanup and documentation of the source code, removal of deprecated files etc.
|
* Refactoring, cleanup and documentation of the source code, removal of deprecated files etc.
|
||||||
* All required fonts bundled with the application, no dependencies on the OS to provide them any longer
|
* All required fonts bundled with the application, no dependencies on the OS to provide them any longer
|
||||||
* Made pugixml an external dependency instead of bundling it
|
* Made pugixml an external dependency instead of bundling it
|
||||||
|
|
|
@ -94,8 +94,14 @@ void SystemData::setIsGameSystemStatus()
|
||||||
bool SystemData::populateFolder(FileData* folder)
|
bool SystemData::populateFolder(FileData* folder)
|
||||||
{
|
{
|
||||||
const std::string& folderPath = folder->getPath();
|
const std::string& folderPath = folder->getPath();
|
||||||
|
if (!Utils::FileSystem::exists(folderPath)) {
|
||||||
|
LOG(LogInfo) << "Info - Folder with path \"" <<
|
||||||
|
folderPath << "\" does not exist.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (!Utils::FileSystem::isDirectory(folderPath)) {
|
if (!Utils::FileSystem::isDirectory(folderPath)) {
|
||||||
LOG(LogWarning) << "Error - folder with path \"" << folderPath << "\" is not a directory!";
|
LOG(LogWarning) << "Warning - Folder with path \"" <<
|
||||||
|
folderPath << "\" is not a directory!";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +110,8 @@ bool SystemData::populateFolder(FileData* folder)
|
||||||
// If this symlink resolves to somewhere that's at the beginning of our
|
// If this symlink resolves to somewhere that's at the beginning of our
|
||||||
// path, it's going to create a recursive loop. Make sure to avoid this.
|
// path, it's going to create a recursive loop. Make sure to avoid this.
|
||||||
if (folderPath.find(Utils::FileSystem::getCanonicalPath(folderPath)) == 0) {
|
if (folderPath.find(Utils::FileSystem::getCanonicalPath(folderPath)) == 0) {
|
||||||
LOG(LogWarning) << "Skipping infinitely recursive symlink \"" << folderPath << "\"";
|
LOG(LogWarning) << "Warning - Skipping infinitely recursive symlink \"" <<
|
||||||
|
folderPath << "\"";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,7 +218,7 @@ bool SystemData::loadConfig()
|
||||||
LOG(LogInfo) << "Loading system config file " << path << "...";
|
LOG(LogInfo) << "Loading system config file " << path << "...";
|
||||||
|
|
||||||
if (!Utils::FileSystem::exists(path)) {
|
if (!Utils::FileSystem::exists(path)) {
|
||||||
LOG(LogError) << "es_systems.cfg file does not exist!";
|
LOG(LogError) << "Error - es_systems.cfg file does not exist!";
|
||||||
writeExampleConfig(getConfigPath(true));
|
writeExampleConfig(getConfigPath(true));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -220,7 +227,7 @@ bool SystemData::loadConfig()
|
||||||
pugi::xml_parse_result res = doc.load_file(path.c_str());
|
pugi::xml_parse_result res = doc.load_file(path.c_str());
|
||||||
|
|
||||||
if (!res) {
|
if (!res) {
|
||||||
LOG(LogError) << "Could not parse es_systems.cfg file!";
|
LOG(LogError) << "Error - Could not parse es_systems.cfg file!";
|
||||||
LOG(LogError) << res.description();
|
LOG(LogError) << res.description();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -229,7 +236,7 @@ bool SystemData::loadConfig()
|
||||||
pugi::xml_node systemList = doc.child("systemList");
|
pugi::xml_node systemList = doc.child("systemList");
|
||||||
|
|
||||||
if (!systemList) {
|
if (!systemList) {
|
||||||
LOG(LogError) << "es_systems.cfg is missing the <systemList> tag!";
|
LOG(LogError) << "Error - es_systems.cfg is missing the <systemList> tag!";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,8 +282,8 @@ bool SystemData::loadConfig()
|
||||||
// If there appears to be an actual platform ID supplied
|
// If there appears to be an actual platform ID supplied
|
||||||
// but it didn't match the list, generate a warning.
|
// but it didn't match the list, generate a warning.
|
||||||
if (str != nullptr && str[0] != '\0' && platformId == PlatformIds::PLATFORM_UNKNOWN)
|
if (str != nullptr && str[0] != '\0' && platformId == PlatformIds::PLATFORM_UNKNOWN)
|
||||||
LOG(LogWarning) << "Unknown platform for system \"" << name << "\" (platform \""
|
LOG(LogWarning) << "Warning - Unknown platform for system \"" << name <<
|
||||||
<< str << "\" from list \"" << platformList << "\")";
|
"\" (platform \"" << str << "\" from list \"" << platformList << "\")";
|
||||||
else if (platformId != PlatformIds::PLATFORM_UNKNOWN)
|
else if (platformId != PlatformIds::PLATFORM_UNKNOWN)
|
||||||
platformIds.push_back(platformId);
|
platformIds.push_back(platformId);
|
||||||
}
|
}
|
||||||
|
@ -286,7 +293,7 @@ bool SystemData::loadConfig()
|
||||||
|
|
||||||
// Validate.
|
// Validate.
|
||||||
if (name.empty() || path.empty() || extensions.empty() || cmd.empty()) {
|
if (name.empty() || path.empty() || extensions.empty() || cmd.empty()) {
|
||||||
LOG(LogError) << "System \"" << name <<
|
LOG(LogError) << "Error - System \"" << name <<
|
||||||
"\" is missing name, path, extension, or command!";
|
"\" is missing name, path, extension, or command!";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -310,7 +317,7 @@ bool SystemData::loadConfig()
|
||||||
|
|
||||||
SystemData* newSys = new SystemData(name, fullname, envData, themeFolder);
|
SystemData* newSys = new SystemData(name, fullname, envData, themeFolder);
|
||||||
if (newSys->getRootFolder()->getChildrenByFilename().size() == 0) {
|
if (newSys->getRootFolder()->getChildrenByFilename().size() == 0) {
|
||||||
LOG(LogWarning) << "System \"" << name << "\" has no games! Ignoring it.";
|
LOG(LogInfo) << "Info - System \"" << name << "\" has no games, ignoring it.";
|
||||||
delete newSys;
|
delete newSys;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -416,12 +416,18 @@ 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");
|
||||||
|
SDL_Event event;
|
||||||
|
|
||||||
if (!window.init()) {
|
if (!window.init()) {
|
||||||
LOG(LogError) << "Window failed to initialize!";
|
LOG(LogError) << "Window failed to initialize!";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InputManager::getInstance()->parseEvent(event, &window);
|
||||||
|
if (event.type == SDL_QUIT)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
|
||||||
if (splashScreen) {
|
if (splashScreen) {
|
||||||
std::string progressText = "Loading...";
|
std::string progressText = "Loading...";
|
||||||
if (splashScreenProgress)
|
if (splashScreenProgress)
|
||||||
|
@ -433,8 +439,7 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
if (loadSystemConfigFile(errorMsg) != NO_ERRORS) {
|
if (loadSystemConfigFile(errorMsg) != NO_ERRORS) {
|
||||||
// Something went terribly wrong.
|
// Something went terribly wrong.
|
||||||
if (errorMsg == "")
|
if (errorMsg == "") {
|
||||||
{
|
|
||||||
LOG(LogError) << "Unknown error occured while parsing system config file.";
|
LOG(LogError) << "Unknown error occured while parsing system config file.";
|
||||||
Renderer::deinit();
|
Renderer::deinit();
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -161,8 +161,8 @@ void thegamesdb_generate_json_scraper_requests(
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG(LogWarning) << "TheGamesDB scraper warning - no support for platform "
|
LOG(LogWarning) << "Warning - TheGamesDB scraper warning - "
|
||||||
<< getPlatformName(*platformIt);
|
"no support for platform " << getPlatformName(*platformIt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
path += platformQueryParam;
|
path += platformQueryParam;
|
||||||
|
@ -290,6 +290,7 @@ void processGame(const Value& game, std::vector<ScraperSearchResult>& results)
|
||||||
result.gameID = std::to_string(getIntOrThrow(game, "id"));
|
result.gameID = std::to_string(getIntOrThrow(game, "id"));
|
||||||
|
|
||||||
result.mdl.set("name", getStringOrThrow(game, "game_title"));
|
result.mdl.set("name", getStringOrThrow(game, "game_title"));
|
||||||
|
|
||||||
if (game.HasMember("overview") && game["overview"].IsString())
|
if (game.HasMember("overview") && game["overview"].IsString())
|
||||||
result.mdl.set("desc", game["overview"].GetString());
|
result.mdl.set("desc", game["overview"].GetString());
|
||||||
|
|
||||||
|
@ -309,6 +310,21 @@ void processGame(const Value& game, std::vector<ScraperSearchResult>& results)
|
||||||
if (game.HasMember("players") && game["players"].IsInt())
|
if (game.HasMember("players") && game["players"].IsInt())
|
||||||
result.mdl.set("players", std::to_string(game["players"].GetInt()));
|
result.mdl.set("players", std::to_string(game["players"].GetInt()));
|
||||||
|
|
||||||
|
LOG(LogDebug) << "GamesDBJSONScraper::processGame(): Name: " <<
|
||||||
|
result.mdl.get("name");
|
||||||
|
LOG(LogDebug) << "GamesDBJSONScraper::processGame(): Release Date (unparsed): " <<
|
||||||
|
game["release_date"].GetString();
|
||||||
|
LOG(LogDebug) << "GamesDBJSONScraper::processGame(): Release Date (parsed): " <<
|
||||||
|
result.mdl.get("releasedate");
|
||||||
|
LOG(LogDebug) << "GamesDBJSONScraper::processGame(): Developer: " <<
|
||||||
|
result.mdl.get("developer");
|
||||||
|
LOG(LogDebug) << "GamesDBJSONScraper::processGame(): Publisher: " <<
|
||||||
|
result.mdl.get("publisher");
|
||||||
|
LOG(LogDebug) << "GamesDBJSONScraper::processGame(): Genre: " <<
|
||||||
|
result.mdl.get("genre");
|
||||||
|
LOG(LogDebug) << "GamesDBJSONScraper::processGame(): Players: " <<
|
||||||
|
result.mdl.get("players");
|
||||||
|
|
||||||
result.mediaURLFetch = NOT_STARTED;
|
result.mediaURLFetch = NOT_STARTED;
|
||||||
results.push_back(result);
|
results.push_back(result);
|
||||||
}
|
}
|
||||||
|
@ -365,7 +381,7 @@ void TheGamesDBJSONRequest::process(const std::unique_ptr<HttpReq>& req,
|
||||||
|
|
||||||
if (doc.HasParseError()) {
|
if (doc.HasParseError()) {
|
||||||
std::string err =
|
std::string err =
|
||||||
std::string("TheGamesDBJSONRequest - Error parsing JSON. \n\t") +
|
std::string("Error - TheGamesDBJSONRequest - Error parsing JSON. \n\t") +
|
||||||
GetParseError_En(doc.GetParseError());
|
GetParseError_En(doc.GetParseError());
|
||||||
setError(err);
|
setError(err);
|
||||||
LOG(LogError) << err;
|
LOG(LogError) << err;
|
||||||
|
@ -384,7 +400,7 @@ void TheGamesDBJSONRequest::process(const std::unique_ptr<HttpReq>& req,
|
||||||
baseImageUrlLarge = base_url["large"].GetString();
|
baseImageUrlLarge = base_url["large"].GetString();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
std::string warn = "TheGamesDBJSONRequest - No URL path for large images.\n";
|
std::string warn = "Warning - TheGamesDBJSONRequest - No URL path for large images.\n";
|
||||||
LOG(LogWarning) << warn;
|
LOG(LogWarning) << warn;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -393,7 +409,7 @@ void TheGamesDBJSONRequest::process(const std::unique_ptr<HttpReq>& req,
|
||||||
processMediaURLs(images, baseImageUrlLarge, results);
|
processMediaURLs(images, baseImageUrlLarge, results);
|
||||||
}
|
}
|
||||||
catch (std::runtime_error& e) {
|
catch (std::runtime_error& e) {
|
||||||
LOG(LogError) << "Error while processing media URLs: " << e.what();
|
LOG(LogError) << "Error - Error while processing media URLs: " << e.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find how many more requests we can make before the scraper
|
// Find how many more requests we can make before the scraper
|
||||||
|
@ -412,7 +428,7 @@ void TheGamesDBJSONRequest::process(const std::unique_ptr<HttpReq>& req,
|
||||||
// These process steps are for the initial scraping response.
|
// These process steps are for the initial scraping response.
|
||||||
if (!doc.HasMember("data") || !doc["data"].HasMember("games") ||
|
if (!doc.HasMember("data") || !doc["data"].HasMember("games") ||
|
||||||
!doc["data"]["games"].IsArray()) {
|
!doc["data"]["games"].IsArray()) {
|
||||||
std::string warn = "TheGamesDBJSONRequest - Response had no game data.\n";
|
std::string warn = "Warning - TheGamesDBJSONRequest - Response had no game data.\n";
|
||||||
LOG(LogWarning) << warn;
|
LOG(LogWarning) << warn;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -426,7 +442,7 @@ void TheGamesDBJSONRequest::process(const std::unique_ptr<HttpReq>& req,
|
||||||
processGame(v, results);
|
processGame(v, results);
|
||||||
}
|
}
|
||||||
catch (std::runtime_error& e) {
|
catch (std::runtime_error& e) {
|
||||||
LOG(LogError) << "Error while processing game: " << e.what();
|
LOG(LogError) << "Error - Error while processing game: " << e.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,8 @@ std::unique_ptr<ScraperSearchHandle> startScraperSearch(const ScraperSearchParam
|
||||||
|
|
||||||
// Check if the scraper in the settings still exists as a registered scraping source.
|
// Check if the scraper in the settings still exists as a registered scraping source.
|
||||||
if (scraper_request_funcs.find(name) == scraper_request_funcs.end())
|
if (scraper_request_funcs.find(name) == scraper_request_funcs.end())
|
||||||
LOG(LogWarning) << "Configured scraper (" << name << ") unavailable, scraping aborted.";
|
LOG(LogWarning) << "Warning - Configured scraper (" << name <<
|
||||||
|
") unavailable, scraping aborted.";
|
||||||
else
|
else
|
||||||
scraper_request_funcs.at(name)(params, handle->mRequestQueue, handle->mResults);
|
scraper_request_funcs.at(name)(params, handle->mRequestQueue, handle->mResults);
|
||||||
|
|
||||||
|
@ -44,7 +45,8 @@ std::unique_ptr<ScraperSearchHandle> startMediaURLsFetch(const std::string& game
|
||||||
ScraperSearchParams params;
|
ScraperSearchParams params;
|
||||||
// Check if the scraper in the settings still exists as a registered scraping source.
|
// Check if the scraper in the settings still exists as a registered scraping source.
|
||||||
if (scraper_request_funcs.find(name) == scraper_request_funcs.end())
|
if (scraper_request_funcs.find(name) == scraper_request_funcs.end())
|
||||||
LOG(LogWarning) << "Configured scraper (" << name << ") unavailable, scraping aborted.";
|
LOG(LogWarning) << "Warning - Configured scraper (" << name <<
|
||||||
|
") unavailable, scraping aborted.";
|
||||||
else
|
else
|
||||||
// Specifically use the TheGamesDB function as this type of request
|
// Specifically use the TheGamesDB function as this type of request
|
||||||
// will never occur for ScreenScraper.
|
// will never occur for ScreenScraper.
|
||||||
|
@ -140,7 +142,7 @@ void ScraperHttpRequest::update()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Everything else is some sort of error.
|
// Everything else is some sort of error.
|
||||||
LOG(LogError) << "ScraperHttpRequest network error (status: " << status<< ") - "
|
LOG(LogError) << "Error - ScraperHttpRequest network error (status: " << status<< ") - "
|
||||||
<< mReq->getErrorMsg();
|
<< mReq->getErrorMsg();
|
||||||
setError(mReq->getErrorMsg());
|
setError(mReq->getErrorMsg());
|
||||||
}
|
}
|
||||||
|
@ -367,7 +369,7 @@ bool resizeImage(const std::string& path, int maxWidth, int maxHeight)
|
||||||
if (format == FIF_UNKNOWN)
|
if (format == FIF_UNKNOWN)
|
||||||
format = FreeImage_GetFIFFromFilename(path.c_str());
|
format = FreeImage_GetFIFFromFilename(path.c_str());
|
||||||
if (format == FIF_UNKNOWN) {
|
if (format == FIF_UNKNOWN) {
|
||||||
LOG(LogError) << "Error - could not detect filetype for image \"" << path << "\"!";
|
LOG(LogError) << "Error - Could not detect filetype for image \"" << path << "\"!";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,7 +378,7 @@ bool resizeImage(const std::string& path, int maxWidth, int maxHeight)
|
||||||
image = FreeImage_Load(format, path.c_str());
|
image = FreeImage_Load(format, path.c_str());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG(LogError) << "Error - file format reading not supported for image \"" << path << "\"!";
|
LOG(LogError) << "Error - File format not supported for image \"" << path << "\"!";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,7 +399,7 @@ bool resizeImage(const std::string& path, int maxWidth, int maxHeight)
|
||||||
FreeImage_Unload(image);
|
FreeImage_Unload(image);
|
||||||
|
|
||||||
if (imageRescaled == nullptr) {
|
if (imageRescaled == nullptr) {
|
||||||
LOG(LogError) << "Could not resize image! (not enough memory? invalid bitdepth?)";
|
LOG(LogError) << "Error - Could not resize image! (not enough memory? invalid bitdepth?)";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,7 +407,7 @@ bool resizeImage(const std::string& path, int maxWidth, int maxHeight)
|
||||||
FreeImage_Unload(imageRescaled);
|
FreeImage_Unload(imageRescaled);
|
||||||
|
|
||||||
if (!saved) {
|
if (!saved) {
|
||||||
LOG(LogError) << "Failed to save resized image!";
|
LOG(LogError) << "Error - Failed to save resized image!";
|
||||||
}
|
}
|
||||||
|
|
||||||
return saved;
|
return saved;
|
||||||
|
|
|
@ -149,7 +149,7 @@ void screenscraper_generate_scraper_requests(const ScraperSearchParams& params,
|
||||||
p_ids.push_back(mapIt->second);
|
p_ids.push_back(mapIt->second);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG(LogWarning) << "ScreenScraper: no support for platform " <<
|
LOG(LogWarning) << "Warning - ScreenScraper: no support for platform " <<
|
||||||
getPlatformName(*platformIt);
|
getPlatformName(*platformIt);
|
||||||
// Add the scrape request without a platform/system ID.
|
// Add the scrape request without a platform/system ID.
|
||||||
requests.push(std::unique_ptr<ScraperRequest>
|
requests.push(std::unique_ptr<ScraperRequest>
|
||||||
|
@ -180,8 +180,7 @@ void ScreenScraperRequest::process(const std::unique_ptr<HttpReq>& req,
|
||||||
|
|
||||||
if (!parseResult) {
|
if (!parseResult) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "ScreenScraperRequest - Error parsing XML." << std::endl <<
|
ss << "Error - ScreenScraperRequest - Error parsing XML: " << parseResult.description();
|
||||||
parseResult.description() << "";
|
|
||||||
|
|
||||||
std::string err = ss.str();
|
std::string err = ss.str();
|
||||||
setError(err);
|
setError(err);
|
||||||
|
@ -232,14 +231,12 @@ void ScreenScraperRequest::processGame(const pugi::xml_document& xmldoc,
|
||||||
// Genre fallback language: EN. ( Xpath: Data/jeu[0]/genres/genre[*] ).
|
// Genre fallback language: EN. ( Xpath: Data/jeu[0]/genres/genre[*] ).
|
||||||
result.mdl.set("genre", find_child_by_attribute_list(game.child("genres"),
|
result.mdl.set("genre", find_child_by_attribute_list(game.child("genres"),
|
||||||
"genre", "langue", { language, "en" }).text().get());
|
"genre", "langue", { language, "en" }).text().get());
|
||||||
LOG(LogDebug) << "Genre: " << result.mdl.get("genre");
|
|
||||||
|
|
||||||
// Get the date proper. The API returns multiple 'date' children nodes to the 'dates'
|
// Get the date proper. The API returns multiple 'date' children nodes to the 'dates'
|
||||||
// main child of 'jeu'.
|
// main child of 'jeu'.
|
||||||
// Date fallback: WOR(LD), US, SS, JP, EU.
|
// Date fallback: WOR(LD), US, SS, JP, EU.
|
||||||
std::string _date = find_child_by_attribute_list(game.child("dates"), "date", "region",
|
std::string _date = find_child_by_attribute_list(game.child("dates"), "date", "region",
|
||||||
{ region, "wor", "us", "ss", "jp", "eu" }).text().get();
|
{ region, "wor", "us", "ss", "jp", "eu" }).text().get();
|
||||||
LOG(LogDebug) << "Release Date (unparsed): " << _date;
|
|
||||||
|
|
||||||
// Date can be YYYY-MM-DD or just YYYY.
|
// Date can be YYYY-MM-DD or just YYYY.
|
||||||
if (_date.length() > 4) {
|
if (_date.length() > 4) {
|
||||||
|
@ -251,8 +248,6 @@ void ScreenScraperRequest::processGame(const pugi::xml_document& xmldoc,
|
||||||
Utils::Time::stringToTime(_date, "%Y")));
|
Utils::Time::stringToTime(_date, "%Y")));
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(LogDebug) << "Release Date (parsed): " << result.mdl.get("releasedate");
|
|
||||||
|
|
||||||
/// Developer for the game( Xpath: Data/jeu[0]/developpeur ).
|
/// Developer for the game( Xpath: Data/jeu[0]/developpeur ).
|
||||||
std::string developer = game.child("developpeur").text().get();
|
std::string developer = game.child("developpeur").text().get();
|
||||||
if (!developer.empty())
|
if (!developer.empty())
|
||||||
|
@ -276,6 +271,21 @@ void ScreenScraperRequest::processGame(const pugi::xml_document& xmldoc,
|
||||||
result.mdl.set("rating", ss.str());
|
result.mdl.set("rating", ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG(LogDebug) << "ScreenScraperRequest::processGame(): Name: " <<
|
||||||
|
result.mdl.get("name");
|
||||||
|
LOG(LogDebug) << "ScreenScraperRequest::processGame(): Release Date (unparsed): " <<
|
||||||
|
_date;
|
||||||
|
LOG(LogDebug) << "ScreenScraperRequest::processGame(): Release Date (parsed): " <<
|
||||||
|
result.mdl.get("releasedate");
|
||||||
|
LOG(LogDebug) << "ScreenScraperRequest::processGame(): Developer: " <<
|
||||||
|
result.mdl.get("developer");
|
||||||
|
LOG(LogDebug) << "ScreenScraperRequest::processGame(): Publisher: " <<
|
||||||
|
result.mdl.get("publisher");
|
||||||
|
LOG(LogDebug) << "ScreenScraperRequest::processGame(): Genre: " <<
|
||||||
|
result.mdl.get("genre");
|
||||||
|
LOG(LogDebug) << "ScreenScraperRequest::processGame(): Players: " <<
|
||||||
|
result.mdl.get("players");
|
||||||
|
|
||||||
// Media super-node.
|
// Media super-node.
|
||||||
pugi::xml_node media_list = game.child("medias");
|
pugi::xml_node media_list = game.child("medias");
|
||||||
|
|
||||||
|
@ -352,13 +362,13 @@ void ScreenScraperRequest::processList(const pugi::xml_document& xmldoc,
|
||||||
{
|
{
|
||||||
assert(mRequestQueue != nullptr);
|
assert(mRequestQueue != nullptr);
|
||||||
|
|
||||||
LOG(LogDebug) << "Processing a list of results";
|
LOG(LogDebug) << "ScreenScraper: Processing a list of results";
|
||||||
|
|
||||||
pugi::xml_node data = xmldoc.child("Data");
|
pugi::xml_node data = xmldoc.child("Data");
|
||||||
pugi::xml_node game = data.child("jeu");
|
pugi::xml_node game = data.child("jeu");
|
||||||
|
|
||||||
if (!game) {
|
if (!game) {
|
||||||
LOG(LogDebug) << "Found nothing";
|
LOG(LogDebug) << "ScreenScraper: Found nothing";
|
||||||
}
|
}
|
||||||
|
|
||||||
ScreenScraperRequest::ScreenScraperConfig ssConfig;
|
ScreenScraperRequest::ScreenScraperConfig ssConfig;
|
||||||
|
|
|
@ -146,8 +146,8 @@ void UIModeController::logInput(InputConfig * config, Input input)
|
||||||
mapname += ", ";
|
mapname += ", ";
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(LogDebug) << "UIModeController::logInput( " << config->getDeviceName() <<
|
LOG(LogDebug) << "UIModeController::logInput(" << config->getDeviceName() <<
|
||||||
" ):" << input.string() << ", isMappedTo= " << mapname << ", value=" << input.value;
|
"): " << input.string() << ", isMappedTo=" << mapname << ", value=" << input.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UIModeController::isValidInput(InputConfig * config, Input input)
|
bool UIModeController::isValidInput(InputConfig * config, Input input)
|
||||||
|
|
|
@ -65,7 +65,8 @@ std::vector<unsigned char> ImageIO::loadFromMemoryRGBA32(const unsigned char * d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG(LogError) << "Error - File type " <<
|
LOG(LogError) << "Error - Couldn't load image, file is missing or the file type is " <<
|
||||||
|
// it's not existing or the file type " <<
|
||||||
(format == FIF_UNKNOWN ? "unknown" : "unsupported") << "!";
|
(format == FIF_UNKNOWN ? "unknown" : "unsupported") << "!";
|
||||||
}
|
}
|
||||||
// Free fiMemory again
|
// Free fiMemory again
|
||||||
|
|
|
@ -5,7 +5,12 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
|
|
||||||
|
#include "renderers/Renderer.h"
|
||||||
#include "utils/StringUtil.h"
|
#include "utils/StringUtil.h"
|
||||||
|
#include "AudioManager.h"
|
||||||
|
#include "Log.h"
|
||||||
|
#include "MameNames.h"
|
||||||
|
|
||||||
#if defined(__linux__) || defined(_WIN64)
|
#if defined(__linux__) || defined(_WIN64)
|
||||||
#include <SDL2/SDL_events.h>
|
#include <SDL2/SDL_events.h>
|
||||||
|
@ -22,8 +27,6 @@
|
||||||
#endif
|
#endif
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include "Log.h"
|
|
||||||
|
|
||||||
int runRebootCommand()
|
int runRebootCommand()
|
||||||
{
|
{
|
||||||
#ifdef _WIN64 // Windows.
|
#ifdef _WIN64 // Windows.
|
||||||
|
@ -141,6 +144,19 @@ int quitES(QuitMode mode)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void emergencyShutdown()
|
||||||
|
{
|
||||||
|
LOG(LogError) << "Critical Error - Performing emergency shutdown...";
|
||||||
|
|
||||||
|
MameNames::deinit();
|
||||||
|
AudioManager::getInstance()->deinit();
|
||||||
|
// Most of the SDL deinitialization is done in Renderer.
|
||||||
|
Renderer::deinit();
|
||||||
|
Log::flush();
|
||||||
|
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
void touch(const std::string& filename)
|
void touch(const std::string& filename)
|
||||||
{
|
{
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
|
|
|
@ -29,7 +29,10 @@ int runSystemCommand(const std::wstring& cmd_utf16);
|
||||||
int launchEmulatorUnix(const std::string& cmd_utf8);
|
int launchEmulatorUnix(const std::string& cmd_utf8);
|
||||||
int launchEmulatorWindows(const std::wstring& cmd_utf16);
|
int launchEmulatorWindows(const std::wstring& cmd_utf16);
|
||||||
|
|
||||||
|
// Clean, normal shutdown.
|
||||||
int quitES(QuitMode mode = QuitMode::QUIT);
|
int quitES(QuitMode mode = QuitMode::QUIT);
|
||||||
|
// Immediately shut down the application as cleanly as possible.
|
||||||
|
void emergencyShutdown();
|
||||||
void processQuitMode();
|
void processQuitMode();
|
||||||
|
|
||||||
#endif // ES_CORE_PLATFORM_H
|
#endif // ES_CORE_PLATFORM_H
|
||||||
|
|
|
@ -37,8 +37,8 @@ namespace Renderer
|
||||||
{
|
{
|
||||||
size_t width = 0;
|
size_t width = 0;
|
||||||
size_t height = 0;
|
size_t height = 0;
|
||||||
ResourceData resData =
|
ResourceData resData = ResourceManager::getInstance()->
|
||||||
ResourceManager::getInstance()->getFileData(":/graphics/window_icon_256.png");
|
getFileData(":/graphics/window_icon_256.png");
|
||||||
std::vector<unsigned char> rawData =
|
std::vector<unsigned char> rawData =
|
||||||
ImageIO::loadFromMemoryRGBA32(resData.ptr.get(), resData.length, width, height);
|
ImageIO::loadFromMemoryRGBA32(resData.ptr.get(), resData.length, width, height);
|
||||||
|
|
||||||
|
|
|
@ -213,6 +213,13 @@ std::vector<std::string> getFallbackFontPaths()
|
||||||
{
|
{
|
||||||
std::vector<std::string> fontPaths;
|
std::vector<std::string> fontPaths;
|
||||||
|
|
||||||
|
// Standard fonts, let's include them here for error checking purposes even though that's
|
||||||
|
// not really the correct location. (The application will crash if they are missing.)
|
||||||
|
ResourceManager::getInstance()->
|
||||||
|
getResourcePath(":/fonts/opensans_hebrew_condensed_light.ttf");
|
||||||
|
ResourceManager::getInstance()->
|
||||||
|
getResourcePath(":/fonts/opensans_hebrew_condensed_regular.ttf");
|
||||||
|
|
||||||
// Vera sans Unicode:
|
// Vera sans Unicode:
|
||||||
fontPaths.push_back(ResourceManager::getInstance()->
|
fontPaths.push_back(ResourceManager::getInstance()->
|
||||||
getResourcePath(":/fonts/DejaVuSans.ttf"));
|
getResourcePath(":/fonts/DejaVuSans.ttf"));
|
||||||
|
|
|
@ -8,6 +8,10 @@
|
||||||
#include "ResourceManager.h"
|
#include "ResourceManager.h"
|
||||||
|
|
||||||
#include "utils/FileSystemUtil.h"
|
#include "utils/FileSystemUtil.h"
|
||||||
|
#include "Log.h"
|
||||||
|
#include "Platform.h"
|
||||||
|
#include "Scripting.h"
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
auto array_deleter = [](unsigned char* p) { delete[] p; };
|
auto array_deleter = [](unsigned char* p) { delete[] p; };
|
||||||
|
@ -31,23 +35,36 @@ std::string ResourceManager::getResourcePath(const std::string& path) const
|
||||||
{
|
{
|
||||||
// Check if this is a resource file.
|
// Check if this is a resource file.
|
||||||
if ((path[0] == ':') && (path[1] == '/')) {
|
if ((path[0] == ':') && (path[1] == '/')) {
|
||||||
std::string test;
|
std::string testHome;
|
||||||
|
std::string testDataPath;
|
||||||
|
|
||||||
// Check under the home directory.
|
// Check under the home directory.
|
||||||
test = Utils::FileSystem::getHomePath() + "/.emulationstation/resources/" + &path[2];
|
testHome = Utils::FileSystem::getHomePath() + "/.emulationstation/resources/" + &path[2];
|
||||||
if (Utils::FileSystem::exists(test))
|
if (Utils::FileSystem::exists(testHome))
|
||||||
return test;
|
return testHome;
|
||||||
|
|
||||||
// Check for the resource under the data installation directory for Unix or under
|
// Check for the resource under the data installation directory for Unix or under
|
||||||
// the executable directory for Windows.
|
// the executable directory for Windows.
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
test = Utils::FileSystem::getExePath() + "/resources/" + &path[2];
|
testDataPath = Utils::FileSystem::getExePath() + "/resources/" + &path[2];
|
||||||
#else
|
#else
|
||||||
test = Utils::FileSystem::getProgramDataPath() + "/resources/" + &path[2];
|
testDataPath = Utils::FileSystem::getProgramDataPath() + "/resources/" + &path[2];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (Utils::FileSystem::exists(test))
|
if (Utils::FileSystem::exists(testDataPath)) {
|
||||||
return test;
|
return testDataPath;
|
||||||
|
}
|
||||||
|
// For missing resources, log an error and terminate the application. This should
|
||||||
|
// indicate that we have a broken EmulationStation installation.
|
||||||
|
else {
|
||||||
|
LOG(LogError) << "Error - Program resource missing: " << path;
|
||||||
|
LOG(LogError) << "Tried to find the resource in the following locations:";
|
||||||
|
LOG(LogError) << testHome;
|
||||||
|
LOG(LogError) << testDataPath;
|
||||||
|
LOG(LogError) << "Has EmulationStation been properly installed?";
|
||||||
|
Scripting::fireEvent("quit");
|
||||||
|
emergencyShutdown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not a resource, return unmodified path.
|
// Not a resource, return unmodified path.
|
||||||
|
|
|
@ -490,20 +490,19 @@ namespace Utils
|
||||||
#if defined(_WIN64)
|
#if defined(_WIN64)
|
||||||
HANDLE hFile = CreateFile(path.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ,
|
HANDLE hFile = CreateFile(path.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ,
|
||||||
0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
/*
|
// TEMPORARY, will need to fix this later.
|
||||||
if (hFile != INVALID_HANDLE_VALUE) {
|
// if (hFile != INVALID_HANDLE_VALUE) {
|
||||||
resolved.resize(GetFinalPathNameByHandle(hFile, nullptr, 0,
|
// resolved.resize(GetFinalPathNameByHandle(hFile, nullptr, 0,
|
||||||
resolved.resize(GetFinalPathNameByHandle(hFile, nullptr, 0,
|
// resolved.resize(GetFinalPathNameByHandle(hFile, nullptr, 0,
|
||||||
FILE_NAME_NORMALIZED) + 1);
|
// FILE_NAME_NORMALIZED) + 1);
|
||||||
if (GetFinalPathNameByHandle(hFile, (LPSTR)resolved.data(),
|
// if (GetFinalPathNameByHandle(hFile, (LPSTR)resolved.data(),
|
||||||
if (GetFinalPathNameByHandle(hFile, (LPSTR)resolved.data(),
|
// if (GetFinalPathNameByHandle(hFile, (LPSTR)resolved.data(),
|
||||||
(DWORD)resolved.size(), FILE_NAME_NORMALIZED) > 0) {
|
// (DWORD)resolved.size(), FILE_NAME_NORMALIZED) > 0) {
|
||||||
resolved.resize(resolved.size() - 1);
|
// resolved.resize(resolved.size() - 1);
|
||||||
resolved = getGenericPath(resolved);
|
// resolved = getGenericPath(resolved);
|
||||||
}
|
// }
|
||||||
CloseHandle(hFile);
|
// CloseHandle(hFile);
|
||||||
}
|
// }
|
||||||
*/
|
|
||||||
#else
|
#else
|
||||||
struct stat info;
|
struct stat info;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue