summaryrefslogtreecommitdiff
path: root/tools/obconf/plugins.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/obconf/plugins.c')
-rw-r--r--tools/obconf/plugins.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/tools/obconf/plugins.c b/tools/obconf/plugins.c
new file mode 100644
index 00000000..f838b962
--- /dev/null
+++ b/tools/obconf/plugins.c
@@ -0,0 +1,157 @@
+#include "obconf.h"
+#include "plugins/obconf_interface.h"
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <string.h>
+#include <gmodule.h>
+
+typedef struct ConfigPlugin {
+ GModule *module;
+ char *fname;
+ char *name;
+ char *plugin_name;
+
+ PluginStartupFunc start;
+ PluginShutdownFunc stop;
+ PluginInterfaceVersionFunc interface;
+ PluginNameFunc getname;
+ PluginPluginNameFunc getpname;
+ PluginIconFunc icon;
+ PluginToplevelWidgetFunc toplevel;
+ PluginEditedFunc edited;
+ PluginLoadFunc load;
+ PluginSaveFunc save;
+} ConfigPlugin;
+
+GSList *plugins_list = NULL;
+
+static gpointer load_sym(GModule *module, char *name, char *symbol,
+ gboolean allow_fail)
+{
+ gpointer var;
+ if (!g_module_symbol(module, symbol, &var)) {
+ if (!allow_fail)
+ g_warning("Failed to load symbol '%s' from plugin '%s'",
+ symbol, name);
+ var = NULL;
+ }
+ return var;
+}
+
+static void add_plugin(ConfigPlugin *p)
+{
+ GtkTreeIter it;
+
+ gtk_list_store_append(obconf_sections_store, &it);
+ gtk_list_store_set(obconf_sections_store, &it, 0, p->name, -1);
+ gtk_notebook_append_page(obconf_options, p->toplevel(), NULL);
+}
+
+void load_dir(char *path)
+{
+ char *fpath;
+ DIR *dir;
+ struct dirent *dirp;
+ ConfigPlugin *p;
+ GModule *mod;
+ GSList *it;
+ char *suffix;
+
+ suffix = g_strconcat("-config.", G_MODULE_SUFFIX, NULL);
+
+ if (!(dir = opendir(path)))
+ return;
+ while ((dirp = readdir(dir))) {
+ if (g_strrstr(dirp->d_name, suffix)) {
+ /* look for duplicates */
+ for (it = plugins_list; it; it = it->next)
+ if (!strcmp(((ConfigPlugin*)it->data)->fname, dirp->d_name))
+ break;
+ if (!it) {
+ fpath = g_build_filename(path, dirp->d_name, NULL);
+
+ if ((mod = g_module_open(fpath, 0))) {
+ p = g_new(ConfigPlugin, 1);
+ p->module = mod;
+ p->fname = g_strdup(dirp->d_name);
+
+ p->interface = (PluginInterfaceVersionFunc)
+ load_sym(p->module, p->fname,
+ "plugin_interface_version",
+ FALSE);
+ p->start = (PluginStartupFunc)
+ load_sym(p->module, p->fname, "plugin_startup", FALSE);
+ p->stop = (PluginShutdownFunc)
+ load_sym(p->module, p->fname, "plugin_shutdown",FALSE);
+ p->getname = (PluginNameFunc)
+ load_sym(p->module, p->fname, "plugin_name", FALSE);
+ p->getpname = (PluginNameFunc)
+ load_sym(p->module, p->fname, "plugin_plugin_name",
+ FALSE);
+ p->icon = (PluginIconFunc)
+ load_sym(p->module, p->fname, "plugin_icon", FALSE);
+ p->toplevel = (PluginToplevelWidgetFunc)
+ load_sym(p->module, p->fname, "plugin_toplevel_widget",
+ FALSE);
+ p->edited = (PluginEditedFunc)
+ load_sym(p->module, p->fname, "plugin_edited", FALSE);
+ p->load = (PluginLoadFunc)
+ load_sym(p->module, p->fname, "plugin_load", FALSE);
+ p->save = (PluginSaveFunc)
+ load_sym(p->module, p->fname, "plugin_save", FALSE);
+
+ if (!(p->start &&
+ p->stop &&
+ p->interface &&
+ p->name &&
+ p->icon &&
+ p->toplevel &&
+ p->edited &&
+ p->load &&
+ p->save)) {
+ g_module_close(p->module);
+ g_free(p->fname);
+ g_free(p);
+ } else {
+ p->start();
+ p->name = p->getname();
+ p->plugin_name = p->getpname();
+ plugins_list = g_slist_append(plugins_list, p);
+
+ add_plugin(p); /* add to the gui */
+ }
+ }
+ g_free(fpath);
+ }
+ }
+ }
+
+ g_free(suffix);
+}
+
+void plugins_load()
+{
+ char *path;
+
+ path = g_build_filename(g_get_home_dir(), ".openbox", "plugins", NULL);
+ load_dir(path);
+ g_free(path);
+
+ load_dir(PLUGINDIR);
+}
+
+gboolean plugins_edited(ConfigPlugin *p)
+{
+ return p->edited();
+}
+
+void plugins_load_settings(ConfigPlugin *p, xmlDocPtr doc, xmlNodePtr root)
+{
+ p->load(doc, root);
+}
+
+void plugins_save_settings(ConfigPlugin *p, xmlDocPtr doc, xmlNodePtr root)
+{
+ p->save(doc, root);
+}