From 2d149c5161f7c48afc79801e526b7324c57b4a4a Mon Sep 17 00:00:00 2001 From: Leon Styhre Date: Mon, 10 Jan 2022 18:43:17 +0100 Subject: [PATCH] Moved all Platform functions to the utility namespace. --- es-app/src/FileData.cpp | 6 +- es-app/src/guis/GuiMenu.cpp | 8 +- es-app/src/main.cpp | 8 +- es-core/src/InputManager.cpp | 2 +- es-core/src/Platform.cpp | 438 +++++++++++----------- es-core/src/Platform.h | 53 ++- es-core/src/Scripting.cpp | 2 +- es-core/src/resources/ResourceManager.cpp | 2 +- 8 files changed, 263 insertions(+), 256 deletions(-) diff --git a/es-app/src/FileData.cpp b/es-app/src/FileData.cpp index 2619273e1..93021117e 100644 --- a/es-app/src/FileData.cpp +++ b/es-app/src/FileData.cpp @@ -1107,10 +1107,10 @@ void FileData::launchGame(Window* window) // Possibly keep ES-DE running in the background while the game is launched. #if defined(_WIN64) - returnValue = - launchGameWindows(Utils::String::stringToWideString(command), runInBackground, hideWindow); + returnValue = Utils::Platform::launchGameWindows(Utils::String::stringToWideString(command), + runInBackground, hideWindow); #else - returnValue = launchGameUnix(command, runInBackground); + returnValue = Utils::Platform::launchGameUnix(command, runInBackground); #endif // Notify the user in case of a failed game launch using a popup window. if (returnValue != 0) { diff --git a/es-app/src/guis/GuiMenu.cpp b/es-app/src/guis/GuiMenu.cpp index 117d6b3fb..4442910d9 100644 --- a/es-app/src/guis/GuiMenu.cpp +++ b/es-app/src/guis/GuiMenu.cpp @@ -1135,7 +1135,7 @@ void GuiMenu::openQuitMenu() [this] { Scripting::fireEvent("quit"); close(true); - quitES(); + Utils::Platform::quitES(); }, "NO", nullptr)); } @@ -1153,7 +1153,7 @@ void GuiMenu::openQuitMenu() [this] { Scripting::fireEvent("quit"); close(true); - quitES(); + Utils::Platform::quitES(); }, "NO", nullptr)); }); @@ -1170,7 +1170,7 @@ void GuiMenu::openQuitMenu() [] { Scripting::fireEvent("quit", "reboot"); Scripting::fireEvent("reboot"); - if (quitES(QuitMode::REBOOT) != 0) { + if (Utils::Platform::quitES(Utils::Platform::QuitMode::REBOOT) != 0) { LOG(LogWarning) << "Reboot terminated with non-zero result!"; } }, @@ -1189,7 +1189,7 @@ void GuiMenu::openQuitMenu() [] { Scripting::fireEvent("quit", "poweroff"); Scripting::fireEvent("poweroff"); - if (quitES(QuitMode::POWEROFF) != 0) { + if (Utils::Platform::quitES(Utils::Platform::QuitMode::POWEROFF) != 0) { LOG(LogWarning) << "Power off terminated with non-zero result!"; } }, diff --git a/es-app/src/main.cpp b/es-app/src/main.cpp index e6d19a34a..647ea2b8e 100644 --- a/es-app/src/main.cpp +++ b/es-app/src/main.cpp @@ -563,8 +563,8 @@ int main(int argc, char* argv[]) if (Settings::getInstance()->getBool("HideTaskbar")) { taskbarStateChanged = true; - taskbarState = getTaskbarState(); - hideTaskbar(); + taskbarState = Utils::Platform::getTaskbarState(); + Utils::Platform::hideTaskbar(); } #endif @@ -692,10 +692,10 @@ int main(int argc, char* argv[]) #if defined(_WIN64) // If the taskbar state was changed (taskbar was hidden), then revert it. if (taskbarStateChanged) - revertTaskbarState(taskbarState); + Utils::Platform::revertTaskbarState(taskbarState); #endif - processQuitMode(); + Utils::Platform::processQuitMode(); LOG(LogInfo) << "EmulationStation cleanly shutting down"; diff --git a/es-core/src/InputManager.cpp b/es-core/src/InputManager.cpp index c77162479..bc985b4dc 100644 --- a/es-core/src/InputManager.cpp +++ b/es-core/src/InputManager.cpp @@ -239,7 +239,7 @@ void InputManager::doOnFinish() LOG(LogInfo) << " " << tocall; std::cout << "==============================================\n" "input config finish command:\n"; - int exitCode = runSystemCommand(tocall); + int exitCode = Utils::Platform::runSystemCommand(tocall); std::cout << "==============================================\n"; if (exitCode != 0) { diff --git a/es-core/src/Platform.cpp b/es-core/src/Platform.cpp index 812427f72..5fb96350d 100644 --- a/es-core/src/Platform.cpp +++ b/es-core/src/Platform.cpp @@ -3,7 +3,7 @@ // EmulationStation Desktop Edition // Platform.cpp // -// Platform-specific functions. +// Platform utility functions. // #include "Platform.h" @@ -25,133 +25,139 @@ #endif #include -int runRebootCommand() +namespace Utils { + namespace Platform + { + int runRebootCommand() + { #if defined(_WIN64) - return system("shutdown -r -t 0"); + return system("shutdown -r -t 0"); #elif defined(__APPLE__) - // This will probably never be used as macOS requires root privileges to reboot. - return system("shutdown -r now"); + // This will probably never be used as macOS requires root privileges to reboot. + return system("shutdown -r now"); #else - return system("shutdown --reboot now"); + return system("shutdown --reboot now"); #endif -} + } -int runPoweroffCommand() -{ + int runPoweroffCommand() + { #if defined(_WIN64) - return system("shutdown -s -t 0"); + return system("shutdown -s -t 0"); #elif defined(__APPLE__) - // This will probably never be used as macOS requires root privileges to power off. - return system("shutdown now"); + // This will probably never be used as macOS requires root privileges to power off. + return system("shutdown now"); #else - return system("shutdown --poweroff now"); + return system("shutdown --poweroff now"); #endif -} + } -int runSystemCommand(const std::string& cmd_utf8) -{ + int runSystemCommand(const std::string& cmd_utf8) + { #if defined(_WIN64) - // On Windows we use _wsystem to support non-ASCII paths - // which requires converting from UTF-8 to a wstring. - std::wstring wchar_str = Utils::String::stringToWideString(cmd_utf8); - return _wsystem(wchar_str.c_str()); + // On Windows we use _wsystem to support non-ASCII paths + // which requires converting from UTF-8 to a wstring. + std::wstring wchar_str = Utils::String::stringToWideString(cmd_utf8); + return _wsystem(wchar_str.c_str()); #else - return system(cmd_utf8.c_str()); + return system(cmd_utf8.c_str()); #endif -} + } -int runSystemCommand(const std::wstring& cmd_utf16) -{ + int runSystemCommand(const std::wstring& cmd_utf16) + { #if defined(_WIN64) - return _wsystem(cmd_utf16.c_str()); + return _wsystem(cmd_utf16.c_str()); #else - return 0; + return 0; #endif -} + } -int launchGameUnix(const std::string& cmd_utf8, bool runInBackground) -{ + int launchGameUnix(const std::string& cmd_utf8, bool runInBackground) + { #if defined(__unix__) || defined(__APPLE__) - std::string command = std::string(cmd_utf8) + " 2>&1 &"; + std::string command = std::string(cmd_utf8) + " 2>&1 &"; - // Launching games while keeping ES-DE running in the background is very crude as for - // instance no output from the command is captured and no real error handling is - // implemented. It should therefore only be used when absolutely necessary. - if (runInBackground) { - LOG(LogDebug) << "Platform::launchGameUnix(): Launching game while keeping ES-DE running " - "in the background, no command output will be written to the log file"; - return system(command.c_str()); - } + // Launching games while keeping ES-DE running in the background is very crude as for + // instance no output from the command is captured and no real error handling is + // implemented. It should therefore only be used when absolutely necessary. + if (runInBackground) { + LOG(LogDebug) + << "Platform::launchGameUnix(): Launching game while keeping ES-DE running " + "in the background, no command output will be written to the log file"; + return system(command.c_str()); + } - FILE* commandPipe; - std::array buffer; - std::string commandOutput; - int returnValue; + FILE* commandPipe; + std::array buffer; + std::string commandOutput; + int returnValue; - if (!(commandPipe = reinterpret_cast(popen(command.c_str(), "r")))) { - LOG(LogError) << "Couldn't open pipe to command."; - return -1; - } + if (!(commandPipe = reinterpret_cast(popen(command.c_str(), "r")))) { + LOG(LogError) << "Couldn't open pipe to command."; + return -1; + } - while (fgets(buffer.data(), buffer.size(), commandPipe) != nullptr) { - commandOutput += buffer.data(); - } + while (fgets(buffer.data(), buffer.size(), commandPipe) != nullptr) { + commandOutput += buffer.data(); + } - returnValue = pclose(commandPipe); + returnValue = pclose(commandPipe); #if defined(_RPI_) - // Hack to avoid that the application window occasionally loses focus when returning from - // a game, which only seems to happen on Raspberry Pi OS 10. - SDL_Delay(50); - SDL_SetWindowInputFocus(Renderer::getSDLWindow()); + // Hack to avoid that the application window occasionally loses focus when returning + // from a game, which only seems to happen on Raspberry Pi OS 10. + SDL_Delay(50); + SDL_SetWindowInputFocus(Renderer::getSDLWindow()); #endif - // We need to shift the return value as it contains some flags (which we don't need). - returnValue >>= 8; + // We need to shift the return value as it contains some flags (which we don't need). + returnValue >>= 8; - // Remove any trailing newline from the command output. - if (commandOutput.size()) { - if (commandOutput.back() == '\n') - commandOutput.pop_back(); - } + // Remove any trailing newline from the command output. + if (commandOutput.size()) { + if (commandOutput.back() == '\n') + commandOutput.pop_back(); + } - if (returnValue) { - LOG(LogError) << "launchGameUnix - return value " << std::to_string(returnValue) + ":"; - if (commandOutput.size()) - LOG(LogError) << commandOutput; - else - LOG(LogError) << "No error output provided by game or emulator"; - } - else if (commandOutput.size()) { - LOG(LogDebug) << "Platform::launchGameUnix():"; - LOG(LogDebug) << "Output from launched game:\n" << commandOutput; - } + if (returnValue) { + LOG(LogError) << "launchGameUnix - return value " + << std::to_string(returnValue) + ":"; + if (commandOutput.size()) + LOG(LogError) << commandOutput; + else + LOG(LogError) << "No error output provided by game or emulator"; + } + else if (commandOutput.size()) { + LOG(LogDebug) << "Platform::launchGameUnix():"; + LOG(LogDebug) << "Output from launched game:\n" << commandOutput; + } - return returnValue; + return returnValue; #else // __unix__ - return 0; + return 0; #endif -} + } -int launchGameWindows(const std::wstring& cmd_utf16, bool runInBackground, bool hideWindow) -{ + int launchGameWindows(const std::wstring& cmd_utf16, bool runInBackground, bool hideWindow) + { #if defined(_WIN64) - STARTUPINFOW si{}; - PROCESS_INFORMATION pi; + STARTUPINFOW si{}; + PROCESS_INFORMATION pi; - si.cb = sizeof(si); - if (hideWindow) { - // Optionally hide the window. This is intended primarily for hiding console windows when - // launching scripts (used for example by Steam games and source ports). - si.dwFlags = STARTF_USESHOWWINDOW; - si.wShowWindow = SW_HIDE; - } - bool processReturnValue = true; - DWORD errorCode = 0; + si.cb = sizeof(si); + if (hideWindow) { + // Optionally hide the window. This is intended primarily for hiding console windows + // when launching scripts (used for example by Steam games and source ports). + si.dwFlags = STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; + } + bool processReturnValue = true; + DWORD errorCode = 0; - // clang-format off + // clang-format off processReturnValue = CreateProcessW( nullptr, // No application name (use command line). const_cast(cmd_utf16.c_str()), // Command line. @@ -163,148 +169,136 @@ int launchGameWindows(const std::wstring& cmd_utf16, bool runInBackground, bool nullptr, // Use parent's starting directory. &si, // Pointer to the STARTUPINFOW structure. &pi); // Pointer to the PROCESS_INFORMATION structure. - // clang-format on + // clang-format on - if (!runInBackground) { - int width{}; - int height{}; + if (!runInBackground) { + int width{}; + int height{}; - // Hack to make the emulator window render correctly when launching games while running in - // full screen mode. If not done, the emulator window will simply be black although the - // game actually works and outputs sounds, accepts input etc. There is sometimes a white - // flash the first time an emulator is started during the program session and a white - // single-pixel line will be visible at the bottom of the screen while the game is loading. - // But it's at least a tolerable workaround. - SDL_GetWindowSize(Renderer::getSDLWindow(), &width, &height); - SDL_SetWindowSize(Renderer::getSDLWindow(), width, height - 1); - SDL_Delay(100); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - Renderer::swapBuffers(); + // Hack to make the emulator window render correctly when launching games while + // running in full screen mode. If not done, the emulator window will simply be + // black although the game actually works and outputs sounds, accepts input etc. + // There is sometimes a white flash the first time an emulator is started during the + // program session and a white single-pixel line will be visible at the bottom of + // the screen while the game is loading. But it's at least a tolerable workaround. + SDL_GetWindowSize(Renderer::getSDLWindow(), &width, &height); + SDL_SetWindowSize(Renderer::getSDLWindow(), width, height - 1); + SDL_Delay(100); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + Renderer::swapBuffers(); - WaitForSingleObject(pi.hThread, INFINITE); - WaitForSingleObject(pi.hProcess, INFINITE); + WaitForSingleObject(pi.hThread, INFINITE); + WaitForSingleObject(pi.hProcess, INFINITE); - SDL_SetWindowSize(Renderer::getSDLWindow(), width, height); - } + SDL_SetWindowSize(Renderer::getSDLWindow(), width, height); + } - // If the return value is false, then something failed. - if (!processReturnValue) { - LPWSTR pBuffer = nullptr; + // If the return value is false, then something failed. + if (!processReturnValue) { + LPWSTR pBuffer = nullptr; - FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, nullptr, - GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - reinterpret_cast(&pBuffer), 0, nullptr); + FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, nullptr, + GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + reinterpret_cast(&pBuffer), 0, nullptr); - errorCode = GetLastError(); + errorCode = GetLastError(); - std::string errorMessage = Utils::String::wideStringToString(pBuffer); - // Remove trailing newline from the error message. - if (errorMessage.size()) { - if (errorMessage.back() == '\n') - errorMessage.pop_back(); - if (errorMessage.size()) { - if (errorMessage.back() == '\r') - errorMessage.pop_back(); + std::string errorMessage = Utils::String::wideStringToString(pBuffer); + // Remove trailing newline from the error message. + if (errorMessage.size()) { + if (errorMessage.back() == '\n') + errorMessage.pop_back(); + if (errorMessage.size()) { + if (errorMessage.back() == '\r') + errorMessage.pop_back(); + } + } + + LOG(LogError) << "launchGameWindows - system error code " << errorCode << ": " + << errorMessage; + } + + // Close process and thread handles. + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + + return errorCode; + +#else // _WIN64 + return 0; +#endif + } + + unsigned int getTaskbarState() + { +#if defined(_WIN64) + APPBARDATA barData; + barData.cbSize = sizeof(APPBARDATA); + return static_cast(SHAppBarMessage(ABM_GETSTATE, &barData)); +#else + return 0; +#endif + } + + void hideTaskbar() + { +#if defined(_WIN64) + APPBARDATA barData; + barData.cbSize = sizeof(APPBARDATA); + barData.lParam = ABS_AUTOHIDE; + SHAppBarMessage(ABM_SETSTATE, &barData); +#endif + } + + void revertTaskbarState(unsigned int& state) + { +#if defined(_WIN64) + APPBARDATA barData; + barData.cbSize = sizeof(APPBARDATA); + barData.lParam = state; + SHAppBarMessage(ABM_SETSTATE, &barData); +#endif + } + + int quitES(QuitMode mode) + { + quitMode = mode; + + SDL_Event quit; + quit.type = SDL_QUIT; + SDL_PushEvent(&quit); + return 0; + } + + void emergencyShutdown() + { + LOG(LogError) << "Critical - Performing emergency shutdown..."; + + Window::getInstance()->deinit(); + Log::flush(); + + exit(EXIT_FAILURE); + } + + void processQuitMode() + { + switch (quitMode) { + case QuitMode::REBOOT: { + LOG(LogInfo) << "Rebooting system"; + runRebootCommand(); + break; + } + case QuitMode::POWEROFF: { + LOG(LogInfo) << "Powering off system"; + runPoweroffCommand(); + break; + } + default: { + break; + } } } - LOG(LogError) << "launchGameWindows - system error code " << errorCode << ": " - << errorMessage; - } + } // namespace Platform - // Close process and thread handles. - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - - return errorCode; - -#else // _WIN64 - return 0; -#endif -} - -unsigned int getTaskbarState() -{ -#if defined(_WIN64) - APPBARDATA barData; - barData.cbSize = sizeof(APPBARDATA); - return static_cast(SHAppBarMessage(ABM_GETSTATE, &barData)); -#else - return 0; -#endif -} - -void hideTaskbar() -{ -#if defined(_WIN64) - APPBARDATA barData; - barData.cbSize = sizeof(APPBARDATA); - barData.lParam = ABS_AUTOHIDE; - SHAppBarMessage(ABM_SETSTATE, &barData); -#endif -} - -void revertTaskbarState(unsigned int& state) -{ -#if defined(_WIN64) - APPBARDATA barData; - barData.cbSize = sizeof(APPBARDATA); - barData.lParam = state; - SHAppBarMessage(ABM_SETSTATE, &barData); -#endif -} - -QuitMode quitMode = QuitMode::QUIT; - -int quitES(QuitMode mode) -{ - quitMode = mode; - - SDL_Event quit; - quit.type = SDL_QUIT; - SDL_PushEvent(&quit); - return 0; -} - -void emergencyShutdown() -{ - LOG(LogError) << "Critical - Performing emergency shutdown..."; - - Window::getInstance()->deinit(); - Log::flush(); - - exit(EXIT_FAILURE); -} - -void touch(const std::string& filename) -{ -#if defined(_WIN64) - FILE* fp; - fopen_s(&fp, filename.c_str(), "ab+"); - if (fp != nullptr) - fclose(fp); -#else - int fd = open(filename.c_str(), O_CREAT | O_WRONLY, 0644); - if (fd >= 0) - close(fd); -#endif -} - -void processQuitMode() -{ - switch (quitMode) { - case QuitMode::REBOOT: { - LOG(LogInfo) << "Rebooting system"; - runRebootCommand(); - break; - } - case QuitMode::POWEROFF: { - LOG(LogInfo) << "Powering off system"; - runPoweroffCommand(); - break; - } - default: { - break; - } - } -} +} // namespace Utils diff --git a/es-core/src/Platform.h b/es-core/src/Platform.h index 3cd8971ea..97b3effd5 100644 --- a/es-core/src/Platform.h +++ b/es-core/src/Platform.h @@ -3,7 +3,7 @@ // EmulationStation Desktop Edition // Platform.h // -// Platform-specific functions. +// Platform utility functions. // #ifndef ES_CORE_PLATFORM_H @@ -17,29 +17,42 @@ #include #endif -enum QuitMode { - QUIT = 0, // Replace with AllowShortEnumsOnASingleLine: false (clang-format >=11.0). - REBOOT = 1, - POWEROFF = 2 -}; +namespace Utils +{ + namespace Platform + { + enum QuitMode { + QUIT = 0, // Replace with AllowShortEnumsOnASingleLine: false (clang-format >=11.0). + REBOOT = 1, + POWEROFF = 2 + }; -// Uses UTF-8 for Unix and does a UTF-16/wstring conversion for Windows. -int runSystemCommand(const std::string& cmd_utf8); -// Windows specific UTF-16/wstring function. (FOR FUTURE USE) -int runSystemCommand(const std::wstring& cmd_utf16); + int runRebootCommand(); + int runPoweroffCommand(); -int launchGameUnix(const std::string& cmd_utf8, bool runInBackground); -int launchGameWindows(const std::wstring& cmd_utf16, bool runInBackground, bool hideWindow); + // Uses UTF-8 for Unix and does a UTF-16/wstring conversion for Windows. + int runSystemCommand(const std::string& cmd_utf8); + // Windows specific UTF-16/wstring function. (FOR FUTURE USE) + int runSystemCommand(const std::wstring& cmd_utf16); -unsigned int getTaskbarState(); -void hideTaskbar(); -void revertTaskbarState(unsigned int& state); + int launchGameUnix(const std::string& cmd_utf8, bool runInBackground); + int launchGameWindows(const std::wstring& cmd_utf16, bool runInBackground, bool hideWindow); -// Clean, normal shutdown. -int quitES(QuitMode mode = QuitMode::QUIT); + unsigned int getTaskbarState(); + void hideTaskbar(); + void revertTaskbarState(unsigned int& state); -// Immediately shut down the application as cleanly as possible. -void emergencyShutdown(); -void processQuitMode(); + // Clean, normal shutdown. + int quitES(QuitMode mode = QuitMode::QUIT); + + // Immediately shut down the application as cleanly as possible. + void emergencyShutdown(); + void processQuitMode(); + + inline static QuitMode quitMode = QuitMode::QUIT; + + } // namespace Platform + +} // namespace Utils #endif // ES_CORE_PLATFORM_H diff --git a/es-core/src/Scripting.cpp b/es-core/src/Scripting.cpp index 82f27e9a2..6bdeaf03d 100644 --- a/es-core/src/Scripting.cpp +++ b/es-core/src/Scripting.cpp @@ -77,7 +77,7 @@ namespace Scripting .append(arg4) .append(arg4Quotation); LOG(LogDebug) << "Executing: " << script; - runSystemCommand(script); + Utils::Platform::runSystemCommand(script); } } } diff --git a/es-core/src/resources/ResourceManager.cpp b/es-core/src/resources/ResourceManager.cpp index 9a10cc18b..4a64c0377 100644 --- a/es-core/src/resources/ResourceManager.cpp +++ b/es-core/src/resources/ResourceManager.cpp @@ -79,7 +79,7 @@ std::string ResourceManager::getResourcePath(const std::string& path, bool termi LOG(LogError) << testExePath; LOG(LogError) << "Has EmulationStation been properly installed?"; Scripting::fireEvent("quit"); - emergencyShutdown(); + Utils::Platform::emergencyShutdown(); } else { return "";