aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/elementary/src/lib/elm_module.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libraries/elementary/src/lib/elm_module.c251
1 files changed, 251 insertions, 0 deletions
diff --git a/libraries/elementary/src/lib/elm_module.c b/libraries/elementary/src/lib/elm_module.c
new file mode 100644
index 0000000..396e9de
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_module.c
@@ -0,0 +1,251 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4/* what are moodules in elementary for? for modularising behavior and features
5 * so they can be plugged in and out where you dont want the core source to
6 * always behave like that or do it that way. plug it at runtime!
7 *
8 * they have module names (in config) and "slots" to plug that module into
9 * to server a purpose. eg you plug plugin "xx" into the "entry-copy-paste"
10 * slot so it would provide replacement copy & paste ui functionality and
11 * specific symbols
12 *
13 * config is something like:
14 *
15 * export ELM_MODULES="xx>slot1:yy>slot2"
16 *
17 * where a module named xx is plugged into slot1 & yy is plugged into slot2
18 *
19 * real examples:
20 *
21 * export ELM_MODULES="my_module>entry/api"
22 *
23 * this loads the module called "my_module" into the slot "entry/api" which
24 * is an api slot for entry modules to modify behavior and hook to
25 * creation/deletion of the entry as well as replace the longpress behavior.
26 */
27
28#ifdef HAVE_CONFIG_H
29# include "elementary_config.h"
30#endif
31
32static Eina_Hash *modules = NULL;
33static Eina_Hash *modules_as = NULL;
34
35void
36_elm_module_init(void)
37{
38 modules = eina_hash_string_small_new(NULL);
39 modules_as = eina_hash_string_small_new(NULL);
40}
41
42void
43_elm_module_shutdown(void)
44{
45 // FIXME: unload all modules
46 if (modules) eina_hash_free(modules);
47 modules = NULL;
48 if (modules_as) eina_hash_free(modules_as);
49 modules_as = NULL;
50}
51
52void
53_elm_module_parse(const char *s)
54{
55 const char *p, *pe;
56
57 p = s;
58 pe = p;
59 for (;;)
60 {
61 if ((*pe == ':') || (!*pe))
62 { // p -> pe == 'name:'
63 if (pe > p)
64 {
65 char *n = malloc(pe - p + 1);
66 if (n)
67 {
68 char *nn;
69
70 strncpy(n, p, pe - p);
71 n[pe - p] = 0;
72 nn = strchr(n, '>');
73 if (nn)
74 {
75 *nn = 0;
76 nn++;
77 _elm_module_add(n, nn);
78 }
79 free(n);
80 }
81 }
82 if (!*pe) break;
83 p = pe + 1;
84 pe = p;
85 }
86 else
87 pe++;
88 }
89}
90
91Elm_Module *
92_elm_module_find_as(const char *as)
93{
94 Elm_Module *m;
95
96 m = eina_hash_find(modules_as, as);
97 if (!m) return NULL;
98
99 if (!_elm_module_load(m))
100 {
101 _elm_module_del(m);
102 return NULL;
103 }
104 return m;
105}
106
107Eina_Bool
108_elm_module_load(Elm_Module *m)
109{
110 const char *home;
111 char buf[PATH_MAX];
112
113 if (m->module) return EINA_TRUE;
114
115 home = getenv("HOME");
116 if (home)
117 {
118 snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/modules/%s/%s/module" EFL_SHARED_EXTENSION, home, m->name, MODULE_ARCH);
119 m->module = eina_module_new(buf);
120 if (m->module && eina_module_load (m->module) == EINA_TRUE)
121 {
122 m->init_func = eina_module_symbol_get(m->module, "elm_modapi_init");
123 if (m->init_func)
124 {
125 m->shutdown_func = eina_module_symbol_get(m->module, "elm_modapi_shutdown");
126 m->so_path = eina_stringshare_add(buf);
127 snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/modules/%s/%s", home, m->name, MODULE_ARCH);
128 m->bin_dir = eina_stringshare_add(buf);
129 snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/modules/%s", home, m->name);
130 m->data_dir = eina_stringshare_add(buf);
131 }
132 else
133 {
134 if (m->module)
135 {
136 eina_module_unload(m->module);
137 eina_module_free(m->module);
138 m->module = NULL;
139 }
140 return EINA_FALSE;
141 }
142 }
143 else if (m->module)
144 {
145 eina_module_free(m->module);
146 m->module = NULL;
147 }
148 }
149
150 if (!m->module)
151 {
152 snprintf(buf, sizeof(buf), "%s/elementary/modules/%s/%s/module" EFL_SHARED_EXTENSION, _elm_lib_dir, m->name, MODULE_ARCH);
153 m->module = eina_module_new(buf);
154 if (m->module && eina_module_load (m->module) == EINA_TRUE)
155 {
156 m->init_func = eina_module_symbol_get(m->module, "elm_modapi_init");
157 if (m->init_func)
158 {
159 m->shutdown_func = eina_module_symbol_get(m->module, "elm_modapi_shutdown");
160 m->so_path = eina_stringshare_add(buf);
161 snprintf(buf, sizeof(buf), "%s/elementary/modules/%s/%s", _elm_lib_dir, m->name, MODULE_ARCH);
162 m->bin_dir = eina_stringshare_add(buf);
163 snprintf(buf, sizeof(buf), "%s/elementary/modules/%s", _elm_lib_dir, m->name);
164 m->data_dir = eina_stringshare_add(buf);
165 }
166 else
167 {
168 if (m->module)
169 {
170 eina_module_unload(m->module);
171 eina_module_free(m->module);
172 m->module = NULL;
173 }
174 return EINA_FALSE;
175 }
176 }
177 }
178 else if (m->module)
179 {
180 eina_module_free(m->module);
181 m->module = NULL;
182 }
183
184 if (!m->module) return EINA_FALSE;
185 return EINA_TRUE;
186}
187
188void
189_elm_module_unload(Elm_Module *m)
190{
191 eina_stringshare_del(m->so_path);
192 eina_stringshare_del(m->data_dir);
193 eina_stringshare_del(m->bin_dir);
194 if (m->api)
195 {
196 free(m->api);
197 m->api = NULL;
198 }
199 if (m->module)
200 {
201 if (m->shutdown_func) m->shutdown_func(m);
202 eina_module_unload(m->module);
203 eina_module_free(m->module);
204 m->module = NULL;
205 }
206 m->shutdown_func = NULL;
207 m->init_func = NULL;
208}
209
210Elm_Module *
211_elm_module_add(const char *name, const char *as)
212{
213 Elm_Module *m;
214
215 if (name[0] == '/') return NULL;
216
217 m = eina_hash_find(modules, name);
218 if (m)
219 {
220 m->references++;
221 return m;
222 }
223 m = calloc(1, sizeof(Elm_Module));
224 if (!m) return NULL;
225 m->version = 1;
226 m->name = eina_stringshare_add(name);
227 m->references = 1;
228 eina_hash_direct_add(modules, m->name, m);
229 m->as = eina_stringshare_add(as);
230 eina_hash_direct_add(modules_as, m->as, m);
231 return m;
232}
233
234void
235_elm_module_del(Elm_Module *m)
236{
237 m->references--;
238 if (m->references > 0) return;
239 _elm_module_unload(m);
240 eina_hash_del(modules, m->name, m);
241 eina_hash_del(modules_as, m->as, m);
242 eina_stringshare_del(m->name);
243 eina_stringshare_del(m->as);
244 free(m);
245}
246
247const void *
248_elm_module_symbol_get(Elm_Module *m, const char *name)
249{
250 return eina_module_symbol_get(m->module, name);
251}