diff --git a/libdino/CMakeLists.txt b/libdino/CMakeLists.txt index 22dab2d8..96abdd62 100644 --- a/libdino/CMakeLists.txt +++ b/libdino/CMakeLists.txt @@ -74,7 +74,7 @@ DEPENDS ${CMAKE_BINARY_DIR}/exports/dino_i18n.h ) -add_definitions(${VALA_CFLAGS} -DDINO_PLUGINS_SYSTEM_PLUGIN_DIR="${PLUGIN_INSTALL_DIR}" -DDINO_PLUGINS_SYSTEM_LIBDIR_NAME="${LIBDIR_NAME}") +add_definitions(${VALA_CFLAGS} -DDINO_SYSTEM_PLUGIN_DIR="${PLUGIN_INSTALL_DIR}" -DDINO_SYSTEM_LIBDIR_NAME="${LIBDIR_NAME}") add_library(libdino SHARED ${LIBDINO_VALA_C} ${CMAKE_BINARY_DIR}/exports/dino_i18n.h) add_dependencies(libdino dino-vapi) target_link_libraries(libdino xmpp-vala qlite ${LIBDINO_PACKAGES} m) diff --git a/libdino/src/plugin/loader.vala b/libdino/src/plugin/loader.vala index d38a0ec5..43876b92 100644 --- a/libdino/src/plugin/loader.vala +++ b/libdino/src/plugin/loader.vala @@ -1,7 +1,6 @@ -namespace Dino.Plugins { +using Gee; -private extern const string SYSTEM_LIBDIR_NAME; -private extern const string SYSTEM_PLUGIN_DIR; +namespace Dino.Plugins { private class Info : Object { public Module module; @@ -15,72 +14,76 @@ private class Info : Object { public class Loader : Object { [CCode (has_target = false)] - private delegate Type RegisterPluginFunction (Module module); + private delegate Type RegisterPluginFunction(Module module); - private string[] search_paths = new string[0]; + private Application app; + private string[] search_paths; private RootInterface[] plugins = new RootInterface[0]; private Info[] infos = new Info[0]; - public Loader(string? exec_str = null) { - if (Environment.get_variable("DINO_PLUGIN_DIR") != null) { - search_paths += Environment.get_variable("DINO_PLUGIN_DIR"); - } - search_paths += Path.build_filename(Environment.get_home_dir(), ".local", "lib", "dino", "plugins"); - string? exec_path = exec_str; - if (exec_path != null) { - if (!exec_path.contains(Path.DIR_SEPARATOR_S)) { - exec_path = Environment.find_program_in_path(exec_str); - } - if (Path.get_dirname(exec_path).contains("dino") || Path.get_dirname(exec_path) == "." || Path.get_dirname(exec_path).contains("build")) { - search_paths += Path.build_filename(Path.get_dirname(exec_path), "plugins"); - } - if (Path.get_basename(Path.get_dirname(exec_path)) == "bin") { - search_paths += Path.build_filename(Path.get_dirname(Path.get_dirname(exec_path)), SYSTEM_LIBDIR_NAME, "dino", "plugins"); - } - } - search_paths += SYSTEM_PLUGIN_DIR; + public Loader(Application app) { + this.app = app; + this.search_paths = app.search_path_generator.get_plugin_paths(); } - public void print_search_paths() { - foreach (string prefix in search_paths) { - print(@"$prefix\n"); + public void loadAll() { + if (Module.supported() == false) { + throw new Error(-1, 0, "Plugins are not supported"); + } + + HashSet plugin_names = new HashSet(); + + foreach (string path in search_paths) { + try { + Dir dir = Dir.open(path, 0); + string? file = null; + while ((file = dir.read_name()) != null) { + if (file.has_suffix(Module.SUFFIX)) plugin_names.add(file); + } + } catch (Error e) { + // Ignore this folder + } + } + + foreach (string plugin in plugin_names) { + load(plugin); } } - public RootInterface load(string name, Dino.Application app) throws Error { - if (Module.supported () == false) { - throw new Error (-1, 0, "Plugins are not supported"); + public RootInterface load(string name) throws Error { + if (Module.supported() == false) { + throw new Error(-1, 0, "Plugins are not supported"); } Module module = null; string path = ""; foreach (string prefix in search_paths) { path = Path.build_filename(prefix, name); - module = Module.open (path, ModuleFlags.BIND_LAZY); + module = Module.open(path, ModuleFlags.BIND_LAZY); if (module != null) break; } if (module == null) { - throw new Error (-1, 1, "%s", Module.error ().replace(path, name)); + throw new Error(-1, 1, "%s", Module.error().replace(path, name)); } void* function; - module.symbol ("register_plugin", out function); + module.symbol("register_plugin", out function); if (function == null) { - throw new Error (-1, 2, "register_plugin () not found"); + throw new Error(-1, 2, "register_plugin () not found"); } RegisterPluginFunction register_plugin = (RegisterPluginFunction) function; - Type type = register_plugin (module); - if (type.is_a (typeof (RootInterface)) == false) { - throw new Error (-1, 3, "Unexpected type"); + Type type = register_plugin(module); + if (type.is_a(typeof(RootInterface)) == false) { + throw new Error(-1, 3, "Unexpected type"); } - Info info = new Plugins.Info (type, (owned) module); + Info info = new Plugins.Info(type, (owned) module); infos += info; RootInterface plugin = (RootInterface) Object.new (type); plugins += plugin; - plugin.registered (app); + plugin.registered(app); return plugin; } diff --git a/libdino/src/util.vala b/libdino/src/util.vala index 85047dd8..cc705c10 100644 --- a/libdino/src/util.vala +++ b/libdino/src/util.vala @@ -1,5 +1,8 @@ namespace Dino { +private extern const string SYSTEM_LIBDIR_NAME; +private extern const string SYSTEM_PLUGIN_DIR; + public class SearchPathGenerator { public string? exec_path { get; private set; } @@ -18,6 +21,28 @@ public class SearchPathGenerator { } return locale_dir ?? locale_install_dir; } + + public string[] get_plugin_paths() { + string[] search_paths = new string[0]; + if (Environment.get_variable("DINO_PLUGIN_DIR") != null) { + search_paths += Environment.get_variable("DINO_PLUGIN_DIR"); + } + search_paths += Path.build_filename(Environment.get_home_dir(), ".local", "lib", "dino", "plugins"); + string? exec_path = this.exec_path; + if (exec_path != null) { + if (!exec_path.contains(Path.DIR_SEPARATOR_S)) { + exec_path = Environment.find_program_in_path(this.exec_path); + } + if (Path.get_dirname(exec_path).contains("dino") || Path.get_dirname(exec_path) == "." || Path.get_dirname(exec_path).contains("build")) { + search_paths += Path.build_filename(Path.get_dirname(exec_path), "plugins"); + } + if (Path.get_basename(Path.get_dirname(exec_path)) == "bin") { + search_paths += Path.build_filename(Path.get_dirname(Path.get_dirname(exec_path)), SYSTEM_LIBDIR_NAME, "dino", "plugins"); + } + } + search_paths += SYSTEM_PLUGIN_DIR; + return search_paths; + } } public static string get_storage_dir() { diff --git a/main/src/main.vala b/main/src/main.vala index c4c441a1..46b3affd 100644 --- a/main/src/main.vala +++ b/main/src/main.vala @@ -11,36 +11,14 @@ void main(string[] args) { try{ string? exec_path = args.length > 0 ? args[0] : null; SearchPathGenerator search_path_generator = new SearchPathGenerator(exec_path); - if (exec_path != null && exec_path.contains(Path.DIR_SEPARATOR_S)) { - string bindir = Path.get_dirname(exec_path); - if (FileUtils.test(Path.build_filename(bindir, "gschemas.compiled"), FileTest.IS_REGULAR)) { - Environment.set_variable("GSETTINGS_SCHEMA_DIR", Path.get_dirname(exec_path), false); - } - } Intl.textdomain(GETTEXT_PACKAGE); internationalize(GETTEXT_PACKAGE, search_path_generator.get_locale_path(GETTEXT_PACKAGE, LOCALE_INSTALL_DIR)); - Plugins.Loader loader = new Plugins.Loader(exec_path); Gtk.init(ref args); Dino.Ui.Application app = new Dino.Ui.Application() { search_path_generator=search_path_generator }; + Plugins.Loader loader = new Plugins.Loader(app); + loader.loadAll(); - app.add_main_option("plugin-paths", 0, 0, OptionArg.NONE, "Display plugin search paths and exit", null); - app.handle_local_options.connect((options) => { - Variant v = options.lookup_value("plugin-paths", VariantType.BOOLEAN); - if (v != null && v.get_boolean()) { - loader.print_search_paths(); - return 0; - } - return -1; - }); - - foreach (string plugin in new string[]{"omemo", "openpgp", "http-files"}) { - try { - loader.load(plugin, app); - } catch (Error e) { - print(@"Error loading plugin $plugin: $(e.message)\n"); - } - } app.run(args); loader.shutdown(); } catch (Error e) {