mirror of
https://github.com/Palakis/obs-websocket.git
synced 2024-08-30 18:12:16 +00:00
Config: Migrate config/persistent data to plugin_config directory
This commit moves the Config value storage from `global.ini` to a new `config.json` file in the `plugin_config/obs-websocket` directory. This comes after some internal discussion about plugins not using the `plugin_config` directory, and that obs-websocket was offending. Settings are currently stored as a JSON object, and field names have been changed from using PascalCase to snake_case, to better align with how JSON is stored elsewhere in OBS.
This commit is contained in:
parent
4410e30684
commit
af31f1adca
162
src/Config.cpp
162
src/Config.cpp
@ -17,45 +17,59 @@ You should have received a copy of the GNU General Public License along
|
||||
with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include <obs-frontend-api.h>
|
||||
|
||||
#include "Config.h"
|
||||
#include "utils/Crypto.h"
|
||||
#include "utils/Platform.h"
|
||||
#include "utils/Obs.h"
|
||||
|
||||
#define CONFIG_SECTION_NAME "OBSWebSocket"
|
||||
#define CONFIG_PARAM_FIRSTLOAD "FirstLoad"
|
||||
#define CONFIG_PARAM_ENABLED "ServerEnabled"
|
||||
#define CONFIG_PARAM_PORT "ServerPort"
|
||||
#define CONFIG_PARAM_ALERTS "AlertsEnabled"
|
||||
#define CONFIG_PARAM_AUTHREQUIRED "AuthRequired"
|
||||
#define CONFIG_PARAM_PASSWORD "ServerPassword"
|
||||
|
||||
#define PARAM_FIRSTLOAD "FirstLoad"
|
||||
#define PARAM_ENABLED "ServerEnabled"
|
||||
#define PARAM_PORT "ServerPort"
|
||||
#define PARAM_ALERTS "AlertsEnabled"
|
||||
#define PARAM_AUTHREQUIRED "AuthRequired"
|
||||
#define PARAM_PASSWORD "ServerPassword"
|
||||
#define CONFIG_FILE_NAME "config.json"
|
||||
#define PARAM_FIRSTLOAD "first_load"
|
||||
#define PARAM_ENABLED "server_enabled"
|
||||
#define PARAM_PORT "server_port"
|
||||
#define PARAM_ALERTS "alerts_enabled"
|
||||
#define PARAM_AUTHREQUIRED "auth_required"
|
||||
#define PARAM_PASSWORD "server_password"
|
||||
|
||||
#define CMDLINE_WEBSOCKET_PORT "websocket_port"
|
||||
#define CMDLINE_WEBSOCKET_IPV4_ONLY "websocket_ipv4_only"
|
||||
#define CMDLINE_WEBSOCKET_PASSWORD "websocket_password"
|
||||
#define CMDLINE_WEBSOCKET_DEBUG "websocket_debug"
|
||||
|
||||
Config::Config()
|
||||
void Config::Load(json config)
|
||||
{
|
||||
SetDefaultsToGlobalStore();
|
||||
}
|
||||
|
||||
void Config::Load()
|
||||
{
|
||||
config_t *obsConfig = GetConfigStore();
|
||||
if (!obsConfig) {
|
||||
blog(LOG_ERROR, "[Config::Load] Unable to fetch OBS config!");
|
||||
return;
|
||||
if (config.is_null()) {
|
||||
std::string configFilePath = Utils::Obs::StringHelper::GetModuleConfigPath(CONFIG_FILE_NAME);
|
||||
Utils::Json::GetJsonFileContent(configFilePath, config); // Fetch the existing config, which may not exist
|
||||
}
|
||||
|
||||
FirstLoad = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_FIRSTLOAD);
|
||||
ServerEnabled = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ENABLED);
|
||||
AlertsEnabled = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ALERTS);
|
||||
ServerPort = config_get_uint(obsConfig, CONFIG_SECTION_NAME, PARAM_PORT);
|
||||
AuthRequired = config_get_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_AUTHREQUIRED);
|
||||
ServerPassword = config_get_string(obsConfig, CONFIG_SECTION_NAME, PARAM_PASSWORD);
|
||||
// Should never happen, but just in case
|
||||
if (!config.is_object())
|
||||
return;
|
||||
|
||||
if (config.contains(PARAM_FIRSTLOAD) && config[PARAM_FIRSTLOAD].is_boolean())
|
||||
FirstLoad = config[PARAM_FIRSTLOAD];
|
||||
if (config.contains(PARAM_ENABLED) && config[PARAM_ENABLED].is_boolean())
|
||||
ServerEnabled = config[PARAM_ENABLED];
|
||||
if (config.contains(PARAM_ALERTS) && config[PARAM_ALERTS].is_boolean())
|
||||
AlertsEnabled = config[PARAM_ALERTS];
|
||||
if (config.contains(PARAM_PORT) && config[PARAM_PORT].is_number_unsigned())
|
||||
ServerPort = config[PARAM_PORT];
|
||||
if (config.contains(PARAM_AUTHREQUIRED) && config[PARAM_AUTHREQUIRED].is_boolean())
|
||||
AuthRequired = config[PARAM_AUTHREQUIRED];
|
||||
if (config.contains(PARAM_PASSWORD) && config[PARAM_PASSWORD].is_string())
|
||||
ServerPassword = QString::fromStdString(config[PARAM_PASSWORD].get<std::string>());
|
||||
|
||||
// Set server password and save it to the config before processing overrides,
|
||||
// so that there is always a true configured password regardless of if
|
||||
@ -110,43 +124,93 @@ void Config::Load()
|
||||
|
||||
void Config::Save()
|
||||
{
|
||||
config_t *obsConfig = GetConfigStore();
|
||||
if (!obsConfig) {
|
||||
blog(LOG_ERROR, "[Config::Save] Unable to fetch OBS config!");
|
||||
return;
|
||||
}
|
||||
json config;
|
||||
|
||||
config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_FIRSTLOAD, FirstLoad);
|
||||
config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ENABLED, ServerEnabled);
|
||||
if (!PortOverridden) {
|
||||
config_set_uint(obsConfig, CONFIG_SECTION_NAME, PARAM_PORT, ServerPort);
|
||||
}
|
||||
config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ALERTS, AlertsEnabled);
|
||||
std::string configFilePath = Utils::Obs::StringHelper::GetModuleConfigPath(CONFIG_FILE_NAME);
|
||||
Utils::Json::GetJsonFileContent(configFilePath, config); // Fetch the existing config, which may not exist
|
||||
|
||||
config[PARAM_FIRSTLOAD] = FirstLoad.load();
|
||||
config[PARAM_ENABLED] = ServerEnabled.load();
|
||||
if (!PortOverridden)
|
||||
config[PARAM_PORT] = ServerPort.load();
|
||||
config[PARAM_ALERTS] = AlertsEnabled.load();
|
||||
if (!PasswordOverridden) {
|
||||
config_set_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_AUTHREQUIRED, AuthRequired);
|
||||
config_set_string(obsConfig, CONFIG_SECTION_NAME, PARAM_PASSWORD, QT_TO_UTF8(ServerPassword));
|
||||
config[PARAM_AUTHREQUIRED] = AuthRequired.load();
|
||||
config[PARAM_PASSWORD] = ServerPassword.toStdString();
|
||||
}
|
||||
|
||||
config_save(obsConfig);
|
||||
if (!Utils::Json::SetJsonFileContent(configFilePath, config))
|
||||
blog(LOG_ERROR, "[Config::Save] Failed to write config file!");
|
||||
}
|
||||
|
||||
void Config::SetDefaultsToGlobalStore()
|
||||
// Finds any old values in global.ini and removes them, then returns the values as JSON
|
||||
json MigrateGlobalConfigData()
|
||||
{
|
||||
config_t *obsConfig = GetConfigStore();
|
||||
if (!obsConfig) {
|
||||
blog(LOG_ERROR, "[Config::SetDefaultsToGlobalStore] Unable to fetch OBS config!");
|
||||
return;
|
||||
// Get existing global config
|
||||
config_t *config = obs_frontend_get_global_config();
|
||||
json ret;
|
||||
|
||||
// Move values to temporary JSON blob
|
||||
if (config_has_user_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_FIRSTLOAD)) {
|
||||
ret[PARAM_FIRSTLOAD] = config_get_bool(config, CONFIG_SECTION_NAME, CONFIG_PARAM_FIRSTLOAD);
|
||||
config_remove_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_FIRSTLOAD);
|
||||
}
|
||||
if (config_has_user_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_ENABLED)) {
|
||||
ret[PARAM_ENABLED] = config_get_bool(config, CONFIG_SECTION_NAME, CONFIG_PARAM_ENABLED);
|
||||
config_remove_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_ENABLED);
|
||||
}
|
||||
if (config_has_user_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_PORT)) {
|
||||
ret[PARAM_PORT] = config_get_uint(config, CONFIG_SECTION_NAME, CONFIG_PARAM_PORT);
|
||||
config_remove_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_PORT);
|
||||
}
|
||||
if (config_has_user_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_ALERTS)) {
|
||||
ret[PARAM_ALERTS] = config_get_bool(config, CONFIG_SECTION_NAME, CONFIG_PARAM_ALERTS);
|
||||
config_remove_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_ALERTS);
|
||||
}
|
||||
if (config_has_user_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_AUTHREQUIRED)) {
|
||||
ret[PARAM_AUTHREQUIRED] = config_get_bool(config, CONFIG_SECTION_NAME, CONFIG_PARAM_AUTHREQUIRED);
|
||||
config_remove_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_AUTHREQUIRED);
|
||||
}
|
||||
if (config_has_user_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_PASSWORD)) {
|
||||
ret[PARAM_PASSWORD] = config_get_string(config, CONFIG_SECTION_NAME, CONFIG_PARAM_PASSWORD);
|
||||
config_remove_value(config, CONFIG_SECTION_NAME, CONFIG_PARAM_PASSWORD);
|
||||
}
|
||||
|
||||
config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_FIRSTLOAD, FirstLoad);
|
||||
config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ENABLED, ServerEnabled);
|
||||
config_set_default_uint(obsConfig, CONFIG_SECTION_NAME, PARAM_PORT, ServerPort);
|
||||
config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_ALERTS, AlertsEnabled);
|
||||
config_set_default_bool(obsConfig, CONFIG_SECTION_NAME, PARAM_AUTHREQUIRED, AuthRequired);
|
||||
config_set_default_string(obsConfig, CONFIG_SECTION_NAME, PARAM_PASSWORD, QT_TO_UTF8(ServerPassword));
|
||||
if (!ret.is_null()) {
|
||||
blog(LOG_INFO, "[MigrateGlobalConfigData] Some configurations have been migrated from old config");
|
||||
config_save(config);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
config_t *Config::GetConfigStore()
|
||||
// Migration from storing persistent data in obsWebSocketPersistentData.json to the module config directory
|
||||
// This will overwrite any persistent data in the destination. People doing manual OBS config modification be warned!
|
||||
bool MigratePersistentData()
|
||||
{
|
||||
return obs_frontend_get_global_config();
|
||||
std::error_code ec;
|
||||
|
||||
// Ensure module config directory exists
|
||||
std::string moduleConfigDirectory = Utils::Obs::StringHelper::GetModuleConfigPath("");
|
||||
if (!std::filesystem::exists(moduleConfigDirectory, ec))
|
||||
std::filesystem::create_directories(moduleConfigDirectory, ec);
|
||||
if (ec) {
|
||||
blog(LOG_ERROR, "[MigratePersistentData] Failed to create directory `%s`: %s", moduleConfigDirectory.c_str(), ec.message().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Move any existing persistent data to module config directory, then delete old file
|
||||
std::string oldPersistentDataPath = Utils::Obs::StringHelper::GetCurrentProfilePath() + "/../../../obsWebSocketPersistentData.json";
|
||||
if (std::filesystem::exists(oldPersistentDataPath, ec)) {
|
||||
std::string persistentDataPath = Utils::Obs::StringHelper::GetModuleConfigPath("persistent_data.json");
|
||||
std::filesystem::copy_file(oldPersistentDataPath, persistentDataPath, ec);
|
||||
std::filesystem::remove(oldPersistentDataPath, ec);
|
||||
blog(LOG_INFO, "[MigratePersistentData] Persistent data migrated to new path");
|
||||
}
|
||||
if (ec) {
|
||||
blog(LOG_ERROR, "[MigratePersistentData] Failed to move persistent data: %s", ec.message().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -23,14 +23,12 @@ with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
#include <QString>
|
||||
#include <util/config-file.h>
|
||||
|
||||
#include "utils/Json.h"
|
||||
#include "plugin-macros.generated.h"
|
||||
|
||||
struct Config {
|
||||
Config();
|
||||
void Load();
|
||||
void Load(json config = nullptr);
|
||||
void Save();
|
||||
void SetDefaultsToGlobalStore();
|
||||
static config_t *GetConfigStore();
|
||||
|
||||
std::atomic<bool> PortOverridden = false;
|
||||
std::atomic<bool> PasswordOverridden = false;
|
||||
@ -44,3 +42,6 @@ struct Config {
|
||||
std::atomic<bool> AuthRequired = true;
|
||||
QString ServerPassword;
|
||||
};
|
||||
|
||||
json MigrateGlobalConfigData();
|
||||
bool MigratePersistentData();
|
||||
|
@ -60,9 +60,16 @@ bool obs_module_load(void)
|
||||
// Initialize the cpu stats
|
||||
_cpuUsageInfo = os_cpu_usage_info_start();
|
||||
|
||||
// Handle migrations
|
||||
if (!MigratePersistentData()) {
|
||||
os_cpu_usage_info_destroy(_cpuUsageInfo);
|
||||
return false;
|
||||
}
|
||||
json migratedConfig = MigrateGlobalConfigData();
|
||||
|
||||
// Create the config manager then load the parameters from storage
|
||||
_config = ConfigPtr(new Config());
|
||||
_config->Load();
|
||||
_config->Load(migratedConfig);
|
||||
|
||||
// Initialize the event handler
|
||||
_eventHandler = EventHandlerPtr(new EventHandler());
|
||||
|
Loading…
Reference in New Issue
Block a user