Introduce plugin manager

This commit is contained in:
Moritz Lipp 2012-04-01 18:32:16 +02:00
parent 7a9c7d762c
commit 025c995d89
8 changed files with 203 additions and 112 deletions

View file

@ -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) {

1
page.c
View file

@ -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 */

164
plugin.c
View file

@ -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)
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)
#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)
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)
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)
GIRARA_LIST_FOREACH_END(zathura->plugins.path, char*, iter, plugindir); GIRARA_LIST_FOREACH_END(zathura->plugins.path, char*, iter, plugindir);
} }
void zathura_plugin_t*
zathura_document_plugin_free(zathura_plugin_t* plugin) 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; 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)
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)
{ {

View file

@ -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,6 +25,55 @@ struct zathura_plugin_s
void* handle; /**< DLL handle */ 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 * 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)(); 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 #endif // PLUGIN_H

10
types.h
View file

@ -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
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
* *

14
utils.c
View file

@ -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)
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

View file

@ -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[])
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[])
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)
} }
/* free registered plugins */ /* free registered plugins */
girara_list_free(zathura->plugins.type_plugin_mapping); zathura_plugin_manager_free(zathura->plugins.manager);
girara_list_free(zathura->plugins.plugins);
girara_list_free(zathura->plugins.path);
/* free config variables */ /* free config variables */
g_free(zathura->config.config_dir); g_free(zathura->config.config_dir);

View file

@ -63,9 +63,7 @@ typedef struct zathura_s
struct struct
{ {
girara_list_t* plugins; /**< List of plugins */ void* manager; /**< Plugin manager */
girara_list_t* path; /**< List of plugin paths */
girara_list_t* type_plugin_mapping; /**< List of type -> plugin mappings */
} plugins; } plugins;
struct struct