Commit 025c995d authored by Moritz Lipp's avatar Moritz Lipp
Browse files

Introduce plugin manager

parent 7a9c7d76
...@@ -103,13 +103,7 @@ zathura_document_open(zathura_t* zathura, const char* path, const char* password ...@@ -103,13 +103,7 @@ zathura_document_open(zathura_t* zathura, const char* path, const char* password
return NULL; return NULL;
} }
zathura_plugin_t* plugin = NULL; zathura_plugin_t* plugin = zathura_plugin_manager_get_plugin(zathura->plugins.manager, content_type);
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);
g_free((void*)content_type); g_free((void*)content_type);
if (plugin == NULL) { if (plugin == NULL) {
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "plugin.h" #include "plugin.h"
#include "utils.h" #include "utils.h"
#include "internal.h" #include "internal.h"
#include "types.h"
struct zathura_page_s { struct zathura_page_s {
double height; /**< Page height */ double height; /**< Page height */
......
...@@ -13,14 +13,57 @@ ...@@ -13,14 +13,57 @@
#include <girara/settings.h> #include <girara/settings.h>
/** /**
* 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 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 */ /* read all files in the plugin directory */
GDir* dir = g_dir_open(plugindir, 0, NULL); GDir* dir = g_dir_open(plugindir, 0, NULL);
if (dir == NULL) { if (dir == NULL) {
...@@ -31,7 +74,7 @@ zathura_document_plugins_load(zathura_t* zathura) ...@@ -31,7 +74,7 @@ zathura_document_plugins_load(zathura_t* zathura)
char* name = NULL; char* name = NULL;
while ((name = (char*) g_dir_read_name(dir)) != 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) { if (g_file_test(path, G_FILE_TEST_IS_REGULAR) == 0) {
girara_info("%s is not a regular file. Skipping.", path); girara_info("%s is not a regular file. Skipping.", path);
g_free(path); g_free(path);
...@@ -92,10 +135,10 @@ zathura_document_plugins_load(zathura_t* zathura) ...@@ -92,10 +135,10 @@ zathura_document_plugins_load(zathura_t* zathura)
#endif #endif
} }
zathura_plugin_register_service_t register_plugin; zathura_plugin_register_service_t register_service;
*(void**)(&register_plugin) = dlsym(handle, PLUGIN_REGISTER_FUNCTION); *(void**)(&register_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); girara_error("could not find '%s' function in plugin %s", PLUGIN_REGISTER_FUNCTION, path);
g_free(path); g_free(path);
dlclose(handle); dlclose(handle);
...@@ -106,7 +149,7 @@ zathura_document_plugins_load(zathura_t* zathura) ...@@ -106,7 +149,7 @@ zathura_document_plugins_load(zathura_t* zathura)
plugin->content_types = girara_list_new2(g_free); plugin->content_types = girara_list_new2(g_free);
plugin->handle = handle; plugin->handle = handle;
register_plugin(plugin); register_service(plugin);
/* register functions */ /* register functions */
if (plugin->register_function == NULL) { if (plugin->register_function == NULL) {
...@@ -118,11 +161,11 @@ zathura_document_plugins_load(zathura_t* zathura) ...@@ -118,11 +161,11 @@ zathura_document_plugins_load(zathura_t* zathura)
plugin->register_function(&(plugin->functions)); 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); girara_error("could not register plugin %s", path);
zathura_document_plugin_free(plugin); zathura_plugin_free(plugin);
} else { } else {
girara_info("successfully loaded plugin %s", path); girara_info("successfully loaded plugin %s", path);
} }
...@@ -133,61 +176,97 @@ zathura_document_plugins_load(zathura_t* zathura) ...@@ -133,61 +176,97 @@ zathura_document_plugins_load(zathura_t* zathura)
GIRARA_LIST_FOREACH_END(zathura->plugins.path, char*, iter, plugindir); GIRARA_LIST_FOREACH_END(zathura->plugins.path, char*, iter, plugindir);
} }
zathura_plugin_t*
zathura_plugin_manager_get_plugin(zathura_plugin_manager_t* plugin_manager, const char* type)
{
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 void
zathura_document_plugin_free(zathura_plugin_t* plugin) zathura_plugin_manager_free(zathura_plugin_manager_t* plugin_manager)
{ {
if (plugin == NULL) { if (plugin_manager == NULL) {
return; return;
} }
dlclose(plugin->handle); if (plugin_manager->plugins != NULL) {
girara_list_free(plugin->content_types); girara_list_free(plugin_manager->plugins);
g_free(plugin); }
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 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"); girara_error("plugin: could not register\n");
return false; return false;
} }
bool atleastone = false; bool at_least_one = false;
GIRARA_LIST_FOREACH(new_plugin->content_types, gchar*, iter, type) GIRARA_LIST_FOREACH(plugin->content_types, gchar*, iter, type)
if (!zathura_type_plugin_mapping_new(zathura, type, new_plugin)) { if (plugin_mapping_new(plugin_manager, type, plugin) == false) {
girara_error("plugin: already registered for filetype %s\n", type); girara_error("plugin: already registered for filetype %s\n", type);
} else { } 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) { if (at_least_one == true) {
girara_list_append(zathura->plugins.plugins, new_plugin); girara_list_append(plugin_manager->plugins, plugin);
} }
return atleastone;
return at_least_one;
} }
bool static bool
zathura_type_plugin_mapping_new(zathura_t* zathura, const gchar* type, zathura_plugin_t* plugin) 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)) { if (g_content_type_equals(type, mapping->type)) {
girara_list_iterator_free(iter); girara_list_iterator_free(iter);
return false; 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)); 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; mapping->plugin = plugin;
girara_list_append(zathura->plugins.type_plugin_mapping, mapping); girara_list_append(plugin_manager->type_plugin_mapping, mapping);
return true; return true;
} }
void static void
zathura_type_plugin_mapping_free(zathura_type_plugin_mapping_t* mapping) zathura_type_plugin_mapping_free(zathura_type_plugin_mapping_t* mapping)
{ {
if (mapping == NULL) { if (mapping == NULL) {
...@@ -198,6 +277,19 @@ zathura_type_plugin_mapping_free(zathura_type_plugin_mapping_t* mapping) ...@@ -198,6 +277,19 @@ zathura_type_plugin_mapping_free(zathura_type_plugin_mapping_t* mapping)
g_free(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 void
zathura_plugin_set_register_functions_function(zathura_plugin_t* plugin, zathura_plugin_register_function_t register_function) 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) ...@@ -215,5 +307,5 @@ zathura_plugin_add_mimetype(zathura_plugin_t* plugin, const char* mime_type)
return; 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));
} }
...@@ -14,15 +14,6 @@ ...@@ -14,15 +14,6 @@
#define PLUGIN_API_VERSION_FUNCTION "zathura_plugin_api_version" #define PLUGIN_API_VERSION_FUNCTION "zathura_plugin_api_version"
#define PLUGIN_ABI_VERSION_FUNCTION "zathura_plugin_abi_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 * Document plugin structure
*/ */
...@@ -34,56 +25,75 @@ struct zathura_plugin_s ...@@ -34,56 +25,75 @@ struct zathura_plugin_s
void* handle; /**< DLL handle */ void* handle; /**< DLL handle */
}; };
typedef struct zathura_plugin_manager_s zathura_plugin_manager_t;
/** /**
* Function prototype that is called to register a document plugin * Creates a new instance of the plugin manager
* *
* @param The document plugin * @return A plugin manager object or NULL if an error occured
*/ */
typedef void (*zathura_plugin_register_service_t)(zathura_plugin_t*); zathura_plugin_manager_t* zathura_plugin_manager_new();
/** /**
* Function prototype that is called to get the plugin's API version. * Adds a plugin directory to the plugin manager
* *
* @return plugin's API version * @param plugin_manager The plugin manager
* @param dir Path to a directory with plugins
*/ */
typedef unsigned int (*zathura_plugin_api_version_t)(); void zathura_plugin_manager_add_dir(zathura_plugin_manager_t* plugin_manager, const char* dir);
/** /**
* Function prototype that is called to get the ABI version the plugin is built * Loads all plugins available in the previously given directories
* against.
* *
* @return plugin's ABI version * @param plugin_manager The plugin manager
*/ */
typedef unsigned int (*zathura_plugin_abi_version_t)(); void zathura_plugin_manager_load(zathura_plugin_manager_t* plugin_manager);
/** /**
* Load all document plugins * Returns the (if available) associated plugin
* *
* @param zathura the zathura session * @param plugin_manager The plugin manager
* @param type The document type
* @return The plugin or NULL if no matching plugin is available
*/ */
void zathura_document_plugins_load(zathura_t* zathura); zathura_plugin_t* zathura_plugin_manager_get_plugin(zathura_plugin_manager_t* plugin_manager, const char* type);
/** /**
* Free a document plugin * Frees the plugin manager
* *
* @param plugin The plugin * @param plugin_manager
*/ */
void zathura_document_plugin_free(zathura_plugin_t* plugin); void zathura_plugin_manager_free(zathura_plugin_manager_t* plugin_manager);
/** /**
* Add type -> plugin mapping * 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); 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
*
* @param The document plugin
*/
typedef void (*zathura_plugin_register_service_t)(zathura_plugin_t*);
/**
* Function prototype that is called to get the plugin's API version.
*
* @return plugin's API version
*/
typedef unsigned int (*zathura_plugin_api_version_t)();
/** /**
* Free type -> plugin mapping * Function prototype that is called to get the ABI version the plugin is built
* @param mapping To be freed * against.
*
* @return plugin's ABI version
*/ */
void zathura_type_plugin_mapping_free(zathura_type_plugin_mapping_t* mapping); typedef unsigned int (*zathura_plugin_abi_version_t)();
#endif // PLUGIN_H #endif // PLUGIN_H
...@@ -5,11 +5,6 @@ ...@@ -5,11 +5,6 @@
#include "zathura.h" #include "zathura.h"
/**
* Plugin
*/
typedef struct zathura_plugin_s zathura_plugin_t;
/** /**
* Error types * Error types
*/ */
...@@ -39,6 +34,11 @@ typedef enum zathura_document_information_type_e ...@@ -39,6 +34,11 @@ typedef enum zathura_document_information_type_e
ZATHURA_DOCUMENT_INFORMATION_OTHER /**< Any other information */ ZATHURA_DOCUMENT_INFORMATION_OTHER /**< Any other information */
} zathura_document_information_type_t; } zathura_document_information_type_t;
/**
* Plugin
*/
typedef struct zathura_plugin_s zathura_plugin_t;
/** /**
* Document information entry * Document information entry
* *
......
...@@ -47,7 +47,7 @@ file_get_extension(const char* path) ...@@ -47,7 +47,7 @@ file_get_extension(const char* path)
bool bool
file_valid_extension(zathura_t* zathura, const char* path) 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; return false;
} }
...@@ -56,16 +56,10 @@ file_valid_extension(zathura_t* zathura, const char* path) ...@@ -56,16 +56,10 @@ file_valid_extension(zathura_t* zathura, const char* path)
return false; return false;
} }
bool result = false; zathura_plugin_t* plugin = zathura_plugin_manager_get_plugin(zathura->plugins.manager, content_type);
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);
g_free((void*)content_type); g_free((void*)content_type);
return result;
return (plugin == NULL) ? false : true;
} }
bool bool
......
...@@ -103,12 +103,12 @@ zathura_init(int argc, char* argv[]) ...@@ -103,12 +103,12 @@ zathura_init(int argc, char* argv[])
zathura_t* zathura = g_malloc0(sizeof(zathura_t)); zathura_t* zathura = g_malloc0(sizeof(zathura_t));
/* plugins */ /* plugins */
zathura->plugins.plugins = girara_list_new2( zathura->plugins.manager = zathura_plugin_manager_new();
(girara_free_function_t)zathura_document_plugin_free); if (zathura->plugins.manager == NULL) {
zathura->plugins.path = girara_list_new2(g_free); goto error_free;
zathura->plugins.type_plugin_mapping = girara_list_new2( }
(girara_free_function_t)zathura_type_plugin_mapping_free);
/* configuration and data */
if (config_dir != NULL) { if (config_dir != NULL) {
zathura->config.config_dir = g_strdup(config_dir); zathura->config.config_dir = g_strdup(config_dir);
} else { } else {
...@@ -131,12 +131,16 @@ zathura_init(int argc, char* argv[]) ...@@ -131,12 +131,16 @@ zathura_init(int argc, char* argv[])
if (plugin_path != NULL) { if (plugin_path != NULL) {
girara_list_t* paths = girara_split_path_array(plugin_path); 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); girara_list_free(paths);
} else { } else {
#ifdef ZATHURA_PLUGINDIR #ifdef ZATHURA_PLUGINDIR
girara_list_t* paths = girara_split_path_array(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); girara_list_free(paths);
#endif #endif
} }
...@@ -153,7 +157,7 @@ zathura_init(int argc, char* argv[]) ...@@ -153,7 +157,7 @@ zathura_init(int argc, char* argv[])
zathura->global.update_page_number = true; zathura->global.update_page_number = true;
/* load plugins */ /* load plugins */
zathura_document_plugins_load(zathura); zathura_plugin_manager_load(zathura->plugins.manager);
/* configuration */ /* configuration */
config_load_default(zathura); config_load_default(zathura);
...@@ -335,9 +339,7 @@ zathura_free(zathura_t* zathura) ...@@ -335,9 +339,7 @@ zathura_free(zathura_t* zathura)
} }
/* free registered plugins */ /* free registered plugins */