// license:BSD-3-Clause // copyright-holders:Miodrag Milanovic /*************************************************************************** pluginopts.cpp Plugin options manager. ***************************************************************************/ #include "emu.h" #include "pluginopts.h" #include "options.h" #include #include #include #include //************************************************************************** // PLUGIN OPTIONS //************************************************************************** //------------------------------------------------- // plugin_options - constructor //------------------------------------------------- plugin_options::plugin_options() { } //------------------------------------------------- // scan_directory //------------------------------------------------- void plugin_options::scan_directory(const std::string &path, bool recursive) { // first try to open as a directory osd::directory::ptr directory = osd::directory::open(path); if (directory) { // iterate over all files in the directory for (const osd::directory::entry *entry = directory->read(); entry != nullptr; entry = directory->read()) { if (entry->type == osd::directory::entry::entry_type::FILE && !strcmp(entry->name, "plugin.json")) { std::string curfile = std::string(path).append(PATH_SEPARATOR).append(entry->name); load_plugin(curfile); } else if (entry->type == osd::directory::entry::entry_type::DIR) { if (recursive && strcmp(entry->name, ".") && strcmp(entry->name, "..")) scan_directory(path + PATH_SEPARATOR + entry->name, recursive); } } } } //------------------------------------------------- // load_plugin //------------------------------------------------- bool plugin_options::load_plugin(const std::string &path) { std::ifstream ifs(path); rapidjson::IStreamWrapper isw(ifs); rapidjson::Document document; document.ParseStream<0>(isw); if (document.HasParseError()) { const std::string error(GetParseError_En(document.GetParseError())); osd_printf_error("Unable to parse plugin definition file %s. Errors returned:\n%s", path, error); return false; } if (!document["plugin"].IsObject()) { osd_printf_error("Bad plugin definition file %s:\n", path); return false; } size_t last_path_sep = path.find_last_of(PATH_SEPARATOR[0]); std::string dir = last_path_sep != std::string::npos ? path.substr(0, last_path_sep) : "."; plugin p; p.m_name = document["plugin"]["name"].GetString(); p.m_description = document["plugin"]["description"].GetString(); p.m_type = document["plugin"]["type"].GetString(); p.m_directory = std::move(dir); p.m_start = false; if (document["plugin"].HasMember("start") && (std::string(document["plugin"]["start"].GetString()) == "true")) p.m_start = true; m_plugins.push_back(std::move(p)); return true; } //------------------------------------------------- // find //------------------------------------------------- plugin *plugin_options::find(const std::string &name) { auto iter = std::find_if( m_plugins.begin(), m_plugins.end(), [&name](const plugin &p) { return name == p.m_name; }); return iter != m_plugins.end() ? &*iter : nullptr; } //------------------------------------------------- // create_core_options //------------------------------------------------- static core_options create_core_options(const plugin_options &plugin_opts) { // we're sort of abusing core_options to just get INI file parsing, so we'll build a // core_options structure for the sole purpose of parsing an INI file, and then reflect // the data back static const options_entry s_option_entries[] = { { nullptr, nullptr, OPTION_HEADER, "PLUGINS OPTIONS" }, { nullptr } }; core_options opts; opts.add_entries(s_option_entries); // create an entry for each option for (const plugin &p : plugin_opts.plugins()) { opts.add_entry( { p.m_name }, nullptr, core_options::option_type::BOOLEAN, p.m_start ? "1" : "0"); } return opts; } //------------------------------------------------- // parse_ini_file //------------------------------------------------- void plugin_options::parse_ini_file(util::core_file &inifile) { core_options opts = create_core_options(*this); // parse the INI file opts.parse_ini_file(inifile, OPTION_PRIORITY_NORMAL, true, true); // and reflect these options back for (plugin &p : m_plugins) p.m_start = opts.bool_value(p.m_name.c_str()); } //------------------------------------------------- // output_ini //------------------------------------------------- std::string plugin_options::output_ini() const { core_options opts = create_core_options(*this); return opts.output_ini(); }