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

Introduce plugin manager

parent 7a9c7d76
......@@ -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) {
......
......@@ -10,6 +10,7 @@
#include "plugin.h"
#include "utils.h"
#include "internal.h"
#include "types.h"
struct zathura_page_s {
double height; /**< Page height */
......
......@@ -13,14 +13,57 @@
#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
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**)(&register_plugin) = dlsym(handle, PLUGIN_REGISTER_FUNCTION);
zathura_plugin_register_service_t register_service;
*(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);
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);
}
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
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;
}
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));
}
......@@ -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,56 +25,75 @@ struct zathura_plugin_s
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
* against.
* Loads all plugins available in the previously given directories
*
* @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
* @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
* Plugin mapping
*/
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
* @param mapping To be freed
* Function prototype that is called to get the ABI version the plugin is built
* 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
......@@ -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
*
......
......@@ -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
......
......@@ -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);
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment