/****************************************************************************** Copyright (C) 2026 by FiniteSingularity This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ******************************************************************************/ #include "PluginModuleLoader.hpp" #include "PluginManager.hpp" #include #include #include #include #include #include #include #include // Flatpak Third-Party Plugin Locations // // * Flatpak Extension Point Path: /app/plugins // * Binary: /app/plugins//obs-modules/plugins/.so // * Data: /app/plugins//obs/obs-modules/plugins/ // // * Legacy Flatpak Root Path: /app/plugins // * Binary: //obs-plugins/.so // * Data: /share/obs/obs-plugins/ // // * XDG Data Home Path: // * Binary: /obs-studio/plugins//.so // * Data: /obs-studio/plugins//data // // * XDG Config Home Path: // * Binary: /obs-studio/plugins//bin/64bit/.so // * Data: /obs-studio/plugins//data using State = OBS::PluginManager::State; using ModuleType = obs_runtime_module_type; namespace Constants = OBS::Constants; constexpr std::string_view kConfigBinaryPath{"/obs-studio/plugins/%module%/"}; constexpr std::string_view kConfigDataPath{"/obs-studio/plugins/%module%/data/"}; constexpr std::string_view kLegacyConfigBinaryPath{"/obs-studio/plugins/%module%/bin/64bit"}; constexpr std::string_view kLegacyConfigDataPath{"/obs-studio/plugins/%module%/data"}; constexpr std::string_view kFlatpakBasePath{"/app/plugins/"}; namespace { State pluginLoadHelper(const ModuleLoadInfo &info, ModuleList &failedModules) { int failedModuleCount = loadPluginsByInfo(info, failedModules); State result = (failedModuleCount > 0) ? State::PartialFailure : State::Success; return result; } } // namespace namespace OBS { State PluginManager::loadPlugins(bool /*usePortableMode*/) { State flatpakPluginState = State::Failure; { std::string binaryPath{kFlatpakBasePath}; std::string dataPath{kFlatpakBasePath}; binaryPath.append(Constants::kPlatformLibraryPath); binaryPath.append("obs-modules/plugins/"); dataPath.append(Constants::kPlatformDataPath); dataPath.append("obs/obs-modules/plugins/%module%"); ModuleLoadInfo info = {.path_info = {.binary = binaryPath.c_str(), .data = dataPath.c_str()}, .type = OBS_MODULE_TYPE_PLUGIN, .name = nullptr}; flatpakPluginState = pluginLoadHelper(info, failedModules_); } State xdgDataHomeState = State::Failure; std::string xdgDataHomePath = getEnvironmentVariable(Constants::kXDGDataHomeVariable); if (!xdgDataHomePath.empty()) { std::string binaryPath{xdgDataHomePath}; std::string dataPath{xdgDataHomePath}; binaryPath.append(kConfigBinaryPath); dataPath.append(kConfigDataPath); ModuleLoadInfo info = {.path_info = {.binary = binaryPath.c_str(), .data = dataPath.c_str()}, .type = OBS_MODULE_TYPE_PLUGIN, .name = nullptr}; xdgDataHomeState = pluginLoadHelper(info, failedModules_); } else { xdgDataHomeState = State::Success; } return (flatpakPluginState && xdgDataHomeState) ? State::Success : State::PartialFailure; } State PluginManager::loadLegacyPlugins(bool /*usePortableMode*/) { State flatpakPluginState = State::Failure; { std::string binaryPath{kFlatpakBasePath}; std::string dataPath{kFlatpakBasePath}; binaryPath.append(Constants::kPlatformLibraryPath); binaryPath.append("obs-plugins/"); dataPath.append(Constants::kPlatformDataPath); dataPath.append("obs/obs-plugins/%module%"); ModuleLoadInfo info = {.path_info = {.binary = binaryPath.c_str(), .data = dataPath.c_str()}, .type = OBS_MODULE_TYPE_LEGACY_PLUGIN, .name = nullptr}; flatpakPluginState = pluginLoadHelper(info, failedModules_); } State xdgDataConfigState = State::Failure; std::string xdgConfigHomePath = getEnvironmentVariable(Constants::kXDGConfigHomeVariable); if (!xdgConfigHomePath.empty()) { std::string binaryPath{xdgConfigHomePath}; std::string dataPath{xdgConfigHomePath}; binaryPath.append(kLegacyConfigBinaryPath); dataPath.append(kLegacyConfigDataPath); ModuleLoadInfo info = {.path_info = {.binary = binaryPath.c_str(), .data = dataPath.c_str()}, .type = OBS_MODULE_TYPE_LEGACY_PLUGIN, .name = nullptr}; xdgDataConfigState = pluginLoadHelper(info, failedModules_); } return (flatpakPluginState && xdgDataConfigState) ? State::Success : State::PartialFailure; } } // namespace OBS