diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c739c74..fd98a84f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -429,6 +429,8 @@ list(APPEND PROJECT_TEMPLATES ) list(APPEND PROJECT_PRIVATE_SOURCE # Plugin + "source/configuration.hpp" + "source/configuration.cpp" "source/common.hpp" "source/strings.hpp" "source/plugin.hpp" diff --git a/source/configuration.cpp b/source/configuration.cpp new file mode 100644 index 00000000..71818b2d --- /dev/null +++ b/source/configuration.cpp @@ -0,0 +1,102 @@ +/* + * Modern effects for a modern Streamer + * Copyright (C) 2020 Michael Fabian Dirks + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "configuration.hpp" +#include "obs/obs-tools.hpp" +#include "plugin.hpp" + +constexpr std::string_view version_tag_name = "Version"; +constexpr std::string_view path_backup_ext = ".bk"; + +streamfx::configuration::~configuration() +{ + // Update version tag. + obs_data_set_int(_data.get(), version_tag_name.data(), STREAMFX_VERSION); + + try { + if (_config_path.has_parent_path()) { + std::filesystem::create_directories(_config_path.parent_path()); + } + if (!obs_data_save_json_safe(_data.get(), _config_path.string().c_str(), ".tmp", + _config_backup_path.string().c_str())) { + throw std::exception(); + } + } catch (...) { + LOG_ERROR("Failed to save configuration, next start will be using defaults or backed up configuration."); + } +} + +streamfx::configuration::configuration() : _data(), _config_path(), _config_backup_path() +{ + { // Retrieve global configuration path. + const char* path = obs_module_config_path("config.json"); + _config_path = path; + _config_backup_path = std::filesystem::path(_config_path).concat(path_backup_ext); + } + + try { + if (!std::filesystem::exists(_config_path) || !std::filesystem::is_regular_file(_config_path)) { + throw std::exception(); + } else { + obs_data_t* data = obs_data_create_from_json_file_safe(_config_path.string().c_str(), + _config_backup_path.string().c_str()); + if (!data) { + throw std::exception(); + } else { + _data = std::shared_ptr(data, obs::obs_data_deleter); + } + } + } catch (...) { + _data = std::shared_ptr(obs_data_create(), obs::obs_data_deleter); + } +} + +std::shared_ptr streamfx::configuration::get() +{ + obs_data_addref(_data.get()); + return std::shared_ptr(_data.get(), obs::obs_data_deleter); +} + +uint64_t streamfx::configuration::version() +{ + return static_cast(obs_data_get_int(_data.get(), version_tag_name.data())); +} + +bool streamfx::configuration::is_different_version() +{ + return (version() & STREAMFX_MASK_COMPAT) != (STREAMFX_VERSION & STREAMFX_MASK_COMPAT); +} + +static std::shared_ptr _instance = nullptr; + +void streamfx::configuration::initialize() +{ + if (!_instance) + _instance = std::make_shared(); +} + +void streamfx::configuration::finalize() +{ + _instance.reset(); +} + +std::shared_ptr streamfx::configuration::instance() +{ + return _instance; +} diff --git a/source/configuration.hpp b/source/configuration.hpp new file mode 100644 index 00000000..3ced48d4 --- /dev/null +++ b/source/configuration.hpp @@ -0,0 +1,48 @@ +/* + * Modern effects for a modern Streamer + * Copyright (C) 2020 Michael Fabian Dirks + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma once +#include "common.hpp" +#include +#include + +namespace streamfx { + class configuration { + std::shared_ptr _data; + + std::filesystem::path _config_path; + std::filesystem::path _config_backup_path; + + public: + ~configuration(); + configuration(); + + public: + std::shared_ptr get(); + + uint64_t version(); + + bool is_different_version(); + + public /* Singleton */: + static void initialize(); + static void finalize(); + static std::shared_ptr instance(); + }; +} // namespace streamfx diff --git a/source/plugin.cpp b/source/plugin.cpp index 7584a420..b143b17c 100644 --- a/source/plugin.cpp +++ b/source/plugin.cpp @@ -19,6 +19,7 @@ #include "plugin.hpp" #include +#include "configuration.hpp" #include "obs/obs-source-tracker.hpp" #ifdef ENABLE_ENCODER_FFMPEG @@ -69,6 +70,9 @@ try { global_threadpool = std::make_shared(); + // Initialize Configuration + streamfx::configuration::initialize(); + // Initialize Source Tracker obs::source_tracker::initialize(); @@ -173,6 +177,9 @@ try { // Finalize Source Tracker obs::source_tracker::finalize(); + // Finalize Configuration + streamfx::configuration::finalize(); + global_threadpool.reset(); } catch (...) { LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);