summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac1
-rw-r--r--po/POTFILES.in1
-rw-r--r--src/Makefile.am2
-rw-r--r--src/include/Makefile.am6
-rw-r--r--src/include/engagement/plugin.h78
-rw-r--r--src/lib/Makefile.am5
-rw-r--r--src/lib/plugin.c74
7 files changed, 164 insertions, 3 deletions
diff --git a/configure.ac b/configure.ac
index e8b8193..4396242 100644
--- a/configure.ac
+++ b/configure.ac
@@ -94,6 +94,7 @@ packaging/pkgbuild/Makefile
po/Makefile.in
src/Makefile
src/bin/Makefile
+src/include/Makefile
src/lib/Makefile
src/tests/Makefile
doc/engagement.1
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 2708812..7269d3e 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,2 +1,3 @@
src/bin/engagement.c
src/bin/engagement_private.h
+src/lib/plugin.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 15871c9..b52407c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,4 +1,4 @@
MAINTAINERCLEANFILES = Makefile.in
-SUBDIRS = lib bin tests
+SUBDIRS = include lib bin tests
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
new file mode 100644
index 0000000..6a1282d
--- /dev/null
+++ b/src/include/Makefile.am
@@ -0,0 +1,6 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+includesdir = $(includedir)/engagement
+includes_HEADERS = engagement/plugin.h
+
+EXTRA_DIST = gettext.h
diff --git a/src/include/engagement/plugin.h b/src/include/engagement/plugin.h
new file mode 100644
index 0000000..7bd7fa6
--- /dev/null
+++ b/src/include/engagement/plugin.h
@@ -0,0 +1,78 @@
+/*
+ * (c) Copyright 2016 Olliver Schinagl
+ * Author: Olliver Schinagl <oliver@schinagl.nl>
+ *
+ * SPDX-License-Identifier: AGPL-3.0+
+ */
+
+/** \file
+ * Common header to describe the generic plugin API.
+ */
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+#include <stdint.h>
+
+/**
+ * @defgroup Plugins
+ * @ingroup engagement
+ *
+ * Generic plugin API
+ */
+
+#define PLUGIN_MAGIC 0 /* TODO pick plugin magic */
+#define PLUGIN_VERSION_MAJOR 0 /* TODO replace with version from src? @ENGAGEMENT_VERSION_MAJOR@ */
+#define PLUGIN_VERSION_MINOR 0 /* TODO replace with version from src? */
+
+#define PLUGIN_SYMBOL "calendar_plugin" /* TODO use generic name */
+
+#define PLUGIN_INIT(plugin)
+
+enum plugin_type {
+ PLUGIN_TYPE_CALENDAR,
+ PLUGIN_TYPE_DIRECTORY,
+};
+
+struct plugin_info {
+ const char *name;
+ const char *summary;
+ const char *description;
+ const char *help;
+ const char *author;
+ const char *email;
+ const char *url;
+};
+
+struct plugin_version {
+ uint8_t major;
+ uint8_t minor;
+ uint32_t micro;
+};
+
+struct plugin {
+ uint32_t magic;
+ void *_handle;
+ enum plugin_type type;
+ const char *id;
+ struct plugin_version version;
+ struct plugin_info info;
+ void *dependencies; /* Unused/reserved */
+ bool (*load)(void);
+ bool (*unload)(void);
+ void *ui; /* struct plugin_ui ui; Unused/reserved */
+ void *ops;
+ void *priv;
+};
+
+struct plugin *plugin_load(const char *path);
+int plugin_unload(struct plugin *plugin);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _PLUGIN_H_ */
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 0eaf568..fc64133 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -3,6 +3,7 @@ MAINTAINERCLEANFILES = Makefile.in
AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib \
-I$(top_builddir)/src/lib \
+-I$(top_srcdir)/src/include \
-DPACKAGE_LIB_DIR=\"$(libdir)\" \
-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
@EFL_CFLAGS@ \
@@ -13,6 +14,6 @@ lib_LTLIBRARIES = libengagement.la
includes_HEADERS = engagement.h
includesdir = $(includedir)/engagement-@VMAJ@
-libengagement_la_SOURCES = engagement.c
-libengagement_la_LIBADD = @EFL_LIBS@ -lm
+libengagement_la_SOURCES = engagement.c plugin.c
+libengagement_la_LIBADD = @EFL_LIBS@ @LIBDL@
libengagement_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
diff --git a/src/lib/plugin.c b/src/lib/plugin.c
new file mode 100644
index 0000000..09df8de
--- /dev/null
+++ b/src/lib/plugin.c
@@ -0,0 +1,74 @@
+/*
+ * (c) Copyright 2016 Olliver Schinagl
+ * Author: Olliver Schinagl <oliver@schinagl.nl>
+ *
+ * SPDX-License-Identifier: AGPL-3.0+
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <dlfcn.h>
+
+#include <engagement/plugin.h>
+
+struct plugin *plugin_load(const char *path)
+{
+ struct plugin *plugin;
+ void *handle;
+
+ handle = dlopen(path, RTLD_LAZY); /* TODO check if RTLD_LAZY is what we want */
+ if (!handle) {
+ // TODO EINA_LOG
+ fprintf(stderr, "dlopen failed: %s\n", dlerror());
+ return NULL;
+ }
+
+ /* TODO use macro's to allow for static inclusion */
+ /* TODO use dlvsym() if available */
+ plugin = (struct plugin *)dlsym(handle, PLUGIN_SYMBOL);
+ if(!plugin) {
+ // TODO EINA_LOG
+ fprintf(stderr, "dlsym failed%s\n", dlerror());
+ return NULL;
+ }
+
+ if (plugin->magic != PLUGIN_MAGIC) {
+ // TODO EINA_LOG
+ fprintf(stderr, "Failed to init plugin, magic mismatch, plugin corrupt?\n");
+ return NULL;
+ }
+ plugin->_handle = handle;
+
+ if (plugin->load)
+ plugin->load();
+
+ return plugin;
+}
+
+int plugin_unload(struct plugin *plugin)
+{
+ int error;
+
+ if (!plugin) {
+ // TODO EINA_LOG
+ fprintf(stderr, "Cannot unload plugin %p.\n", plugin);
+ return -EFAULT;
+ }
+
+ if (plugin->unload)
+ plugin->unload();
+
+ if (!plugin->_handle) {
+ // TODO EINA_LOG
+ fprintf(stderr, "Error, no handle for plugin %s\n",
+ plugin->info.name);
+ return -EFAULT;
+ }
+ error = dlclose(plugin->_handle);
+ if (error)
+ // TODO EINA_LOG
+ fprintf(stderr, "Failed to close %s\n", dlerror());
+
+ return error;
+}