make the openbox engine use the new config shit instead of the themerc shit.
[dana/openbox.git] / openbox / plugin.c
1 #include <glib.h>
2 #include <gmodule.h>
3
4 typedef void (*PluginStartup)();
5 typedef void (*PluginShutdown)();
6
7 typedef struct {
8     GModule *module;
9     char *name;
10
11     PluginStartup startup;
12     PluginShutdown shutdown;
13 } Plugin;
14
15 static gpointer load_sym(GModule *module, char *name, char *symbol)
16 {
17     gpointer var;
18     if (!g_module_symbol(module, symbol, &var)) {
19         g_warning("Failed to load symbol '%s' from plugin '%s'",
20                   symbol, name);
21         var = NULL;
22     }
23     return var;
24 }
25
26 static Plugin *plugin_new(char *name)
27 {
28     Plugin *p;
29     char *path;
30    
31     p = g_new(Plugin, 1);
32
33     path = g_build_filename(PLUGINDIR, name, NULL);
34     p->module = g_module_open(path, 0);
35     g_free(path);
36
37     if (p->module == NULL) {
38         path = g_build_filename(g_get_home_dir(), ".openbox", "plugins", name,
39                                 NULL);
40         p->module = g_module_open(path, 0);
41         g_free(path);
42     }
43
44     if (p->module == NULL) {
45         g_free(p);
46         return NULL;
47     }
48
49     p->startup = (PluginStartup)load_sym(p->module, name, "plugin_startup");
50     p->shutdown = (PluginShutdown)load_sym(p->module, name, "plugin_shutdown");
51
52     if (p->startup == NULL || p->shutdown == NULL) {
53         g_module_close(p->module);
54         g_free(p);
55         return NULL;
56     }
57
58     p->name = g_strdup(name);
59     return p;
60 }
61
62 static void plugin_free(Plugin *p)
63 {
64     p->shutdown();
65
66     g_free(p->name);
67     g_module_close(p->module);
68 }
69
70
71 static GData *plugins = NULL;
72
73 void plugin_startup()
74 {
75     g_datalist_init(&plugins);
76 }
77
78 void plugin_shutdown()
79 {
80     g_datalist_clear(&plugins);
81 }
82
83 gboolean plugin_open(char *name)
84 {
85     Plugin *p;
86
87     if (g_datalist_get_data(&plugins, name) != NULL) {
88         g_warning("plugin '%s' already loaded, can't load again", name);
89         return TRUE;
90     }
91
92     p = plugin_new(name);
93     if (p == NULL) {
94         g_warning("failed to load plugin '%s'", name);
95         return FALSE;
96     }
97     /* XXX p->plugin_set_config(); */
98
99     g_datalist_set_data_full(&plugins, name, p,  (GDestroyNotify) plugin_free);
100     return TRUE;
101 }
102
103 void plugin_close(char *name)
104 {
105     g_datalist_remove_data(&plugins, name);
106 }
107
108 static void foreach_start(GQuark key, Plugin *p, gpointer *foo)
109 {
110     p->startup();
111 }
112
113 void plugin_startall()
114 {
115     g_datalist_foreach(&plugins, (GDataForeachFunc)foreach_start, NULL);
116 }
117
118 void plugin_loadall()
119 {
120     GIOChannel *io;
121     GError *err;
122     char *path, *name;
123
124     path = g_build_filename(g_get_home_dir(), ".openbox", "pluginrc", NULL);
125     err = NULL;
126     io = g_io_channel_new_file(path, "r", &err);
127     g_free(path);
128
129     if (io == NULL) {
130         path = g_build_filename(RCDIR, "pluginrc", NULL);
131         err = NULL;
132         io = g_io_channel_new_file(path, "r", &err);
133         g_free(path);
134     }
135
136     if (io == NULL) {
137         /* load the default plugins */
138         plugin_open("focus");
139         plugin_open("keyboard");
140         plugin_open("mouse");
141         plugin_open("placement");
142         plugin_open("resistance");
143     } else {
144         /* load the plugins in the rc file */
145         while (g_io_channel_read_line(io, &name, NULL, NULL, &err) ==
146                G_IO_STATUS_NORMAL) {
147             plugin_open(name);
148             g_free(name);
149         }
150         g_io_channel_unref(io);
151     }
152 }