/* * Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG * Copyright (C) 2020 Rosalie Wanders * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "Directories.hpp" #include "Error.hpp" #include "Core.hpp" #include "Config.hpp" #include "m64p/Api.hpp" #include #include #include #include // // Local Variables // static std::filesystem::path l_CorePathOverride; static std::filesystem::path l_PluginPathOverride; static std::filesystem::path l_SharedDataPathOverride; // // Local Functions // static std::filesystem::path get_var_directory(std::string var, std::string append, std::string fallbackVar, std::string fallbackAppend) { std::filesystem::path directory; const char* env = std::getenv(var.c_str()); if (env == nullptr) { env = std::getenv(fallbackVar.c_str()); if (env == nullptr) { std::cerr << "get_var_directory: fallbackVar: $" << fallbackVar << " cannot be nullptr!" << std::endl; std::terminate(); } directory = env; directory += fallbackAppend; } else { directory = env; directory += append; } return directory; } static std::filesystem::path get_command_output(std::string command) { std::string output; char buf[2048]; FILE* pipe = nullptr; pipe = popen(command.c_str(), "r"); if (pipe == nullptr) { return std::string(); } while (fgets(buf, sizeof(buf), pipe) != nullptr) { output += buf; } pclose(pipe); // strip newline if (output.back() == '\n') { output.pop_back(); } return output; } // // Exported Functions // bool CoreCreateDirectories(void) { std::string error; std::filesystem::path directories[] = { #ifdef PORTABLE_INSTALL CoreGetCoreDirectory(), CoreGetPluginDirectory(), CoreGetSharedDataDirectory(), #endif // PORTABLE_INSTALL CoreGetUserConfigDirectory(), CoreGetUserDataDirectory(), CoreGetUserCacheDirectory(), CoreGetSaveDirectory(), CoreGetSaveStateDirectory(), CoreGetScreenshotDirectory() }; for (const auto& dir : directories) { try { std::filesystem::create_directories(dir); } catch (...) { error = "CoreCreateDirectories Failed: cannot create the '"; error += dir.string(); error += "' directory!"; CoreSetError(error); return false; } } return true; } std::filesystem::path CoreGetCoreDirectory(void) { std::filesystem::path directory; #ifdef PORTABLE_INSTALL directory = "Core"; #else // Not Portable if (!l_CorePathOverride.empty()) { directory = l_CorePathOverride; } else { directory = CORE_INSTALL_PREFIX; directory += "/lib/RMG/Core"; } #endif // PORTABLE_INSTALL return directory; } std::filesystem::path CoreGetPluginDirectory(void) { std::filesystem::path directory; #ifdef PORTABLE_INSTALL directory = "Plugin"; #else // Not Portable if (!l_PluginPathOverride.empty()) { directory = l_PluginPathOverride; } else { directory = CORE_INSTALL_PREFIX; directory += "/lib/RMG/Plugin"; } #endif // PORTABLE_INSTALL return directory; } std::filesystem::path CoreGetUserConfigDirectory(void) { std::filesystem::path directory; #ifdef PORTABLE_INSTALL directory = "Config"; #else // Not Portable directory = get_var_directory("XDG_CONFIG_HOME", "/RMG", "HOME", "/.config/RMG"); #endif // PORTABLE_INSTALL return directory; } std::filesystem::path CoreGetDefaultUserDataDirectory(void) { std::filesystem::path directory; #ifdef PORTABLE_INSTALL directory = "Data"; #else // Not Portable directory = get_var_directory("XDG_DATA_HOME", "/RMG", "HOME", "/.local/share/RMG"); #endif // PORTABLE_INSTALL return directory; } std::filesystem::path CoreGetDefaultUserCacheDirectory(void) { std::filesystem::path directory; #ifdef PORTABLE_INSTALL directory = "Cache"; #else // Not Portable directory = get_var_directory("XDG_CACHE_HOME", "/RMG", "HOME", "/.cache/RMG"); #endif // PORTABLE_INSTALL return directory; } std::filesystem::path CoreGetDefaultSaveDirectory(void) { std::filesystem::path directory; #ifdef PORTABLE_INSTALL directory = "Save/Game"; #else // Not Portable directory = CoreGetDefaultUserDataDirectory(); directory += "/Save/Game"; #endif // PORTABLE_INSTALL return directory; } std::filesystem::path CoreGetDefaultSaveStateDirectory(void) { std::filesystem::path directory; #ifdef PORTABLE_INSTALL directory = "Save/State"; #else // Not Portable directory = CoreGetDefaultUserDataDirectory(); directory += "/Save/State"; #endif // PORTABLE_INSTALL return directory; } std::filesystem::path CoreGetDefaultScreenshotDirectory(void) { std::filesystem::path directory; #ifdef PORTABLE_INSTALL directory = "Screenshots"; #else // Not Portable directory = get_command_output("xdg-user-dir PICTURES"); if (!directory.empty()) { directory += "/RMG"; } else { directory = get_var_directory("XDG_PICTURES_DIR", "/RMG", "HOME", "/Pictures/RMG"); } #endif // PORTABLE_INSTALL return directory; } std::filesystem::path CoreGetUserDataDirectory(void) { return std::filesystem::path(m64p::Config.GetUserDataPath()); } std::filesystem::path CoreGetUserCacheDirectory(void) { return std::filesystem::path(m64p::Config.GetUserCachePath()); } std::filesystem::path CoreGetSharedDataDirectory(void) { std::filesystem::path directory; #ifdef PORTABLE_INSTALL directory = "Data"; #else // Not Portable if (!l_SharedDataPathOverride.empty()) { directory = l_SharedDataPathOverride; } else { directory = CORE_INSTALL_PREFIX; directory += "/share/RMG"; } #endif // PORTABLE_INSTALL return directory; } std::filesystem::path CoreGetSaveDirectory(void) { return CoreSettingsGetStringValue(SettingsID::Core_SaveSRAMPath); } std::filesystem::path CoreGetSaveStateDirectory(void) { return CoreSettingsGetStringValue(SettingsID::Core_SaveStatePath); } std::filesystem::path CoreGetScreenshotDirectory(void) { return CoreSettingsGetStringValue(SettingsID::Core_ScreenshotPath); } #ifndef PORTABLE_INSTALL void CoreSetCorePathOverride(std::filesystem::path path) { l_CorePathOverride = path; } void CoreSetPluginPathOverride(std::filesystem::path path) { l_PluginPathOverride = path; } void CoreSetSharedDataPathOverride(std::filesystem::path path) { l_SharedDataPathOverride = path; } #endif // PORTABLE_INSTALL