mirror of
https://github.com/FunKey-Project/RetroFE.git
synced 2026-03-20 02:42:41 +01:00
Port from git
This commit is contained in:
326
Source/Execute/Launcher.cpp
Normal file
326
Source/Execute/Launcher.cpp
Normal file
@@ -0,0 +1,326 @@
|
||||
/* This file is subject to the terms and conditions defined in
|
||||
* file 'LICENSE.txt', which is part of this source code package.
|
||||
*/
|
||||
#include "Launcher.h"
|
||||
#include "../Collection/Item.h"
|
||||
#include "../Utility/Log.h"
|
||||
#include "../Database/Configuration.h"
|
||||
#include "../Utility/Utils.h"
|
||||
#include "../RetroFE.h"
|
||||
#include "../SDL.h"
|
||||
#include <cstdlib>
|
||||
#include <locale>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <cstring>
|
||||
#endif
|
||||
|
||||
Launcher::Launcher(RetroFE *p)
|
||||
: Config(p->GetConfiguration())
|
||||
, RetroFEInst(p)
|
||||
{
|
||||
}
|
||||
|
||||
bool Launcher::Run(std::string collection, Item *collectionItem)
|
||||
{
|
||||
std::string launcherName = collectionItem->GetLauncher();
|
||||
std::string executablePath;
|
||||
std::string selectedItemsDirectory;
|
||||
std::string selectedItemsPath;
|
||||
std::string currentDirectory;
|
||||
std::string extensions;
|
||||
std::string matchedExtension;
|
||||
std::string args;
|
||||
|
||||
if(!GetLauncherExecutable(executablePath, currentDirectory, launcherName))
|
||||
{
|
||||
Logger::Write(Logger::ZONE_ERROR, "Launcher", "Failed to find launcher executable (launcher: " + launcherName + " executable: " + executablePath + ")");
|
||||
return false;
|
||||
}
|
||||
if(!GetExtensions(extensions, collection))
|
||||
{
|
||||
Logger::Write(Logger::ZONE_ERROR, "Launcher", "No file extensions configured for collection \"" + collection + "\"");
|
||||
return false;
|
||||
}
|
||||
if(!GetCollectionDirectory(selectedItemsDirectory, collection))
|
||||
{
|
||||
Logger::Write(Logger::ZONE_ERROR, "Launcher", "Could not find files in directory \"" + selectedItemsDirectory + "\" for collection \"" + collection + "\"");
|
||||
return false;
|
||||
}
|
||||
if(!GetLauncherArgs(args, launcherName))
|
||||
{
|
||||
Logger::Write(Logger::ZONE_ERROR, "Launcher", "No launcher arguments specified for launcher " + launcherName);
|
||||
return false;
|
||||
}
|
||||
if(!FindFile(selectedItemsPath, matchedExtension, selectedItemsDirectory, collectionItem->GetName(), extensions))
|
||||
{
|
||||
// FindFile() prints out diagnostic messages for us, no need to print anything here
|
||||
return false;
|
||||
}
|
||||
args = ReplaceVariables(args,
|
||||
selectedItemsPath,
|
||||
collectionItem->GetName(),
|
||||
collectionItem->GetFileName(),
|
||||
selectedItemsDirectory,
|
||||
collection);
|
||||
|
||||
executablePath = ReplaceVariables(executablePath,
|
||||
selectedItemsPath,
|
||||
collectionItem->GetName(),
|
||||
collectionItem->GetFileName(),
|
||||
selectedItemsDirectory,
|
||||
collection);
|
||||
|
||||
currentDirectory = ReplaceVariables(currentDirectory,
|
||||
selectedItemsPath,
|
||||
collectionItem->GetName(),
|
||||
collectionItem->GetFileName(),
|
||||
selectedItemsDirectory,
|
||||
collection);
|
||||
|
||||
if(!ExecuteCommand(executablePath, args, currentDirectory))
|
||||
{
|
||||
Logger::Write(Logger::ZONE_ERROR, "Launcher", "Failed to launch.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Launcher::ReplaceVariables(std::string str,
|
||||
std::string itemFilePath,
|
||||
std::string itemName,
|
||||
std::string itemFilename,
|
||||
std::string itemDirectory,
|
||||
std::string itemCollectionName)
|
||||
{
|
||||
str = Utils::Replace(str, "%ITEM_FILEPATH%", itemFilePath);
|
||||
str = Utils::Replace(str, "%ITEM_NAME%", itemName);
|
||||
str = Utils::Replace(str, "%ITEM_FILENAME%", itemFilename);
|
||||
str = Utils::Replace(str, "%ITEM_DIRECTORY%", itemDirectory);
|
||||
str = Utils::Replace(str, "%ITEM_COLLECTION_NAME%", itemCollectionName);
|
||||
str = Utils::Replace(str, "%RETROFE_PATH%", Configuration::GetAbsolutePath());
|
||||
#ifdef WIN32
|
||||
str = Utils::Replace(str, "%RETROFE_EXEC_PATH%", Configuration::GetAbsolutePath() + "/RetroFE.exe");
|
||||
#else
|
||||
str = Utils::Replace(str, "%RETROFE_EXEC_PATH%", Configuration::GetAbsolutePath() + "/RetroFE");
|
||||
#endif
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
bool Launcher::ExecuteCommand(std::string executable, std::string args, std::string currentDirectory)
|
||||
{
|
||||
bool retVal = false;
|
||||
std::string executionString = "\"" + executable + "\" " + args;
|
||||
|
||||
Logger::Write(Logger::ZONE_INFO, "Launcher", "Attempting to launch: " + executionString);
|
||||
Logger::Write(Logger::ZONE_INFO, "Launcher", " from within folder: " + currentDirectory);
|
||||
|
||||
//todo: use delegation instead of depending on knowing the RetroFE class (tie to an interface)
|
||||
RetroFEInst->LaunchEnter();
|
||||
|
||||
#ifdef WIN32
|
||||
STARTUPINFO startupInfo;
|
||||
PROCESS_INFORMATION processInfo;
|
||||
char applicationName[256];
|
||||
char currDir[256];
|
||||
memset(&applicationName, 0, sizeof(applicationName));
|
||||
memset(&startupInfo, 0, sizeof(startupInfo));
|
||||
memset(&processInfo, 0, sizeof(processInfo));
|
||||
strncpy(applicationName, executionString.c_str(), sizeof(applicationName));
|
||||
strncpy(currDir, currentDirectory.c_str(), sizeof(currDir));
|
||||
startupInfo.dwFlags = STARTF_USESTDHANDLES;
|
||||
startupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
||||
startupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
startupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||
startupInfo.wShowWindow = SW_SHOWDEFAULT;
|
||||
|
||||
if(!CreateProcess(NULL, applicationName, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &startupInfo, &processInfo))
|
||||
#else
|
||||
if(system(executionString.c_str()) != 0)
|
||||
#endif
|
||||
{
|
||||
Logger::Write(Logger::ZONE_ERROR, "Launcher", "Failed to run: " + executable);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
#ifdef WIN32
|
||||
while(WAIT_OBJECT_0 != MsgWaitForMultipleObjects(1, &processInfo.hProcess, FALSE, INFINITE, QS_ALLINPUT))
|
||||
{
|
||||
MSG msg;
|
||||
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
||||
{
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
// result = GetExitCodeProcess(processInfo.hProcess, &exitCode);
|
||||
CloseHandle(processInfo.hProcess);
|
||||
#endif
|
||||
retVal = true;
|
||||
}
|
||||
|
||||
Logger::Write(Logger::ZONE_INFO, "Launcher", "Completed");
|
||||
RetroFEInst->LaunchExit();
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool Launcher::GetLauncherName(std::string &launcherName, std::string collection)
|
||||
{
|
||||
std::string launcherKey = "collections." + collection + ".launcher";
|
||||
|
||||
// find the launcher for the particular item
|
||||
if(!Config->GetProperty(launcherKey, launcherName))
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "Launch failed. Could not find a configured launcher for collection \""
|
||||
<< collection
|
||||
<< "\" (could not find a property for \""
|
||||
<< launcherKey
|
||||
<< "\")";
|
||||
|
||||
Logger::Write(Logger::ZONE_ERROR, "Launcher", ss.str());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "collections."
|
||||
<< collection
|
||||
<< " is configured to use launchers."
|
||||
<< launcherName
|
||||
<< "\"";
|
||||
|
||||
Logger::Write(Logger::ZONE_DEBUG, "Launcher", ss.str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Launcher::GetLauncherExecutable(std::string &executable, std::string ¤tDirectory, std::string launcherName)
|
||||
{
|
||||
std::string executableKey = "launchers." + launcherName + ".executable";
|
||||
|
||||
if(!Config->GetProperty(executableKey, executable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string currentDirectoryKey = "launchers." + launcherName + ".currentDirectory";
|
||||
currentDirectory = Utils::GetDirectory(executable);
|
||||
|
||||
Config->GetProperty(currentDirectoryKey, currentDirectory);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Launcher::GetLauncherArgs(std::string &args, std::string launcherName)
|
||||
{
|
||||
std::string argsKey = "launchers." + launcherName + ".arguments";
|
||||
|
||||
if(!Config->GetProperty(argsKey, args))
|
||||
{
|
||||
Logger::Write(Logger::ZONE_ERROR, "Launcher", "No arguments specified for: " + argsKey);
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Launcher::GetExtensions(std::string &extensions, std::string collection)
|
||||
{
|
||||
std::string extensionsKey = "collections." + collection + ".list.extensions";
|
||||
|
||||
if(!Config->GetProperty(extensionsKey, extensions))
|
||||
{
|
||||
Logger::Write(Logger::ZONE_ERROR, "Launcher", "No extensions specified for: " + extensionsKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
extensions = Utils::Replace(extensions, " ", "");
|
||||
extensions = Utils::Replace(extensions, ".", "");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Launcher::GetCollectionDirectory(std::string &directory, std::string collection)
|
||||
{
|
||||
std::string itemsPathKey = "collections." + collection + ".list.path";
|
||||
std::string itemsPathValue;
|
||||
|
||||
// find the items path folder (i.e. ROM path)
|
||||
if(!Config->GetPropertyAbsolutePath(itemsPathKey, itemsPathValue))
|
||||
{
|
||||
directory = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
directory += itemsPathValue + "/";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Launcher::FindFile(std::string &foundFilePath, std::string &foundFilename, std::string directory, std::string filenameWithoutExtension, std::string extensions)
|
||||
{
|
||||
std::string extension;
|
||||
bool fileFound = false;
|
||||
std::stringstream ss;
|
||||
ss << extensions;
|
||||
|
||||
while(!fileFound && std::getline(ss, extension, ',') )
|
||||
{
|
||||
std::string selectedItemsPath = directory + filenameWithoutExtension + "." + extension;
|
||||
std::ifstream f(selectedItemsPath.c_str());
|
||||
|
||||
if (f.good())
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
ss <<"Checking to see if \""
|
||||
<< selectedItemsPath << "\" exists [Yes]";
|
||||
|
||||
fileFound = true;
|
||||
|
||||
Logger::Write(Logger::ZONE_INFO, "Launcher", ss.str());
|
||||
|
||||
foundFilePath = selectedItemsPath;
|
||||
foundFilename = extension;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "Checking to see if \""
|
||||
<< selectedItemsPath << "\" exists [No]";
|
||||
|
||||
Logger::Write(Logger::ZONE_WARNING, "Launcher", ss.str());
|
||||
}
|
||||
|
||||
f.close();
|
||||
}
|
||||
|
||||
// get the launchers executable
|
||||
|
||||
if(!fileFound)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss <<"Could not find any files with the name \""
|
||||
<< filenameWithoutExtension << "\" in folder \""
|
||||
<< directory;
|
||||
|
||||
Logger::Write(Logger::ZONE_ERROR, "Launcher", ss.str());
|
||||
|
||||
}
|
||||
|
||||
return fileFound;
|
||||
}
|
||||
|
||||
|
||||
40
Source/Execute/Launcher.h
Normal file
40
Source/Execute/Launcher.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* This file is subject to the terms and conditions defined in
|
||||
* file 'LICENSE.txt', which is part of this source code package.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class Configuration;
|
||||
class Item;
|
||||
class RetroFE;
|
||||
|
||||
class Launcher
|
||||
{
|
||||
public:
|
||||
Launcher(RetroFE *p);
|
||||
bool Run(std::string collection, Item *collectionItem);
|
||||
|
||||
private:
|
||||
std::string ReplaceString(
|
||||
std::string subject,
|
||||
const std::string &search,
|
||||
const std::string &replace);
|
||||
|
||||
bool GetLauncherName(std::string &launcherName, std::string collection);
|
||||
bool GetLauncherExecutable(std::string &executable, std::string ¤tDirectory, std::string launcherName);
|
||||
bool GetLauncherArgs(std::string &args, std::string launcherName);
|
||||
bool GetExtensions(std::string &extensions, std::string launcherName);
|
||||
bool GetCollectionDirectory(std::string &directory, std::string collection);
|
||||
bool ExecuteCommand(std::string executable, std::string arguments, std::string currentDirectory);
|
||||
bool FindFile(std::string &foundFilePath, std::string &foundFilename, std::string directory, std::string filenameWithoutExtension, std::string extensions);
|
||||
std::string ReplaceVariables(std::string str,
|
||||
std::string itemFilePath,
|
||||
std::string itemName,
|
||||
std::string itemFilename,
|
||||
std::string itemDirectory,
|
||||
std::string itemCollectionName);
|
||||
|
||||
Configuration *Config;
|
||||
RetroFE *RetroFEInst;
|
||||
};
|
||||
Reference in New Issue
Block a user