diff --git a/document.c b/document.c index 654955f..686be5f 100644 --- a/document.c +++ b/document.c @@ -103,13 +103,7 @@ zathura_document_open(zathura_t* zathura, const char* path, const char* password return NULL; } - zathura_plugin_t* plugin = NULL; - GIRARA_LIST_FOREACH(zathura->plugins.type_plugin_mapping, zathura_type_plugin_mapping_t*, iter, mapping) - if (g_content_type_equals(content_type, mapping->type)) { - plugin = mapping->plugin; - break; - } - GIRARA_LIST_FOREACH_END(zathura->plugins.type_plugin_mapping, zathura_type_plugin_mapping_t*, iter, mapping); + zathura_plugin_t* plugin = zathura_plugin_manager_get_plugin(zathura->plugins.manager, content_type); g_free((void*)content_type); if (plugin == NULL) { diff --git a/page.c b/page.c index 8accf5c..d42c5c2 100644 --- a/page.c +++ b/page.c @@ -10,6 +10,7 @@ #include "plugin.h" #include "utils.h" #include "internal.h" +#include "types.h" struct zathura_page_s { double height; /**< Page height */ diff --git a/plugin.c b/plugin.c index e26438c..41590da 100644 --- a/plugin.c +++ b/plugin.c @@ -13,14 +13,57 @@ #include /** - * Register document plugin + * Plugin manager */ -static bool zathura_document_plugin_register(zathura_t* zathura, zathura_plugin_t* new_plugin); +struct zathura_plugin_manager_s +{ + girara_list_t* plugins; /**< List of plugins */ + girara_list_t* path; /**< List of plugin paths */ + girara_list_t* type_plugin_mapping; /**< List of type -> plugin mappings */ +}; + +static bool register_plugin(zathura_plugin_manager_t* plugin_manager, zathura_plugin_t* plugin); +static bool plugin_mapping_new(zathura_plugin_manager_t* plugin_manager, const gchar* type, zathura_plugin_t* plugin); +static void zathura_plugin_free(zathura_plugin_t* plugin); +static void zathura_type_plugin_mapping_free(zathura_type_plugin_mapping_t* mapping); + +zathura_plugin_manager_t* +zathura_plugin_manager_new() +{ + zathura_plugin_manager_t* plugin_manager = g_malloc0(sizeof(zathura_plugin_manager_t)); + + plugin_manager->plugins = girara_list_new2((girara_free_function_t) zathura_plugin_free); + plugin_manager->path = girara_list_new2(g_free); + plugin_manager->type_plugin_mapping = girara_list_new2((girara_free_function_t)zathura_type_plugin_mapping_free); + + if (plugin_manager->plugins == NULL + || plugin_manager->path == NULL + || plugin_manager->type_plugin_mapping == NULL) { + zathura_plugin_manager_free(plugin_manager); + return NULL; + } + + return plugin_manager; +} void -zathura_document_plugins_load(zathura_t* zathura) +zathura_plugin_manager_add_dir(zathura_plugin_manager_t* plugin_manager, const char* dir) { - GIRARA_LIST_FOREACH(zathura->plugins.path, char*, iter, plugindir) + if (plugin_manager == NULL || plugin_manager->path == NULL) { + return; + } + + girara_list_append(plugin_manager->path, g_strdup(dir)); +} + +void +zathura_plugin_manager_load(zathura_plugin_manager_t* plugin_manager) +{ + if (plugin_manager == NULL || plugin_manager->path == NULL) { + return; + } + + GIRARA_LIST_FOREACH(plugin_manager->path, char*, iter, plugindir) /* read all files in the plugin directory */ GDir* dir = g_dir_open(plugindir, 0, NULL); if (dir == NULL) { @@ -31,7 +74,7 @@ zathura_document_plugins_load(zathura_t* zathura) char* name = NULL; while ((name = (char*) g_dir_read_name(dir)) != NULL) { - char* path = g_build_filename(plugindir, name, NULL); + char* path = g_build_filename(plugindir, name, NULL); if (g_file_test(path, G_FILE_TEST_IS_REGULAR) == 0) { girara_info("%s is not a regular file. Skipping.", path); g_free(path); @@ -92,10 +135,10 @@ zathura_document_plugins_load(zathura_t* zathura) #endif } - zathura_plugin_register_service_t register_plugin; - *(void**)(®ister_plugin) = dlsym(handle, PLUGIN_REGISTER_FUNCTION); + zathura_plugin_register_service_t register_service; + *(void**)(®ister_service) = dlsym(handle, PLUGIN_REGISTER_FUNCTION); - if (register_plugin == NULL) { + if (register_service == NULL) { girara_error("could not find '%s' function in plugin %s", PLUGIN_REGISTER_FUNCTION, path); g_free(path); dlclose(handle); @@ -106,7 +149,7 @@ zathura_document_plugins_load(zathura_t* zathura) plugin->content_types = girara_list_new2(g_free); plugin->handle = handle; - register_plugin(plugin); + register_service(plugin); /* register functions */ if (plugin->register_function == NULL) { @@ -118,11 +161,11 @@ zathura_document_plugins_load(zathura_t* zathura) plugin->register_function(&(plugin->functions)); - bool r = zathura_document_plugin_register(zathura, plugin); + bool ret = register_plugin(plugin_manager, plugin); - if (r == false) { + if (ret == false) { girara_error("could not register plugin %s", path); - zathura_document_plugin_free(plugin); + zathura_plugin_free(plugin); } else { girara_info("successfully loaded plugin %s", path); } @@ -133,61 +176,97 @@ zathura_document_plugins_load(zathura_t* zathura) GIRARA_LIST_FOREACH_END(zathura->plugins.path, char*, iter, plugindir); } -void -zathura_document_plugin_free(zathura_plugin_t* plugin) +zathura_plugin_t* +zathura_plugin_manager_get_plugin(zathura_plugin_manager_t* plugin_manager, const char* type) { - if (plugin == NULL) { + if (plugin_manager == NULL || plugin_manager->type_plugin_mapping == NULL || type == NULL) { + return NULL; + } + + zathura_plugin_t* plugin = NULL; + GIRARA_LIST_FOREACH(plugin_manager->type_plugin_mapping, zathura_type_plugin_mapping_t*, iter, mapping) + if (g_content_type_equals(type, mapping->type)) { + plugin = mapping->plugin; + break; + } + GIRARA_LIST_FOREACH_END(plugin_manager->type_plugin_mapping, zathura_type_plugin_mapping_t*, iter, mapping); + + return plugin; +} + +void +zathura_plugin_manager_free(zathura_plugin_manager_t* plugin_manager) +{ + if (plugin_manager == NULL) { return; } - dlclose(plugin->handle); - girara_list_free(plugin->content_types); - g_free(plugin); + if (plugin_manager->plugins != NULL) { + girara_list_free(plugin_manager->plugins); + } + + if (plugin_manager->path != NULL) { + girara_list_free(plugin_manager->path); + } + + if (plugin_manager->type_plugin_mapping != NULL) { + girara_list_free(plugin_manager->type_plugin_mapping); + } + + g_free(plugin_manager); } static bool -zathura_document_plugin_register(zathura_t* zathura, zathura_plugin_t* new_plugin) +register_plugin(zathura_plugin_manager_t* plugin_manager, zathura_plugin_t* plugin) { - if (new_plugin == NULL || new_plugin->content_types == NULL || new_plugin->register_function == NULL) { + if (plugin == NULL + || plugin->content_types == NULL + || plugin->register_function == NULL + || plugin_manager == NULL + || plugin_manager->plugins == NULL) { girara_error("plugin: could not register\n"); return false; } - bool atleastone = false; - GIRARA_LIST_FOREACH(new_plugin->content_types, gchar*, iter, type) - if (!zathura_type_plugin_mapping_new(zathura, type, new_plugin)) { + bool at_least_one = false; + GIRARA_LIST_FOREACH(plugin->content_types, gchar*, iter, type) + if (plugin_mapping_new(plugin_manager, type, plugin) == false) { girara_error("plugin: already registered for filetype %s\n", type); } else { - atleastone = true; + at_least_one = true; } - GIRARA_LIST_FOREACH_END(new_plugin->content_types, gchar*, iter, type); + GIRARA_LIST_FOREACH_END(plugin->content_types, gchar*, iter, type); - if (atleastone) { - girara_list_append(zathura->plugins.plugins, new_plugin); + if (at_least_one == true) { + girara_list_append(plugin_manager->plugins, plugin); } - return atleastone; + + return at_least_one; } -bool -zathura_type_plugin_mapping_new(zathura_t* zathura, const gchar* type, zathura_plugin_t* plugin) +static bool +plugin_mapping_new(zathura_plugin_manager_t* plugin_manager, const gchar* type, zathura_plugin_t* plugin) { - g_return_val_if_fail(zathura && type && plugin, false); + g_return_val_if_fail(plugin_manager != NULL, false); + g_return_val_if_fail(type != NULL, false); + g_return_val_if_fail(plugin != NULL, false); - GIRARA_LIST_FOREACH(zathura->plugins.type_plugin_mapping, zathura_type_plugin_mapping_t*, iter, mapping) + GIRARA_LIST_FOREACH(plugin_manager->type_plugin_mapping, zathura_type_plugin_mapping_t*, iter, mapping) if (g_content_type_equals(type, mapping->type)) { girara_list_iterator_free(iter); return false; } - GIRARA_LIST_FOREACH_END(zathura->plugins.type_plugin_mapping, zathura_type_plugin_mapping_t*, iter, mapping); + GIRARA_LIST_FOREACH_END(plugin_manager->type_plugin_mapping, zathura_type_plugin_mapping_t*, iter, mapping); zathura_type_plugin_mapping_t* mapping = g_malloc(sizeof(zathura_type_plugin_mapping_t)); - mapping->type = g_strdup(type); + mapping->type = g_strdup(type); mapping->plugin = plugin; - girara_list_append(zathura->plugins.type_plugin_mapping, mapping); + girara_list_append(plugin_manager->type_plugin_mapping, mapping); + return true; } -void +static void zathura_type_plugin_mapping_free(zathura_type_plugin_mapping_t* mapping) { if (mapping == NULL) { @@ -198,6 +277,19 @@ zathura_type_plugin_mapping_free(zathura_type_plugin_mapping_t* mapping) g_free(mapping); } +static void +zathura_plugin_free(zathura_plugin_t* plugin) +{ + if (plugin == NULL) { + return; + } + + dlclose(plugin->handle); + girara_list_free(plugin->content_types); + g_free(plugin); +} + +/* plugin-api.h */ void zathura_plugin_set_register_functions_function(zathura_plugin_t* plugin, zathura_plugin_register_function_t register_function) { @@ -215,5 +307,5 @@ zathura_plugin_add_mimetype(zathura_plugin_t* plugin, const char* mime_type) return; } - girara_list_append(plugin->content_types, g_content_type_from_mime_type(mime_type)); + girara_list_append(plugin->content_types, g_content_type_from_mime_type(mime_type)); } diff --git a/plugin.h b/plugin.h index 039ca90..378349f 100644 --- a/plugin.h +++ b/plugin.h @@ -14,15 +14,6 @@ #define PLUGIN_API_VERSION_FUNCTION "zathura_plugin_api_version" #define PLUGIN_ABI_VERSION_FUNCTION "zathura_plugin_abi_version" -/** - * Plugin mapping - */ -typedef struct zathura_type_plugin_mapping_s -{ - const gchar* type; /**< Plugin type */ - zathura_plugin_t* plugin; /**< Mapped plugin */ -} zathura_type_plugin_mapping_t; - /** * Document plugin structure */ @@ -34,6 +25,55 @@ struct zathura_plugin_s void* handle; /**< DLL handle */ }; +typedef struct zathura_plugin_manager_s zathura_plugin_manager_t; + +/** + * Creates a new instance of the plugin manager + * + * @return A plugin manager object or NULL if an error occured + */ +zathura_plugin_manager_t* zathura_plugin_manager_new(); + +/** + * Adds a plugin directory to the plugin manager + * + * @param plugin_manager The plugin manager + * @param dir Path to a directory with plugins + */ +void zathura_plugin_manager_add_dir(zathura_plugin_manager_t* plugin_manager, const char* dir); + +/** + * Loads all plugins available in the previously given directories + * + * @param plugin_manager The plugin manager + */ +void zathura_plugin_manager_load(zathura_plugin_manager_t* plugin_manager); + +/** + * Returns the (if available) associated plugin + * + * @param plugin_manager The plugin manager + * @param type The document type + * @return The plugin or NULL if no matching plugin is available + */ +zathura_plugin_t* zathura_plugin_manager_get_plugin(zathura_plugin_manager_t* plugin_manager, const char* type); + +/** + * Frees the plugin manager + * + * @param plugin_manager + */ +void zathura_plugin_manager_free(zathura_plugin_manager_t* plugin_manager); + +/** + * Plugin mapping + */ +typedef struct zathura_type_plugin_mapping_s +{ + const gchar* type; /**< Plugin type */ + zathura_plugin_t* plugin; /**< Mapped plugin */ +} zathura_type_plugin_mapping_t; + /** * Function prototype that is called to register a document plugin * @@ -56,34 +96,4 @@ typedef unsigned int (*zathura_plugin_api_version_t)(); */ typedef unsigned int (*zathura_plugin_abi_version_t)(); -/** - * Load all document plugins - * - * @param zathura the zathura session - */ -void zathura_document_plugins_load(zathura_t* zathura); - -/** - * Free a document plugin - * - * @param plugin The plugin - */ -void zathura_document_plugin_free(zathura_plugin_t* plugin); - -/** - * Add type -> plugin mapping - * @param zathura zathura instance - * @param type content type - * @param plugin plugin instance - * @return true on success, false if another plugin is already registered for - * that type - */ -bool zathura_type_plugin_mapping_new(zathura_t* zathura, const gchar* type, zathura_plugin_t* plugin); - -/** - * Free type -> plugin mapping - * @param mapping To be freed - */ -void zathura_type_plugin_mapping_free(zathura_type_plugin_mapping_t* mapping); - #endif // PLUGIN_H diff --git a/types.h b/types.h index f0e285f..c9c2d73 100644 --- a/types.h +++ b/types.h @@ -5,11 +5,6 @@ #include "zathura.h" -/** - * Plugin - */ -typedef struct zathura_plugin_s zathura_plugin_t; - /** * Error types */ @@ -39,6 +34,11 @@ typedef enum zathura_document_information_type_e ZATHURA_DOCUMENT_INFORMATION_OTHER /**< Any other information */ } zathura_document_information_type_t; +/** + * Plugin + */ +typedef struct zathura_plugin_s zathura_plugin_t; + /** * Document information entry * diff --git a/utils.c b/utils.c index 642253a..a65b6ca 100644 --- a/utils.c +++ b/utils.c @@ -47,7 +47,7 @@ file_get_extension(const char* path) bool file_valid_extension(zathura_t* zathura, const char* path) { - if (zathura == NULL || path == NULL) { + if (zathura == NULL || zathura->plugins.manager == NULL || path == NULL) { return false; } @@ -56,16 +56,10 @@ file_valid_extension(zathura_t* zathura, const char* path) return false; } - bool result = false; - GIRARA_LIST_FOREACH(zathura->plugins.type_plugin_mapping, zathura_type_plugin_mapping_t*, iter, mapping) - if (g_content_type_equals(content_type, mapping->type)) { - result = true; - break; - } - GIRARA_LIST_FOREACH_END(zathura->plugins.type_plugin_mapping, zathura_type_plugin_mapping_t*, iter, mapping); - + zathura_plugin_t* plugin = zathura_plugin_manager_get_plugin(zathura->plugins.manager, content_type); g_free((void*)content_type); - return result; + + return (plugin == NULL) ? false : true; } bool diff --git a/zathura.c b/zathura.c index 58f7a8f..6398abd 100644 --- a/zathura.c +++ b/zathura.c @@ -103,12 +103,12 @@ zathura_init(int argc, char* argv[]) zathura_t* zathura = g_malloc0(sizeof(zathura_t)); /* plugins */ - zathura->plugins.plugins = girara_list_new2( - (girara_free_function_t)zathura_document_plugin_free); - zathura->plugins.path = girara_list_new2(g_free); - zathura->plugins.type_plugin_mapping = girara_list_new2( - (girara_free_function_t)zathura_type_plugin_mapping_free); + zathura->plugins.manager = zathura_plugin_manager_new(); + if (zathura->plugins.manager == NULL) { + goto error_free; + } + /* configuration and data */ if (config_dir != NULL) { zathura->config.config_dir = g_strdup(config_dir); } else { @@ -131,12 +131,16 @@ zathura_init(int argc, char* argv[]) if (plugin_path != NULL) { girara_list_t* paths = girara_split_path_array(plugin_path); - girara_list_merge(zathura->plugins.path, paths); + GIRARA_LIST_FOREACH(paths, char*, iter, path) + zathura_plugin_manager_add_dir(zathura->plugins.manager, path); + GIRARA_LIST_FOREACH_END(paths, char*, iter, path); girara_list_free(paths); } else { #ifdef ZATHURA_PLUGINDIR girara_list_t* paths = girara_split_path_array(ZATHURA_PLUGINDIR); - girara_list_merge(zathura->plugins.path, paths); + GIRARA_LIST_FOREACH(paths, char*, iter, path) + zathura_plugin_manager_add_dir(zathura->plugins.manager, path); + GIRARA_LIST_FOREACH_END(paths, char*, iter, path); girara_list_free(paths); #endif } @@ -153,7 +157,7 @@ zathura_init(int argc, char* argv[]) zathura->global.update_page_number = true; /* load plugins */ - zathura_document_plugins_load(zathura); + zathura_plugin_manager_load(zathura->plugins.manager); /* configuration */ config_load_default(zathura); @@ -335,9 +339,7 @@ zathura_free(zathura_t* zathura) } /* free registered plugins */ - girara_list_free(zathura->plugins.type_plugin_mapping); - girara_list_free(zathura->plugins.plugins); - girara_list_free(zathura->plugins.path); + zathura_plugin_manager_free(zathura->plugins.manager); /* free config variables */ g_free(zathura->config.config_dir); diff --git a/zathura.h b/zathura.h index 17d581c..75fe785 100644 --- a/zathura.h +++ b/zathura.h @@ -63,9 +63,7 @@ typedef struct zathura_s struct { - girara_list_t* plugins; /**< List of plugins */ - girara_list_t* path; /**< List of plugin paths */ - girara_list_t* type_plugin_mapping; /**< List of type -> plugin mappings */ + void* manager; /**< Plugin manager */ } plugins; struct