]> icculus.org git repositories - mikachu/openbox.git/blob - tools/obconf/plugins.c
make interactive actions a type and not special cases.
[mikachu/openbox.git] / tools / obconf / plugins.c
1 #include "obconf.h"
2 #include "plugins/obconf_interface.h"
3
4 #include <sys/types.h>
5 #include <dirent.h>
6 #include <string.h>
7 #include <gmodule.h>
8
9 typedef struct ConfigPlugin {
10     GModule *module;
11     char *fname;
12     char *name;
13     char *plugin_name;
14
15     PluginStartupFunc start;
16     PluginShutdownFunc stop;
17     PluginInterfaceVersionFunc interface;
18     PluginNameFunc getname;
19     PluginPluginNameFunc getpname;
20     PluginIconFunc icon;
21     PluginToplevelWidgetFunc toplevel;
22     PluginEditedFunc edited;
23     PluginLoadFunc load;
24     PluginSaveFunc save;
25 } ConfigPlugin;
26
27 GSList *plugins_list = NULL;
28
29 static gpointer load_sym(GModule *module, char *name, char *symbol,
30                          gboolean allow_fail)
31 {
32     gpointer var;
33     if (!g_module_symbol(module, symbol, &var)) {
34         if (!allow_fail)
35             g_warning("Failed to load symbol '%s' from plugin '%s'",
36                       symbol, name);
37         var = NULL;
38     }
39     return var;
40 }
41
42 static void add_plugin(ConfigPlugin *p)
43 {
44     GtkTreeIter it;
45
46     gtk_list_store_append(obconf_sections_store, &it);
47     gtk_list_store_set(obconf_sections_store, &it, 0, p->name, -1);
48     gtk_notebook_append_page(obconf_options, p->toplevel(), NULL);
49 }
50
51 void load_dir(char *path)
52 {
53     char *fpath;
54     DIR *dir;
55     struct dirent *dirp;
56     ConfigPlugin *p;
57     GModule *mod;
58     GSList *it;
59     char *suffix;
60
61     suffix = g_strconcat("-config.", G_MODULE_SUFFIX, NULL);
62
63     if (!(dir = opendir(path)))
64         return;
65     while ((dirp = readdir(dir))) {
66         if (g_strrstr(dirp->d_name, suffix)) {
67             /* look for duplicates */
68             for (it = plugins_list; it; it = it->next)
69                 if (!strcmp(((ConfigPlugin*)it->data)->fname, dirp->d_name))
70                     break;
71             if (!it) {
72                 fpath = g_build_filename(path, dirp->d_name, NULL);
73         
74                 if ((mod = g_module_open(fpath, 0))) {
75                     p = g_new(ConfigPlugin, 1);
76                     p->module = mod;
77                     p->fname = g_strdup(dirp->d_name);
78
79                     p->interface = (PluginInterfaceVersionFunc)
80                         load_sym(p->module, p->fname,
81                                  "plugin_interface_version",
82                                  FALSE);
83                     p->start = (PluginStartupFunc)
84                         load_sym(p->module, p->fname, "plugin_startup", FALSE);
85                     p->stop = (PluginShutdownFunc)
86                         load_sym(p->module, p->fname, "plugin_shutdown",FALSE);
87                     p->getname = (PluginNameFunc)
88                         load_sym(p->module, p->fname, "plugin_name", FALSE);
89                     p->getpname = (PluginNameFunc)
90                         load_sym(p->module, p->fname, "plugin_plugin_name",
91                                  FALSE);
92                     p->icon = (PluginIconFunc)
93                         load_sym(p->module, p->fname, "plugin_icon", FALSE);
94                     p->toplevel = (PluginToplevelWidgetFunc)
95                         load_sym(p->module, p->fname, "plugin_toplevel_widget",
96                                  FALSE);
97                     p->edited = (PluginEditedFunc)
98                         load_sym(p->module, p->fname, "plugin_edited", FALSE);
99                     p->load = (PluginLoadFunc)
100                         load_sym(p->module, p->fname, "plugin_load", FALSE);
101                     p->save = (PluginSaveFunc)
102                         load_sym(p->module, p->fname, "plugin_save", FALSE);
103
104                     if (!(p->start &&
105                           p->stop &&
106                           p->interface &&
107                           p->name &&
108                           p->icon &&
109                           p->toplevel &&
110                           p->edited &&
111                           p->load &&
112                           p->save)) {
113                         g_module_close(p->module);
114                         g_free(p->fname);
115                         g_free(p);
116                     } else {
117                         p->start();
118                         p->name = p->getname();
119                         p->plugin_name = p->getpname();
120                         plugins_list = g_slist_append(plugins_list, p);
121
122                         add_plugin(p); /* add to the gui */
123                     }
124                 }
125                 g_free(fpath);
126             }
127         }              
128     }
129
130     g_free(suffix);
131 }
132
133 void plugins_load()
134 {
135     char *path;
136
137     path = g_build_filename(g_get_home_dir(), ".openbox", "plugins", NULL);
138     load_dir(path);
139     g_free(path);
140
141     load_dir(PLUGINDIR);
142 }
143
144 gboolean plugins_edited(ConfigPlugin *p)
145 {
146     return p->edited();
147 }
148
149 void plugins_load_settings(ConfigPlugin *p, xmlDocPtr doc, xmlNodePtr root)
150 {
151     p->load(doc, root);
152 }
153
154 void plugins_save_settings(ConfigPlugin *p, xmlDocPtr doc, xmlNodePtr root)
155 {
156     p->save(doc, root);
157 }